我正在运行一个从IoT端点接收数据的Spring Boot应用程序。它是一种专有协议,因此我只使用基于this example from Oracle的标准TCP套接字实现。
目前我有一个@Component开始一个新线程:
@Component
public class TCPSocketServer {
@Autowired
private TCPServerRunnable sr;
@PostConstruct
public void init() throws IOException
{
sr.setSocket(new ServerSocket(43110));
Thread server = new Thread(sr);
server.start();
}
@PreDestroy
public void clean()
{
// close any open sockets, resources, etc.
sr.stop();
}
}
和服务器逻辑,为每个连接启动一个新线程:
@Component
public class TCPServerRunnable implements Runnable {
private ServerSocket serverSocket = null;
private static boolean isRunning = true;
@Autowired
private VehicleService vehicleService = null;
@Override
public void run() {
//TODO: Remove comments.
System.out.println("TCP thread started...");
while (isRunning) {
System.out.println("Accepting new TCP connections...");
try {
new TCPServerRunnableHandler(serverSocket.accept(), vehicleService).start();
} catch (IOException ex) {
System.out.println("TCP socket creation failed...");
}
System.out.println("TCP connection established...");
}
}
private static class TCPServerRunnableHandler extends Thread {
private Socket clientSocket;
private DataOutputStream out;
private DataInputStream in;
private VehicleService vehicleService;
public TCPServerRunnableHandler(Socket socket, VehicleService vehicleService) {
this.clientSocket = socket;
this.vehicleService = vehicleService;
}
public void run() {
try {
out = new DataOutputStream(clientSocket.getOutputStream());
in = new DataInputStream(clientSocket.getInputStream());
while (isRunning) {
byte[] data = new byte[512];
int packetEnd = 0, i = 0;
while (packetEnd < 2) {
data[i] = in.readByte();
if (data[i] == (byte)0xC0) {
packetEnd++;
} else {
if (data[i] == (byte)0xDC && i > 0 && data[i-1] == (byte)0xDB) {
data[i-1] = (byte)0xC0;
} else {
i++;
}
}
}
Protocol protocol = new Protocol(vehicleService);
data = protocol.processMessage(data, clientSocket.getInetAddress().getHostAddress(), clientSocket.getPort());
for (int j = 0; j < data.length; j++) {
if (data[j] == (byte) 0xC0 && j > 0) {
out.writeByte(0xDB);
out.writeByte(0xDC);
} else {
out.writeByte(data[i]);
}
}
out.writeByte(0xC0);
out.flush();
}
in.close();
out.close();
clientSocket.close();
} catch (IOException ex) {
System.out.println("TCP iot interface exception....");
}
}
}
void stop() {
isRunning = false;
}
public void setSocket(ServerSocket socket) {
this.serverSocket = socket;
}
}
我遇到的问题是我不知道协议是否是使用连接到数据库的@Service vehicleService并根据收到的消息更新Vehicle字段的正确类。第二个问题是我不喜欢线程的实现。我不能直接在Protocol类中自动装配Vehicle Service,因为它没有被Spring Boot实例化。
您能否告诉我如何处理这些主题?有没有更好的方法在Spring Boot中执行上述操作?
感谢您的任何建议!!!
答案 0 :(得分:0)
除了纯Java套接字外,我一直在寻找类似的方法。这是我的实现,您可能会考虑两个优点。
客户
@Component
public class SocketServer {
@Autowired
private SocketServerRunnable socketServerRunnable;
@PostConstruct
public void init() throws IOException {
try (var listener = new ServerSocket(59898)) {
System.out.println("The server is running...");
var pool = Executors.newFixedThreadPool(100);
//External Loop
while (true) {
socketServerRunnable.setSocket(listener.accept());
pool.execute(socketServerRunnable);
}
}
}
服务器
@Component
@Scope("prototype")
@Data
public class SocketServerRunnable implements Runnable {
private ServerSocket serverSocket;
private Socket socket;
@Override
public void run() {
System.out.println("Connected: " + socket);
try {
DataInputStream din = new DataInputStream(socket.getInputStream());
DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = "", str2 = "";
while (!str.equals("stop")) {
//gateway.route(din);
str = din.readUTF();
System.out.println("client says: " + str);
str = din.readUTF();
System.out.println("client says: " + str);
str = din.readUTF();
System.out.println("client says: " + str);
str2 = br.readLine();
dout.writeUTF(str2);
dout.flush();
}
din.close();
//socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}