关于TCP长连接的服务端
转载一个地址,简单理解一下TCP长连接和短链接
https://blog.csdn.net/zxy987872674/article/details/52653101
下面直接上本次代码做记录
//TCP建立连接并接收信息service
package d1.project.sample.service;
import d1.project.sample.dao.DustDao;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author missoul
*/
@Service
public class TcpRunner implements CommandLineRunner {
private final DustDao dustDao;
public TcpRunner(DustDao dustDao) {
this.dustDao = dustDao;
}
@Override
public void run(String... args) throws Exception {
ServerSocket server = new ServerSocket(8091);
System.out.println("监听端口:" + 8091);
ThreadPoolExecutor pool = new ThreadPoolExecutor(
40,
200,
50,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(50),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
while (true) {
//循环接收不同地址发来的请求,每一个请求单独拉出一个线程处理
Socket socket = server.accept();
pool.execute(new ServerConfig(dustDao, socket));
}
}
}
//代码中使用线程池对TCP长连接进行处理
//处理socket接收到的信息
package d1.project.sample.service;
import d1.project.sample.dao.DustDao;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
/**
* @author missoul
*/
public class ServerConfig extends Thread {
private final DustDao dustDao;
public Socket socket;
public ServerConfig(DustDao dustDao, Socket socket) {
this.dustDao = dustDao;
this.socket = socket;
}
private boolean getMsg(InputStream inputStream) throws IOException {
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
if (len != -1) {
String msg = new String(bytes, 0, len, StandardCharsets.UTF_8);
DustService dustService = new DustService(dustDao);
dustService.insertDustData(msg);
return true;
}
return false;
}
private void sendMsg(OutputStream outputStream) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));
bw.write("success\n");
bw.flush();
}
@Override
public void run() {
// try {
// 设置连接超时9秒
try {
socket.setSoTimeout(120000);
System.out.println("客户 - " + socket.getRemoteSocketAddress() + " -> 连接成功");
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
while (true) {
boolean is = getMsg(inputStream);
if (is) {
sendMsg(outputStream);
}
}
} catch (IOException e) {
try {
System.out.println("异常关闭socket连接");
socket.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
}
关于本次使用中遇到的一些问题
1.在对接过程中,数据接收曾经一度陷入尴尬的无法接收数据问题,最终定位发现是客户端传输数据没有加上一个\n做为单次传输结束的尾标记,导致socket在接收信息的过程中一直在read,最终导致读取时间超时异常。
2.在处理socket连接的信息中,使用的是while true循环,暂时没有找到别的更好的处理方法。