Java网络编程(已经over了)

网络编程时代几乎是结束了,主要目的是为了阐述网络擦欧做的过程,因为这些过程,将直接影响到Java EE的项目开发

1. 网络编程(简介)

网络:是将物理上分开的主机进行连接所形成的交换区域
所谓的网络编程指的就是服务器端与客户端编程的开发操作实现。但是在我们实际的工作下对网络的编程有两种形式:

  • 形式一:C/S结构(Client/Server)此类模式的开发一般要编写两套程序,一端属于客户端代码,一端是服务器代码,这样程序的开发非常的麻烦,因为我们要维护两套程序的使用,但是这类程序有一点好处就是安全性高。因为使用的是自己的连接端口和通讯协议。
  • 形式二:B/S结构(Browser/Server)不再单独开发客户端代码,只开发一套服务器端程序,客户端将利用浏览器进行访问,这种模式只需要开发一套程序,因为使用的是一套公共的HTTP协议以及公共的80端口,安全性不高,所以做的时候会对数据进行加密处理。

本篇指的是C/S开发,这样的程序也称为Socket程序,对于C/S结构的程序分为两类:

  • TCP程序:是采用可靠的连接方式进行的传输
  • UDP程序:不可靠的连接,属于数据报的协议

2.网络编程(基本实现)

如果要进行网络程序的开发,那么最为核心的两个类:

  • 服务器类:ServerSocket,主要工作在服务器端用于接收工作的请求
  • 客户端类:Socket, 每一个连接到服务器上的用户都通过Socket表示
定义服务器端——主要使用ServerSocket
  • 构造方法:public ServerSocket(int port)throws IOException,设置监听端口;(把所有端口都关闭了,电脑是最安全的,所谓的防火墙也是针对端口进行拦截)
  • 接受客户端连接:public Socket accept()throws IOException
  • 取得客户端的输出功能:Socket类定义方法public InputStream getInputStream()throws IOExceptionpublic OutputStreamgetOutputStream()throws IOException客户端的输入信息和客户端的输出信息
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public  class Main {//主类

     public static void main(String args[]) throws Exception {
         ServerSocket server = new ServerSocket(9999);
         //所有的服务器必须有端口
         System.out.println("等待客户端连接");
         Socket client= server.accept();//等待客户端连接,如果没有连接上一直等待
         //OutputStream并不方便输出,所以利用打印流输出
         PrintStream out  = new PrintStream(client.getOutputStream());
         out.println("Hello World!");//不加换行Scanner就可能读不到了
         
         out.close();
         client.close();
         server.close();
     }

 }

此时的服务器端只是输出一个HelloWorld的字符串,然后就关闭服务器操作只能够处理一次客户端的请求。

编写客户端——主要使用Socket
  • 构造方法:public Socket(String host, int port) throws UnknownHostException,IOException接收主机:就是你的IP地址,如果是本机直接访问,那么使用localhost(127.0.0.1)代替IP,后面是端口
  • 得到输入数据:public InputStream getInputStream() throws IOException
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Scanner;

public class HelloClient {
    public static void main(String args[])throws Exception{
        Socket client =new Socket("localhost",9999);
        //表示连接服务器端了
        //取得客户端的输入数据流对象,表示接收服务器端的输出信息
        Scanner scan = new Scanner(client.getInputStream());
        scan.useDelimiter("\n");
        if(scan.hasNext()){
            System.out.println("回应数据:"+scan.next());
        }
        scan.close();
        client.close();
    }
}

客户端现在也只是连接一次服务器,并且接受输入数据输出后结束操作在这里插入图片描述
在这里插入图片描述
在终端执行HelloClient之后,原来一直wait的服务器端口结束执行,客户端输出Hello World!
这是一个最简单的C/S模型,要想连接光有主机不够还要有端口,Socket是客户端。

3.网络编程(Echo模型)

在网络编程之中ECHO是一个经典的程序开发模型,本程序的意义在于:客户端随意输入信息,并且将信息发送给服务器端,服务器端接收后,前面加一个“ECHO:”的标记返回。在这里插入图片描述
在中端也有一个Echo操作,输入什么输出什么。
本程序设计如下:

  • 由于需要采用多次输入的模式,所以不能够每次连接后就立刻关闭服务器端
  • 可以设置一个字符串,eg:byebye,那么才表示结束本次的操作

实现服务器端

import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.ServerSocketChannel;
import java.rmi.ServerError;
import java.util.Scanner;

public  class Main {//主类

     public static void main(String args[]) throws Exception {
         ServerSocket server = new ServerSocket(9999);
         Socket client = server.accept();//连接客户端
        //客户端输入数据以及向客户端输出数据的对象
         Scanner scan = new Scanner(client.getInputStream());//
         PrintStream out = new PrintStream(client.getOutputStream());//向客户端输出信息
         
         boolean flag=true;//控制多次接收操作
         while (flag){
             if(scan.hasNext())
             {
                 String str = scan.next().trim();//得到客户端发送的内容,trim忽略前后空格
                 //但是问题是它发送的内容有可能有空格
                 if(str.equalsIgnoreCase("byebye")){//表示程序要结束
                     out.println("see you next time");
                     flag = false;//表示退出这个循环
                 }
                 else {
                     out.println("ECHO:"+str);
                 }
             }
         }
         client.close();//客观来讲把客户端关闭实际上就把所有的都关闭了
         server.close();
         scan.close();
         out.close();
       
     }

 }

服务器端实现了循环操作

实现客户端

import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Scanner;

public class HelloClient {
    public static void main(String args[])throws Exception{
        Socket client =new Socket("localhost",9999);
        //表示连接服务器端了
        //取得客户端的输入数据流对象,表示接收服务器端的输出信息
        Scanner input = new Scanner(System.in);//键盘输入数据
        input.useDelimiter("\n");
        Scanner scan = new Scanner(client.getInputStream());
        scan.useDelimiter("\n");
        PrintStream out = new PrintStream(client.getOutputStream());
        boolean flag = true;
        while(flag){
            System.out.print("请输入要发送数据:");
            if(input.hasNext()){
                String str = input.next().trim();
                out.println(str);//向服务器端发送数据,无论什么数据都要给服务器端发送
                if(str.equalsIgnoreCase("byebye")){
                   flag = false;//结束循环
                }
                else {
                    if(scan.hasNext())
                    System.out.println(scan.next());//输出回应数据
                }
            }
        }

        scan.close();
        client.close();
        scan.close();
        input.close();
        out.close();
    }
}


此时再开一个终端无法运行,就实现了一个最简单的服务器端与客户端通讯!
此时只能连接一个客户端,因为我们所有的操作都是在主线程上进行的开发,此时的程序属于单线程的网络应用,世纪中不可能如此进行,所以为了让一个服务器端能够为多个客户端服务,使用多线程描述。把每个连接到服务器端的客户都作为一个独立的线程对象保留。

服务器端

package com.company;


import javax.print.attribute.standard.OrientationRequested;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.ServerSocketChannel;
import java.rmi.ServerError;
import java.util.Scanner;

public  class Main {//主类

     public static void main(String args[]) throws Exception {
         ServerSocket server = new ServerSocket(9999);
         Socket client = server.accept();//连接客户端
        //客户端输入数据以及向客户端输出数据的对象
         Scanner scan = new Scanner(client.getInputStream());//
         PrintStream out = new PrintStream(client.getOutputStream());//向客户端输出信息

         boolean flag=true;//控制多次接收操作
         while (flag){
             if(scan.hasNext())
             {
                 String str = scan.next().trim();//得到客户端发送的内容,trim忽略前后空格
                 //但是问题是它发送的内容有可能有空格
                 if(str.equalsIgnoreCase("byebye")){//表示程序要结束
                     out.println("see you next time");
                     flag = false;//表示退出这个循环
                 }
                 else {
                     out.println("ECHO:"+str);
                 }
             }
         }
         client.close();//客观来讲把客户端关闭实际上就把所有的都关闭了
         server.close();
         scan.close();
         out.close();

     }

 }

客户端

import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Scanner;

public class HelloClient {
    public static void main(String args[])throws Exception{
        Socket client =new Socket("localhost",9999);
        //表示连接服务器端了
        //取得客户端的输入数据流对象,表示接收服务器端的输出信息
        Scanner input = new Scanner(System.in);//键盘输入数据
        Scanner scan = new Scanner(client.getInputStream());
        input.useDelimiter("\n");
        scan.useDelimiter("\n");
        PrintStream out = new PrintStream(client.getOutputStream());
        boolean flag = true;
        while(flag){
            System.out.print("请输入要发送数据:");
            if(input.hasNext()){
                String str = input.next().trim();
                out.println(str);//向服务器端发送数据,无论什么数据都要给服务器端发送
                if(str.equalsIgnoreCase("byebye")){
                   flag = false;//结束循环
                }
                if(scan.hasNext())
                    System.out.println(scan.next());//输出回应数据

            }
        }


        input.close();
        scan.close();
        out.close();
        client.close();
    }
}


在这里插入图片描述
但是现在面临着一个问题就是如果我输出what are中间有空格的话,他就会把数据保存在流中,然后一个一个的输出,比如上面的输出,what are输出之后,会先返回what但是你第二次再次输入一个数据他返回的就是are而不是你第二次输入的数据,因为在一开始写的时候就是简单的只能是一个单词的形式。

下面的是多线程写法:
修改服务器端

package com.company;


import javax.print.attribute.standard.OrientationRequested;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.ServerSocketChannel;
import java.rmi.ServerError;
import java.util.Scanner;

class EchoThread implements  Runnable{
  private Socket client;
  public EchoThread(Socket client){
      this.client=client;
  }
    @Override
    public void run() {
        try{//客户端输入数据以及向客户端输出数据的对象
        Scanner scan = new Scanner(client.getInputStream());//
        PrintStream out = new PrintStream(client.getOutputStream());//向客户端输出信息

        boolean flag=true;//控制多次接收操作
        while (flag){
            if(scan.hasNext())
            {
                String str = scan.next().trim();//得到客户端发送的内容,trim忽略前后空格
                //但是问题是它发送的内容有可能有空格
                if(str.equalsIgnoreCase("byebye")){//表示程序要结束
                    out.println("see you next time");
                    flag = false;//表示退出这个循环
                }
                else {
                    out.println("ECHO:"+str);
                }
            }
        }

        scan.close();
        out.close();
        client.close();}
        catch (Exception e){
            e.printStackTrace();
        }
    }
}
public  class Main {//主类
//每一个客户端进来之后都启动一个专门的线程进行此客户端的处理,此时的服务器端就可以支持多个用户的访问
     public static void main(String args[]) throws Exception {
         ServerSocket server = new ServerSocket(9999);
         boolean flag = true;
         while (flag) {
             Socket client = server.accept();//连接客户端
             new Thread(new EchoThread(client)).start();
         }
         //client.close();//客观来讲把客户端关闭实际上就把所有的都关闭了
         server.close();
     }

 }

在这里插入图片描述
服务器开发的基础要素:网络支持类、IO、多线程。
还要考虑很多情况比如线程间的通讯、资源同步(死锁)

总结

很少会进行实际开发了,所以了解一下基本概念就可以了,但至少可以通过代码看出多线程的特点和好处

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值