Setting source port on a Java Socket?

2020-07-03 08:30发布

问题:

I'm very new to socket programming:

Is it possible to explicitly set the the source port on a Java Socket?

I am working on a client/server application in which clients could potentially be listening for replies from the server on several ports. It would be nice if I could set this reply port on the client side when initializing the Socket, so that the server would be able to determine which port to reply to on the other side.

回答1:

Yes, use the bind() method. This mirrors the bind() function available in most C-level socket implementations. Note that you can't always choose freely which port to use, on some system some ranges are reserved and considered off-limits to user applications.



回答2:

It usually goes like this:

First, the Server opens a ServerSocket on a well known port and waits for input.

Meanwhile the Client opens a (client) Socket with the servers hostname and this well known port address. It sends a request message to the server to initialize a communication session.

The server receives the message, spawns a worker thread, which opens another ServerSocket on a different port and the server sends a response, where it tells the client this port number.

Now the client closes the actual connection and creates a new Socket, now with the port number he has just been told.

This way, the server can handle more then one client at a time, because each client gets his individual 'connection' (port).



回答3:

When using datagram sockets, the source address and port is set by the socket when the datagram is sent.

InetAddress sourceAddr = InetAddress.getLocalHost();
DatagramSocket sock = new DatagramSocket(sourcePort, sourceAddr);
DatagramPacket msg = new DatagramPacket(mbuf, mbuf.length, dstIP, dstPort);

sock.send(msg); // sent from sourcePort to dstPort

sourceAddr is a little redundant in this example, new DatagramSocket(sourcePort) would bind to the preferred best-choice address, but if you need to specify the source IP in addition to port, that's how.

For both types of socket, using bind(new InetSocketAddress(port)) will choose an appropriate local source address and the specified port, and port 0 will choose an appropriate local port as well.

All retrievable with getLocalAddress() and getLocalPort().



回答4:

You can use this call to create socket,

public Socket(InetAddress address,
              int port,
              InetAddress localAddr,
              int localPort)
       throws IOException

This is normally done for UDP and this is not advised for TCP connections. If you do this for TCP on both ends, you can only have one TCP connection. If you create one more, the socket layer will get confused and you will end up lose all your connections.

For TCP, the common practice is to reply in the same connection. If you have to reply in a different connection, use a pre-defined ports on client also.



回答5:

First, I will totally recomend you to use Java NIO.

DatagramChannel udpchannel = DatagramChannel.open();
DatagramSocket udpsocket = udpchannel.socket();
SocketAddress sa = new InetSocketAddress(BIND_ADDRESS, BIND_PORT);
udpsocket.bind(sa);

Second, by using the binding to a socket address you will also be able to define to which network address you will be connected to. It means that if you set BIND_ADDRESS to "0.0.0.0" you will be able to listen from every network card connected to your server; but if you set BIND_ADDRESS to, for example, "10.190.0.1" you will only receive requests listened on such address.



标签: java sockets