Sun*_*nal 6 java sockets tcp ip-address
我想在java中为入站和出站连接使用相同的端口
目的是在分布式环境中创建节点.但在Tcp中,我需要使用两个不同的端口来接受和启动连接.
// accept incoming connection on one port
ServerSocket.accept()
// connect to remote, the port used will be different from the one used for accepting
Socket.connect()
Run Code Online (Sandbox Code Playgroud)
现在的问题是:
Socket.connect())时,A和B将保持套接字打开以便将来传递消息.Socket()没有accept()方法的实例绑定的当然,A可以通知B关于它正在收听的端口,但是没有直接的方法吗?
我怎样才能通过这个测试?
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class DualSocketTest {
ExecutorService service= Executors.newFixedThreadPool(10);
int echoServerport=8080;
int localServerport=8090;
@Test
public void testConnectivity() throws IOException {
// create a echo server on port 8080
startEcho();
// create a local Server instance
ServerSocket localServer=new ServerSocket();
// set the reuseAddress to true
localServer.setReuseAddress(true);
// bind the serverSocket
localServer.bind(new InetSocketAddress(localServerport));
// create a socket to connect the echo server using the same port used by localServer
Socket socket = new Socket();
socket.setReuseAddress(true);
// but this will throw SocketBindException
socket.bind(new InetSocketAddress(localServerport));
socket.connect(new InetSocketAddress(echoServerport));
// write hello
socket.getOutputStream().write("Hello !".getBytes());
byte[] result=new byte[100];
// receive hello
String ans=new String(result,0,socket.getInputStream().read(result));
System.out.println("Server replied with : "+ans);
// what was written and what was received must be same.
assert(ans.equals("Hello !"));
}
// start a echo server listening on the specified port
private void startEcho() throws IOException {
ServerSocket echoServer=new ServerSocket(echoServerport);
service.submit(()->{
try {
while(!echoServer.isClosed()) {
Socket socket = echoServer.accept();
System.out.println("connected with :" + socket.getInetAddress().toString() + ":" + socket.getPort());
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
service.submit(() -> {
while (socket.isConnected()) {
try {
outputStream.write(inputStream.read());
} catch (IOException e) {
break;
}
}
System.out.println("The Client has closed connection.");
});
}
} catch (IOException e) {
e.printStackTrace();
}
});
Thread.yield();
}
// Write something to the socket.
}
Run Code Online (Sandbox Code Playgroud)
我之前使用udp时没有这样的问题.相同的套接字支持receive()和send()方法.对于udp,共享地址很容易.
socketAddressA,SO_REUSEADDR 选项应在绑定之前在套接字上设置。我最初在 Python 中进行了测试(无法访问 Java 环境),并且以下脚本在 Windows 10 系统上运行没有错误:
import socket
serv = socket.socket() # set a listening socket
serv.bind(('0.0.0.0',8080))
serv.listen(5)
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0',8080))
s.connect(('127.0.0.1', 8090))
Run Code Online (Sandbox Code Playgroud)
另一个进程正在侦听端口 8090
不幸的是,在 Java setReuseAddrjavadoc 中明确指出(强调我的):
在使用bind(SocketAddress) 绑定套接字之前启用SO_REUSEADDR 允许绑定套接字,即使先前的连接处于超时状态也是如此。
由于我无法猜测的原因,Java 在这里受到更多限制。看起来更奇怪的是,根据另一个问题,它曾经被允许在较旧的 JRE 版本(高达 JRE 7U5)上使用
原始(错误)帖子如下:
诀窍是在绑定之前设置 SO_REUSEADDR 选项。这意味着您需要对ServerSocketet都使用无参数构造函数Socket。或多或少:
ServerSocket localServer = new ServerSocket();
localServer.setReuseAddress(true);
localServer.bind(InetSocketAddress(localServerport));
... // Ok listening...
Socket socket = new Socket();
socket.setReuseAddress(true);
socket.bind(InetSocketAddress(localServerport));
socket.connect(...);
Run Code Online (Sandbox Code Playgroud)
这样您就可以从本地侦听端口进行连接,以便对等方知道在连接关闭后如何重新连接。
注意:未经测试...
| 归档时间: |
|
| 查看次数: |
232 次 |
| 最近记录: |