java对ServerSocket的开启和关闭

文章讲述了在Java中使用TCP服务端处理客户端信息时遇到的问题,如服务端只能处理第一个客户端的数据,以及关闭服务端后客户端仍能发送数据。作者提供了使用多线程和正确关闭Socket的方法来解决这些问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在通过tcp对接数据的时候,使用java创建tcp服务端来接收客户端的信息处理数据时发现的问题和解决办法

1.服务端虽然可以连接多个客户端,缺只能处理第一个客户端的信息

2.服务端关闭时,客户端依然可以发送数据

解决办法

1.因为当第一个客户端连接之后,服务端会一直读取数据造成阻塞,所有只能第一个客户端主动断开连接之后才能处理下一个客户端数据,我们可以用多线程的方式来同时处理多个客户端连接的信息

2.当我们在java程序中close掉serverSocket时,客户端依然会显示连接中,并且可以发送数据,其中是因为流有缓存,我们必须先主动关掉serverSocket.accept()获取到的socket,再关闭serverSocket

下面是整个代码

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author: zrl
 * @create-date: 2024/2/26 14:47
 */
public class TcpService {
    //存储tcp服务端口对应的所有客户端
    public static Map<Integer,List<Socket>> clientSocketMapList=new HashMap();
    //存储tcp服务端口对应的服务端本身
    public static Map<Integer,ServerSocket> serverSocketMap=new HashMap<>();
    public static void main(String[] args) throws IOException, InterruptedException {
        new Thread(() -> {
            try {
                openTcpByByte(8881);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                openTcpByByte(8882);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
        //测试延迟10秒自动关闭
        Thread.sleep(10000);
        closeTcpService(8881);
        closeTcpService(8882);
    }

    public static void openTcpByByte(int port) throws IOException {
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("tcp" + port + "端口启动成功,等待客户端连接...");
        //初始化List<Socket>对象         
        clientSocketMapList.put(port,new ArrayList<>());
        serverSocketMap.put(port,serverSocket);
        // 永久循环以接受多个客户端连接
        while (true) {
            // 监听并接受客户端的连接请求,accept会将socket挂起
            Socket clientSocket = serverSocket.accept();
            List<Socket> sockets = clientSocketMapList.get(port);
            sockets.add(clientSocket);
            clientSocketMapList.put(port,sockets);
            System.out.println(clientSocket.getPort()+"客户端连接成功!");
            //实时的tcp所有的客户端连接信息
            System.out.println(clientSocketMapList);
            InputStream inputStream = null;
            try {
                inputStream = clientSocket.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            byte[] data = new byte[1024];
            InputStream finalInputStream = inputStream;
            new Thread(() -> {
                int len = 0;
                while (true) {
                    try {
                        //finalBr.read中的read方法会阻塞,直到客户端关闭
                        if ((len = finalInputStream.read(data)) == -1) break;
                    } catch (IOException e) {
                        e.printStackTrace();
                        //强制关闭所有的tcp客户端连接,关闭的时候流读取不到数据会报错,捕捉异常后break
                        break;
                    }
                    String value = new String(data, 0, len);
                    System.out.println(value);
                }
                Iterator<Socket> iterator = sockets.iterator();
                while(iterator.hasNext()) {
                    if(iterator.next().getPort()==clientSocket.getPort()) {
                        iterator.remove();
                    }
                }
                //实时的tcp所有的客户端连接信息
                System.out.println(clientSocketMapList);
            }).start();
        }
    }

    public static void openTcpByChar(int port) throws IOException {
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("tcp" + port + "端口启动成功,等待客户端连接...");
        //初始化List<Socket>对象 
        clientSocketMapList.put(port,new ArrayList<>());
        serverSocketMap.put(port,serverSocket);
        // 永久循环以接受多个客户端连接
        while (true) {
            // 监听并接受客户端的连接请求,accept会将socket挂起
            Socket clientSocket = serverSocket.accept();
            List<Socket> sockets = clientSocketMapList.get(port);
            sockets.add(clientSocket);
            clientSocketMapList.put(port,sockets);
            System.out.println(clientSocket.getPort()+"客户端连接成功!");
            //实时的tcp所有的客户端连接信息
            System.out.println(clientSocketMapList);
            InputStream inputStream = null;
            try {
                inputStream = clientSocket.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            char[] data = new char[1024];
            InputStreamReader finalBr = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
            new Thread(() -> {
                int len = 0;
                while (true) {
                    try {
                        //finalBr.read中的read方法会阻塞,直到客户端关闭
                        if ((len = finalBr.read(data)) == -1) break;
                    } catch (IOException e) {
                        e.printStackTrace();
                        //强制关闭所有的tcp客户端连接,关闭的时候流读取不到数据会报错,捕捉异常后break
                        break;
                    }
                    String value = new String(data, 0, len);
                    System.out.println(value);
                }
                Iterator<Socket> iterator = sockets.iterator();
                while(iterator.hasNext()) {
                    if(iterator.next().getPort()==clientSocket.getPort()) {
                        iterator.remove();
                    }
                }
                //实时的tcp所有的客户端连接信息
                System.out.println(clientSocketMapList);
            }).start();
        }
    }

    public static void closeTcpService(int port) throws IOException {
        List<Socket> sockets = clientSocketMapList.get(port);
        for (Socket socket : sockets) {
            socket.close();
        }
        clientSocketMapList.remove(port);
        serverSocketMap.get(port).close();
        serverSocketMap.remove(port);
    }
}

测试工具

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值