首页 > 编程语言 >java对ServerSocket的开启和关闭

java对ServerSocket的开启和关闭

时间:2024-03-15 13:32:32浏览次数:29  
标签:java iterator 开启 连接 ServerSocket new clientSocketMapList port 客户端

在通过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 {
    public static Map<Integer,List<Socket>> clientSocketMapList=new HashMap();
    public static Map<Integer,ServerSocket> serverSocketMap=new HashMap<>();
    public static void main(String[] args) throws IOException, InterruptedException {
        //初始化List<Socket>对象
        clientSocketMapList.put(8881,new ArrayList<>());
        new Thread(() -> {
            try {
                openTcpByByte(8881);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
        clientSocketMapList.put(8882,new ArrayList<>());
        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 + "端口启动成功,等待客户端连接...");
        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 + "端口启动成功,等待客户端连接...");
        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();
        }
        serverSocketMap.get(port).close();
    }
}

测试工具

标签:java,iterator,开启,连接,ServerSocket,new,clientSocketMapList,port,客户端
From: https://blog.csdn.net/weixin_59331533/article/details/136734858

相关文章

  • 安卓Java面试题 171- 180
    171.简述实现Service不被杀死常驻内存的方式有哪些?(1):如果是安卓自身机制因为系统资源不足的时候杀死你的Service,那么一般情况下会在一段时间之后系统会重启刚刚被杀死的Service那么此时你该做的事就是怎么恢复Service被杀之前app的一些状态了,那么该怎么恢复呢?这里用......
  • Java毕业设计-基于springboot开发的4S店车辆管理系统-毕业论文+答辩PPT(附源代码+演示
    文章目录前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1.开发说明2.需求分析3、系统功能结构三、系统实现展示1、系统登录2、管理员功能模块3、销售员功能模块4、维修员功能模块四、毕设内容和源代码获取总结Java毕业设计-基于springboot开发的4S店车辆管理系......
  • 为什么Java不支持多继承
    1、典型回答在Java语言中,不支持多继承的主要原因是为了简化语言设计和避免潜在的问题(如菱形继承)以及避免多重继承的层次膨胀,同时又因为在实际工作中,确实很少用到多继承,所以在Java语言中,并不支持多继承。而且,虽然Java中不支持多继承,但也给了一些功能上的替代方案,比如实现多......
  • java实现论文查重
    这个作业属于哪个课程软件工程2024这个作业要求在哪里个人项目个人gitte地址https://gitee.com/zcan86/zcan86PSP2.1PersonalSoftwareProcessStages预估耗时(分钟)实际耗时(分钟)Planning计划6060·Estimate·估计这个任务需要多少时间606......
  • 人工智能时代,Java从业者必学科目:数据机构和算法,以及AI算法和技能
    【晋升攻略】Java开发者的AI时代高薪加速器在AI时代,Java从业者必学的科目包括数据结构与算法、AI算法和相关技能,这是因为这些知识和技能是构建和发展人工智能应用的基础。具体分析如下:1.数据结构与算法:数据结构和算法是计算机科学的核心,对于编写高效、可维护的代码至关重......
  • Java-IoUtil扩展工具类
    现在记录下IO扩展支持importlombok.extern.slf4j.Slf4j;importorg.apache.commons.lang3.StringUtils;importjava.io.*;importjava.util.HashMap;@Slf4jpublicclassTyIoUtil{//缓存文件头信息-文件头信息publicstaticfinalHashMap<String,String>......
  • vs关于窗体的应用程序如何开启控制台窗口的方式
    方式一:(推荐)属性->生成后事件添加以下指令:editbin/SUBSYSTEM:CONSOLE$(OutDir)$(ProjectName).exe方式二:(动态方式)//分配一个新的控制台窗口 AllocConsole(); SetConsoleTitle(("DebugOutput"</......
  • 学习Java的第十天
    本章来讲一下什么是字符串一、什么是字符串在Java中,最常见的基本类型就是字符串了,哪哪都能见到,如输入语句,输出语句等!那么,什么是字符串呢,字符串就是String类,String类是Java中表示字符串的类。它是不可变的,一旦创建了一个字符串对象,就无法修改它。二、String类和StringBuilde......
  • 授之以渔不是授之以鱼-docker maven 构建java工程
    原始的maven构建语句mvncleaninstall-Dmaven.test.skip=true现在需要在一台新的安装有docker的机子上构建,要求用jdk17和maven3.9,这台机子较旧,只有jdk8和jdk11,但是有安装docker,在不动构建机器现有软件的情况下构建。dockerrun\--rm\-v$(pwd):$(pwd)......
  • Java中实现单例(Singleton)模式的八种方式
    单例模式定义单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。基本的实现思路单例模式要求类能够有返回对象一个引用(永远是同一个)和一个获得该实......