[英]Can two different socket instances listen to same TCP port ( Port already in use )
I have a TcpServer class that is responsible to, well, act like a tcp server. 我有一个TcpServer类负责,就像tcp服务器一样。 You can find the class below :
你可以在下面找到这个课程:
public class TcpServer {
private ServerSocket serverSocket;
private Socket socket;
private int locallyBoundPort;
public TcpServer() {
}
public TcpServer(int locallyBoundPort) {
try {
this.serverSocket = new ServerSocket(locallyBoundPort);
serverSocket.setReuseAddress(true);
} catch (IOException e) {
System.out.println("Error at binding to port TCP : " + locallyBoundPort + "...cause : " + e.getMessage());
}
socket = null;
}
public void accept() {
try {
socket = serverSocket.accept();
socket.setReuseAddress(true);
} catch (IOException e) {
System.out.println("Error at accept : " + locallyBoundPort);
}
}
public void send(Data data) throws IOException {
if(socket != null) {
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(data);
}
}
public Data receive() throws ClassNotFoundException, IOException {
if(socket != null) {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
return (Data) in.readObject();
} else {
return null;
}
}
public boolean bind(int port) throws IOException {
try {
this.serverSocket = new ServerSocket(port);
this.locallyBoundPort = port;
} catch(IOException e) {
return false;
}
return true;
}
public void close() {
try {
serverSocket.close();
socket.close();
} catch (IOException e) {
OzumUtils.print("IOException in close, TcpServer");
}
}
public int getLocallyBoundPort() {
return locallyBoundPort;
}
public Socket getSocket() {
return socket;
}
public ServerSocket getServerSocket() {
return serverSocket;
}
}
And I have a code piece that does this : 我有一个代码片来做到这一点:
TcpServer tcpServer = new TcpServer(LocalPort);
while(1)
{
tcpServer.accept();
Thread thread = new Thread(new runnable(tcpServer));
thread.start();
tcpServer = new TcpServer(LocalPort);
}
However I am getting a port already in use error. 但是我得到一个端口已经在使用错误。 I thought two different socket instances could listen to the same port as multiplexing allows two connections through the same port when the connector has different ip or port ?
我认为两个不同的套接字实例可以监听同一个端口,因为当连接器有不同的ip或端口时,多路复用允许两个连接通过同一个端口? What am I missing?
我错过了什么?
You cannot bind two tcp server sockets to the same port. 您不能将两个tcp服务器套接字绑定到同一端口。
reuseAddress
is really for client sockets, and it does not work the way you think it does ... and the way you are using it would not do anything at all either way (because you are setting it after binding). reuseAddress
是用于客户端套接字,并且它不像你想象的那样工作......并且你使用它的方式根本不会做任何事情(因为你在绑定后设置它)。
You don't really need to bind twice to the same port either. 你真的不需要两次绑定到同一个端口。 Just remove this line
tcpServer = new TcpServer(LocalPort);
只需删除此行
tcpServer = new TcpServer(LocalPort);
from the bottom of your while
loop, and you'll be all set. 从你的
while
循环的底部,你将全部设置。
The way this works is that you bind your server socket once and listen to the port. 这种方式的工作方式是绑定服务器套接字一次并监听端口。 When a connection arrives, it forks a client socket for you to communicate with the client, and the original server socket continues to listen for more connections.
当连接到达时,它会分叉客户端套接字以便您与客户端通信,并且原始服务器套接字继续侦听更多连接。
Basically, you need to remove the socket
member (and any other state) from your TcpServer
, and make the accept
method return the accepted socket. 基本上,您需要从
TcpServer
删除socket
成员(以及任何其他状态),并使accept
方法返回接受的套接字。 Then make your runnable
take that socket
as a parameter instead of the TcpServer
, and use that to serve the client connection. 然后让
runnable
将该socket
作为参数而不是TcpServer
,并使用它来为客户端连接提供服务。 Then just keep calling accept
in the loop, and forking threads for new connections same way you do know, except do not recreate the server every time. 然后继续在循环中调用
accept
,并以您知道的方式为新连接分叉线程,除非每次都不重新创建服务器。
Or, alternatively, remove the server socket and port from TcpServer
, create the socket outside the loop, then while(true)
call accept
on it, create a new TcpServer
with the returned client socket, and use it in a thread to process the connection. 或者,或者从
TcpServer
删除服务器套接字和端口,在循环外创建套接字,然后while(true)
调用accept
,使用返回的客户端套接字创建一个新的TcpServer
,并在线程中使用它来处理连接。
Do not forget to close client sockets after you are done with them. 完成后,不要忘记关闭客户端套接字。
No, you can't use a port already in listening state. 不,您不能使用已处于侦听状态的端口。 However any number of clients can connect to this same port.
但是,任意数量的客户端都可以连接到同一个端口。 You don't need to listen to the port again, you just spawn a new thread to process the current connection and wait for a new one.
您不需要再次侦听端口,只需生成一个新线程来处理当前连接并等待新连接。 For example, supposing you have a class
TcpConnectionHanlder
that implements Runnable
and takes the Socket
as parameter, the loop would look like 例如,假设您有一个实现
Runnable
的类TcpConnectionHanlder
并将Socket
作为参数,则循环看起来像
while (true) { //while(1) is not valid Java syntax
final Socket tcpSocket = tcpServer.accept(); // Get socket for incoming connection
final Thread thread = new Thread(new TcpConnectionHanlder(tcpSocket)); // Create a thread for this socket/client connection
thread.start(); // Launch the thread
// tcpServer = new TcpServer(LocalPort); <- not needed, port still listening.
}
Then in your TcpConnectionHanlder
instance you handle this particular client (socket). 然后在您的
TcpConnectionHanlder
实例中处理此特定客户端(套接字)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.