每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

Java Tcp通信

1. TCP通信原理

TCP(Transmission Control Protocol)协议是面向链接的通信协议,即 数据传输之前,先在发送端和接收端建立逻辑链接,然后再传输数据,它提供 了两台计算机之间可靠无差错的数据传输。

TCP通信中必须明确客户端和服务器端,由客户端向服务端发送连接请求 每次连接的创建都要经过三次握手。

三次握手:

  第一次握手:客户端向服务端发出连接请求,等待服务器确认。

  第二次握手:服务端向客户端回复一个响应,通知客户端收到连接请求

  第三次握手:客户端再次向服务端发送确认信息,确认连接 完成三次握手之后,连接建立,客户端和服务端开始进行数据传输,可以 保证数据安全。 数据传输结束以后,断开连接会进行四次挥手。

四次挥手:

  第一次挥手:客户端向服务端发送断开连接请求,表示数据发送完毕。

  第二次挥手:服务端收到请求后,回复客户端,同意关闭连接的请求。

  第三次挥手:服务端向客户端发出断开连接的请求。

  第四次挥手:客户端收到服务端请求后,向服务端发送确认信息,服务端接收 到确认信息后断开连接。客户端等待之后没有收到服务端的回复,证明服务端 已正常关闭,客户端也关闭。

2. TCP发送数据

发送数据的步骤:

  1、创建客户端Socket对象

  2、获取输出流,写入数据

  3、释放资源

3. TCP接收数据

接收数据的步骤:

  1、创建服务端的Socket对象

  2、监听客户端连接,返回Socket对象

  3、获取输入流读取数据

  4、释放资源

4. TCP通信案例

tcp实现服务端接收多个客户端消息,原理:主线程使用while死循环接收socket连接,为每个客户端的socket通信管道分配一个子线程接收

4.1 服务器端代码

package Tcp通信;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TcpServer {

    public static void main(String[] args) {
        try {
            // 1.创建服务端的ServerSocket对象,注册端口
            ServerSocket serverSocket = new ServerSocket(10086);
            System.out.println("----服务端启动成功了----");

            // 2.定义一个死循环由主线程负责不断接收客户端的socket管道连接
            while (true) {
                Socket socket = serverSocket.accept();

                // 3.读取客户端发送的消息
                ThreadUtil.execute(() -> {
                    try {
                        System.out.println("客户端:" + socket.getRemoteSocketAddress() + " 成功连接到服务器");
                        while (true) {
                            // 4.从Socket通信管道中得到一个字节输入流
                            InputStream inputStream = socket.getInputStream();

                            // 5.把字节输入流包装成缓冲字符输入流进行消息的接收
                            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

                            // 6.按照行读取消息
                            String message = bufferedReader.readLine();
                            if (StrUtil.isNotEmpty(message)) {
                                System.out.println("接收到客户端:" + socket.getRemoteSocketAddress() + ",发送的信息:" + message);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });

                // 向客户端发送消息
                ThreadUtil.execute(() -> {
                    try {
                        System.out.println("请输入发送的信息:");
                        while (true) {
                            Scanner scanner = new Scanner(System.in);
                            String message = scanner.next();
                            if (StrUtil.isNotEmpty(message)) {
                                // 2.从Socket通信管道中得到一个字节输出流,负责发送数据
                                OutputStream outputStream = socket.getOutputStream();

//                                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));
//                                bw.write(message + "\n");
//                                bw.flush();

                                // 把低级的字节流包装成打印流
                                PrintStream ps = new PrintStream(outputStream);
                                ps.println(message);
                                ps.flush();
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

4.2 客户端端代码

package Tcp通信;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class TcpClient {

    public static void main(String[] args) {
        try {
            // 1.创建Socket通信管道请求有服务端的连接,端口号为 10086
            Socket socket = new Socket("127.0.0.1", 10086);
            System.out.println(socket.getLocalPort() + " :客户端启动成功了");

            // 读取服务器发送的消息
            ThreadUtil.execute(() -> {
                try {
                    while (true) {
                        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        String message = br.readLine();
                        if (StrUtil.isNotEmpty(message)) {
                            System.out.println("接收到服务端:" + socket.getRemoteSocketAddress() + ",发送的信息:" + message);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });

            // 向服务器发送消息
            ThreadUtil.execute(() -> {
                try {
                    System.out.println("请输入发送的信息:");
                    while (true) {
                        Scanner scanner = new Scanner(System.in);
                        String message = scanner.nextLine();
                        if (StrUtil.isNotEmpty(message)) {
                            // 2.从Socket通信管道中得到一个字节输出流,负责发送数据
                            OutputStream outputStream = socket.getOutputStream();

//                            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));
//                            bw.write(message + "\n");
//                            bw.flush();

                            // 把低级的字节流包装成打印流
                            PrintStream ps = new PrintStream(outputStream);
                            ps.println(message);
                            ps.flush();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

4.3 通信测试

4.3.1 启动服务端

4.3.2 启动客户端,服务端显示连接成功

4.3.3 客户端给服务端发送信息,服务端收到信息

 

4.3.4 服务端给客户端发送信息,客户端收到信息

 

posted @ 2022-07-21 13:21  helloliyh  阅读(721)  评论(0编辑  收藏  举报