计算机网络(第四弹) --- TCP 套接字编程的通信模型及实现流程

TCP 套接字编程

  • 1 流套接字通信流程
  • 2 TCP 流套接字编程
  • 3 注意事项
  • 4 关于长短连接的理解
    • 4.1 概念
    • 4.2 区别

1 流套接字通信流程

计算机网络(第四弹) --- TCP 套接字编程的通信模型及实现流程_第1张图片

2 TCP 流套接字编程

这里我们简单写一个回显服务器当做 来解读流套接字编程用到的方法和逻辑, ServletSocket 是创建 TCP 服务端 Socket 的 API, 主要处理客户端的连接, Socket 主要用来和客户端进行具体的交互, 这里还需要注意 TCP 协议有连接, 类似于打电话; 此处我们实现的是一个长连接版本的服务器, 关于长连接和短连接的区别, 后面会解释.
服务端代码如下:

public class TcpEchoServer {
    private ServerSocket serverSocket = null;
    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void star() throws IOException {
        System.out.println("服务器启动啦!");
        while (true) {
            Socket clientSocket = serverSocket.accept();
            processConnection(clientSocket);
        }
    }

    private void processConnection(Socket clientSocket) {
        System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress().toString(),
                clientSocket.getPort());
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
             BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()))) {
            while (true) {
                String request = bufferedReader.readLine();
                bufferedWriter.write(reponse + "\n");
                bufferedWriter.flush();
                System.out.printf("[%s:%d] req: %s; resp: %s\n",clientSocket.getInetAddress().toString(),
                        clientSocket.getPort(), request,reponse);
            }
        } catch (IOException e) {
            System.out.printf("[%s:%d] 客户端下线\n",clientSocket.getInetAddress().toString(),
                    clientSocket.getPort());
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.star();
    }
}

代码流程解读:
计算机网络(第四弹) --- TCP 套接字编程的通信模型及实现流程_第2张图片
客户端代码如下:

public class TcpEchoClient {
    private Socket socket = null;
    public TcpEchoClient (String serverIp, int serverPort) throws IOException {
        socket = new Socket(serverIp,serverPort);
    }
    
    public void start() {
        System.out.println("客户端启动了!");
        Scanner scanner = new Scanner(System.in);
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))){
            while (true) {
                System.out.println("--> ");
                String request = scanner.nextLine();
                if("exit".equals(request)) {
                    break;
                }
                bufferedWriter.write(request + "\n");
                bufferedWriter.flush();
                String response = bufferedReader.readLine();
                System.out.println(response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient client = new TcpEchoClient("127.0.0.1",9090);
        client.start();
    }
}

代码流程解读:
计算机网络(第四弹) --- TCP 套接字编程的通信模型及实现流程_第3张图片
运行结果:
计算机网络(第四弹) --- TCP 套接字编程的通信模型及实现流程_第4张图片

3 注意事项

  • TCP 的连接管理是由操作系统内核来管理的, 整体思路就是先描述, 再组织; 描述的主要是通信中的五元组 / 协议类型 / 源 IP 端口 / 目的 IP 端口等, 组织主要是使用一个阻塞队列来组织若干个连接对象;
  • 客户端和服务器建立连接的过程, 完全由内核来进行负责, 应用程序的代码是感知不到的, 当建立成功之后, 内核已经把这个连接对象放到了阻塞队列中了;
  • 代码中的 accept 就是从阻塞队列中取出一个连接对象, 在应用程序中的化身就是 Socket 对象;
  • 如果服务器启动之后么, 没有客户端建立连接, 此时代码中调用 accept 就会阻塞, 阻塞到真正有客户端建立连接为止;
  • 其实这就是一个生产者消费者模型, 后续针对数据的读写都是针对 clientSocket 这个对象进行展开的.

4 关于长短连接的理解

4.1 概念

  • 短连接: 一个连接中, 客户端和服务器之间只交互一次, 交互完毕就断开连接; 每次接收到数据并返回响应后, 都关闭连接;
  • 长连接: 一个连接中, 客户端和服务器之间交互 n 次, 直到满足一定的条件才断开, 因此长连接的效率会更高, 会避免反复建立连接和断开连接的过程; 总之, 不关闭连接, 一直保持连接状态, 双方不停的收发数据.

4.2 区别

  • 建立连接 / 关闭连接的耗时方面: 短连接每次请求 / 响应都需要建立连接 / 关闭连接; 而长连接只需要第一次建立连接, 之后的请求 / 响应都可以直接传输, 相对来说建立连接/ 关闭连接也是耗时的, 长连接的效率更高;
  • 主动发送请求方面: 短连接一般是客户端主动向服务器端发送请求; 而长连接可以是客户端主动发送请求, 也可以是服务端主动发;
  • 使用场景方面: 短连接适用于客户端请求频率不高的场景, 如浏览网页等; 而长连接适用于客户端与服务器端通信频率频繁的场景, 微信聊天就是长连接的场景.

你可能感兴趣的:(计算机网络,Java,tcp/ip,计算机网络,网络)