英文:
Is there a possiblity to write/read from a socket on same port from different class
问题
我有一个用于机器之间通信的Spring Boot应用程序(tcp客户端)和TCP服务器(localhost)。我可以与一个机器/客户端通信,但无法与两个或更多机器通信。
因此,我启动了我的Spring Boot应用程序:
package com.example.workflow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.IOException;
@SpringBootApplication
public class Application {
public static void main(String[] args) throws IOException {
Runnable serverZyklisch = new ServerZyklisch();
Runnable serverAzyklisch = new ServerAzyklisch();
for (int i = 0; i < 4; i++) {
new Thread(serverZyklisch).start();
new Thread(serverAzyklisch).start();
}
SpringApplication.run(Application.class);
}
}
在这里,我启动了不同的线程,以便客户端(例如10.50.12.174 = Press,10.50.12.204 = Drill)可以通过Socket连接连接到TCP服务器。
我的ServerAzyklisch类如下所示:
package com.example.workflow;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerAzyklisch implements Runnable, JavaDelegate {
// ... 这里省略了类的其余部分 ...
}
现在,我想将“while循环”(带有out.write)从其他类中分离出来,以便像在ServerAzyklisch的run方法中一样使用与Socket的连接。
因此,我编写了一个类Presse.java:
package com.example.workflow;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Presse implements JavaDelegate {
// ... 这里省略了类的其余部分 ...
}
我想从这个类发送我的3条消息,就像在ServerAzyklisch类中一样。但是它抛出错误,原因是:
Caused by: java.net.BindException: Address already in use: NET_Bind
我知道这是因为我第二次执行Socket.accept,但我不明白我如何使其正常工作。我是否必须关闭Socket连接?如果是的话,在哪里以及使用哪个Java命令来关闭?
英文:
Im having Spring Boot Application for communication between Machines (tcp Clients) and TCP Server (localhost). I am able to communicate with one machine/client, but I cant communicate with 2 or more machines.
Therefore I start my Spring Boot Application:
package com.example.workflow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.IOException;
@SpringBootApplication
public class Application {
public static void main(String[] args) throws IOException {
Runnable serverZyklisch = new ServerZyklisch();
Runnable serverAzyklisch = new ServerAzyklisch();
for (int i = 0; i < 4; i++) {
new Thread(serverZyklisch).start();
new Thread(serverAzyklisch).start();
}
SpringApplication.run(Application.class);
}
}
There I have different Threads started, so that the clients (for example 10.50.12.174 = Press, 10.50.12.204 = Drill) can connect to TCP Server over Socket Connection.
My ServerAzyklisch class is like this:
package com.example.workflow;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerAzyklisch implements Runnable, JavaDelegate {
int count = 0;
private final ServerSocket ssocket;
static String param = StartTCPServersDelegate.parameter;
HexToByteConverter hexToByteConverter = new HexToByteConverter();
// 2 TCP Server starten Port 2000, Port 2001
public ServerAzyklisch(String Pparam) throws IOException {
ssocket = new ServerSocket(2000);
param = Pparam;
}
public ServerAzyklisch() throws IOException {
ssocket = new ServerSocket(2000);
}
public void run() {
byte[] buf = new byte[1];
System.out.println(param+"Paraaam");
InputStream in;
OutputStream out = null;
Socket socket = null;
//Thread immer aktiv
int n = 0;
while(true){
try {
// Wartet auf Socket Verbindung
System.out.println("Server is listening on port "+ ssocket.getLocalPort());
socket = ssocket.accept();
count++;
System.out.println("Countet clients: "+count);
socket.setSoLinger(true, 1000);
System.out.println("Sockeport: "+socket.getLocalPort());
System.out.println("Connection from " + socket.getInetAddress().toString());
//Inputstream
in = socket.getInputStream();
//Outputstream
out = socket.getOutputStream();
//Datenpuffer deklarieren (anlegen)
byte []data = new byte[132];
byte[]Pressen1hexdump110 = hexToByteConverter.hexStringToByteArray("33333333003d0064000600000004004001c9c78900010000006e0000000000000000000000000001000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"+param);
byte[]Pressen2hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
byte[]Pressen3hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065001400000000004001c9c6e900010000006e000000000000000000000000000100000000001e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
in.read(buf);
while (buf[0] != -1) {
out.write(Pressen1hexdump110);
out.write(Pressen2hexdump);
out.write(Pressen3hexdump);
}
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void execute(DelegateExecution delegateExecution) throws IOException {
}
}
Now I want to outsource the "while loop" (with out.write) in other Classes to use the connection to Socket like in ServerAzyklisch run method.
Therefore I wrote for example a Class Presse.java
package com.example.workflow;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Presse implements JavaDelegate {
ServerSocket ssocket;
private HexToByteConverter hexToByteConverter = new HexToByteConverter();
Socket socket;
InputStream in;
OutputStream out;
byte[]Pressen1hexdump110 = hexToByteConverter.hexStringToByteArray("33333333003d0064000600000004004001c9c78900010000006e00000000000000000000000000010000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005");
byte[]Pressen2hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
byte[]Pressen3hexdump = hexToByteConverter.hexStringToByteArray("3333333300400065001400000000004001c9c6e900010000006e000000000000000000000000000100000000001e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
public Presse() throws IOException {
ssocket = new ServerSocket(2000);
socket = ssocket.accept();
//Inputstream
in = socket.getInputStream();
//Outputstream
out = socket.getOutputStream();
}
public void sendMessage(InputStream in, OutputStream out, byte[]message) throws IOException {
out.write(Pressen1hexdump110);
out.write(Pressen2hexdump);
out.write(Pressen3hexdump);
socket.close();
}
@Override
public void execute(DelegateExecution delegateExecution) throws Exception {
PostRequestDelegate postRequestDelegate = new PostRequestDelegate();
postRequestDelegate.post();
}
}
I want to send my 3 messages from this class, like in ServerAzyklisch class. But it throws Error because:
Caused by: java.net.BindException: Address already in use: NET_Bind
I know this because is I do Socket.accept a second time, but I dont understand how I can achieve this to work. Do I have to close socket connection ? If yes where and with which Java Command ?
答案1
得分: 0
如果您希望在程序中拥有多个“Presse”实例,至少需要从其中删除ServerSocket
。相反,您应该在其他地方accept
来自客户端的连接,并将客户端套接字传递给Presse
构造函数:
public Presse(Socket clientSocket) throws IOException {
this.socket = clientSocket;
// 输入流
in = socket.getInputStream();
// 输出流
out = socket.getOutputStream();
}
通常,您只希望创建一个 ServerSocket
,并在循环中调用accept
。为了允许多个客户端同时连接,可以在单独的线程中与客户端通信。这样,服务器就可以继续接受新的连接。以下是如何使用线程池的示例骨架:
int maxClients = 10;
ExecutorService threadPool = Executors.newFixedThreadPool(maxClients);
ServerSocket serverSocket = new ServerSocket(2000);
while (true) {
Socket clientSocket = serverSocket.accept();
threadPool.submit(() -> {
// 与 clientSocket 通信,例如:
Presse p = new Presse(clientSocket);
// 您可能希望将此代码放在一个单独的方法中
});
}
英文:
If you want to have more than one instances of "Presse" in your program, the very least you'll need to remove ServerSocket
from it. Instead, you should accept
the connection from the client somewhere else, and pass the client socket to the Presse
constructor:
public Presse(Socket clientSocket) throws IOException {
this.socket = clientSocket;
//Inputstream
in = socket.getInputStream();
//Outputstream
out = socket.getOutputStream();
}
Usually you want to create only one ServerSocket
, and call accept
on it in a loop. To allow more than one client to connect at a time, communicate with the client in a separate thread. This way the server can go and accept a new connection. Here's a skeleton example of how to use a thread pool for this:
int maxClients = 10;
ExecutorService threadPool = Executors.newFixedThreadPool(maxClients);
ServerSocket serverSocket = new ServerSocket(2000);
while (true) {
Socket clientSocket = serverSocket.accept();
threadPool.submit(() -> {
// Communicate with clientSocket, for example:
Presse p = new Presse(clientSocket);
// You'll want to have this code in a separate method
});
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论