在通过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
//存储tcp服务端口对应的服务端本身
public static Map
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
clientSocketMapList.put(port,new ArrayList<>());
serverSocketMap.put(port,serverSocket);
// 永久循环以接受多个客户端连接
while (true) {
// 监听并接受客户端的连接请求,accept会将socket挂起
Socket clientSocket = serverSocket.accept();
List
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
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
clientSocketMapList.put(port,new ArrayList<>());
serverSocketMap.put(port,serverSocket);
// 永久循环以接受多个客户端连接
while (true) {
// 监听并接受客户端的连接请求,accept会将socket挂起
Socket clientSocket = serverSocket.accept();
List
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
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
for (Socket socket : sockets) {
socket.close();
}
clientSocketMapList.remove(port);
serverSocketMap.get(port).close();
serverSocketMap.remove(port);
}
}
测试工具