This link provides a tutorial for opening a non-blocking socket. However the method provided here doesn't gives option of picking up any random port. Also all the constructors shown at this java doc page takes address as argument. Any way to do this?
If you look at the constructors for InetSocketAddress, it is stated that
A valid port value is between 0 and 65535. A port number of zero will let the system pick up an ephemeral port in a bind operation.
In essence, just pass in an InetSocketAddress, using 0 for the port argument, and this will result in a random port being chosen.
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
// Use wildcard ip (*) and ephemeral port
serverSocketChannel.socket().bind(new InetSocketAddress(0));
Its bit hacky solution but has worked for me. You can create a normal Socket, with port argument as 0(so you get an random available socket) connect on it, then grab its address. Now close this socket and pass this address as argument while creating SocketChannel.
However be cautious this may be a trouble in multi-threaded program where threads are creating socket in parallel. Consider two parallel threads t1 and t2. Suppose t1 created a socket grabbed its address, closed it and then got context switched. Now t2 got the same port, before t1 was able to connect on a Non-blocking channel, using this socket. For such case it would be good to keep looping till the non-blocking (SocketChannel) connection is not established.
Related
I've searched here and found a similar article but I didn't really get the answer I'm looking for. I'm learning Networking with Java through some examples and some pseudo-reverse engineering. Oracle's documentation is helping quite a bit too but I've got a few questions.
Why exactly do you bind an IP address to a Socket? Is it necessary? When would you use said binding?
Here is part of the code that raised the question to me:
ServerSocket myServerSocket = new ServerSocket(1337);
System.out.println("Server is waiting for an incoming connection from client...");
Socket recievingSocket = myServerSocket.accept();
Now from what I understand that if I was to bind a Socket it would be right after the running accept() correct?
Why exactly do you bind an IP address to a Socket?
To determine which outbound interface it will connect via.
Is it necessary?
In theory, no. In practice it is sometimes required when connecting via a VPN.
Now from what I understand that if I was to bind a Socket it would be right after the running accept() correct?
Incorrect. An accepted or connected Socket is already bound. The only ways to bind a Socket are:
Create it with new Socket() with no arguments and then call bind(), or
Create it with the four-argument constructor, where the first two arguments are the target address and the second two are the bind-address.
The major use of bind() is in conjunction with ServerSocket. For instance, in your example, calling new ServerSocket(1337) creates a socket, binds it to 0.0.0.0:1337, and puts it into the LISTEN state.
You bind a socket to an address in order to restrict where the socket is going to be listening to. It is not necessary if you want it to use default behavior, which IIRC is to listen to ANY.
You would bind before you use accept because accept tells the socket to start listening on the socket, but bind tell it where to look. The socket needs to know where to look before it listens.
Socket is essentially = IP + Port.
So yes you need an IP address to create a socket. And the process is termed as binding because you may bind multiple ports to same address all listening to their respective incoming connections.
Above pretty much sums your question of is it necessary but to add another point - Lets say you create a client to connect to your server. How will it connect if does not know server IP address and port to which it is suppose to connect.
I am trying to write code to hot-swap sockets in Java.
Here is the gist of the code I am currently using:
// initial server initialization
ServerSocket server1 = new ServerSocket(port);
// ... code to accept and process requests
// new server initialization
ServerSocket server2 = new ServerSocket();
// attempt at hotswap
server1.close();
server2.bind(port);
// .. more code
The code works as above but I am wondering about the possibility of dropped messages between the time the first socket is closed and the second one is opened.
Two questions:
Is there a way to ensure that no connections are dropped?
If there is a way to ensure that no connections are dropped does it still work if the instances of the ServerSocket class are in different virtual machines?
Thanks in advance.
The closing of a ServerSocket means that that server1's handler does not handle new incoming connections, these are taken care of by the server2. So far so good. You can garbage collect server1 when it no longer has any connected Sockets left.
There will be a (shorter or longer) period of time where the port is marked as "not open" in the OS networking driver after the first ServerSocket is closed and the second one is opened (since the OS cannot know our intention to start a new socket directly after closing the first one).
An incoming TCP request during this time will get a message back from the OS that the port is not open, and will likely not retry, since it got a confirmation that the port was not open.
A Possible work-around
Use the java NIO constructs, which spawn a new thread per incoming request, see the ServerSocketChannel and be sure to check out the library http://netty.io/ which have several constructs for this.
Make sure that you can set the handler for the incoming request dynamically (and thread safe :), this will make it possible to seamlessly change the handling of the incoming requests, but you will not be able to exchange the ServerSocket (but that's likely not exactly what you want, either).
I have recently nose dived into socket programming using java, and I have a few general sort of questions.
There is a bind() method, as well as a connect() and disconnect(). There is no unbind(). Is this because upon disconnecting the socket is unbound? Does garbage collection take care of this once the program exits? Or is this not even a valid question?
Also, upon creating a DatagramSocket, how is it different if I only provide the port and the address? I am creating a program to collect data off a network, as the data floats around and log it. Should I just use the local address? Could not using the address when I create the socket cause me to not be able to collect packets?
I am just trying to get a stronger understanding on the inner-workings of these things.
There are about 15 independent questions in there, but I'll do my best to address them:
There is a bind() method, as well as a connect() and disconnect(). There is no unbind(). Is this because upon disconnecting the socket is unbound?
bind() is separate from connect() and disconnect(). Bind is used to bind a socket to a particular port -- effectively to "listen" for connections whereas connect() is used to open a connection to a socket that is already listening on a particular port. The equivalent of unbind() is close()
Does garbage collection take care of this once the program exits? Or is this not even a valid question?
This is a totally valid question, although garbage collection is a technology used for memory management, not socket/OS resource management. If you don't release a particular port, it will remain associated with your application until your application terminates and it will then be reclaimed by the OS. This is OS-level functionality, not JVM functionality, etc.
Also, upon creating a DatagramSocket, how is it different if I only provide the port or provide the port and the address?
At some point, you have to provide the internet address and port or the socket you wish to connect to or to bind to. There's no way around it.
I am creating a program to collect data off a network, as the data floats around and log it. Should I just use the local address? Could not using the address when I create the socket cause me to not be able to collect packets?
I'm not sure what you're asking here, are you talking about logging all packets on the network, aka a sniffer? That's going to require more than simple datagram programming. You actually have to inject yourself at the network-adapter level to intercept packets as they are read off the line. What you're talking about will only allow you to receive packets that are sent to the specific port you're listening to.
A DatagramSocket remains bound when disconnected, it is the close() method that would unbind it. Note that for a UDP (datagram) socket the semantics of connect() and disconnect() are different as compared to a TCP (or other connection oriented) socket. UDP is a connectionless protocol and a bound DatagramSocket can send and receive packets without being 'connected'. The connect() method has a purely local effect in that it causes the socket to only be able to send and receive packets to a given host/port, i.e. acting as a filter. A DatagramSocket connected to a multicast or broadcast address will only be able to send packets and not receive them.
bind(SocketAddress) is used to attach a socket to a local address/port combination, before a socket is bound it cannot receive or send any packets. The default behaviour of the constructors is to bind the socket immediately. To create an unbound 'DatagramSocket' use the DatagramSocket(SocketAddress) constructor passing null as an argument. Then it is possible to apply any custom configuration to the socket before binding it with bind().
As far as I know an open DatagramSocket that goes out of scope will cause a resource leak, the object may be garbage collected, but I'm pretty sure the underlying UDP socket will remain allocated by the OS until the JVM process exits.
If an address is not specified before the socket is bound, when bound it will attach to the wildcard address (INADDR_ANY), making it able to receive and send packets from any available local address (unless it is later 'connected' to some host). If a port is not specified (or specified as 0) then the socket is bound to some available port chosen by the OS (ephemeral port).
Edit: An example
// bind to INADDR_ANY, allowing packets on all IP addresses of host:
DatagramSocket dsock = new DatagramSocket(55555);
DatagramPacket packet = new DatagramPacket(new byte[8192]);
//next packet can be from anywhere including local host (127.0.0.0/8)
dsock.receive(packet);
// restrict communication to a single host/port:
dsock.connect(new InetSocketAddress("somehost.net", 99));
// next packet can only be from somehost.net on port 99:
dsock.receive(packet);
What would happen if change both clientSocket and serverSocket to “mySocket”?
Can the client send a segment to server without knowing the server’s IP address and/or port number?
Can multiple clients use the server?
From my notes, on page 20 : http://www.cs.ucc.ie/~cjs/teach/cs2505/02-app-layer-b.pdf . Kind of confused with these.
I assume if you change both client and serverSocket to mySocket then nothing would happen, since it would only be a variable name change( I assume ).
And I assume the client can't send a message without know the IP address/port no?
And that multiple clients cannot use the server since that would require threading?
(1) Since I see no reference to mySocket other than the one in the question I would say your answer seems right.
(2) The address/port are obviously necessary. However this could be a trick question in that client could call connect() on the socket. With UDP, connect() the kernel keeps track of the address passed in the call as the peer of the socket. The socket could then just call write() or send() rather than having to use sendto(). Still, calling connect would still require the address/port in the first place so who knows what they are getting at.
(3) There is no "connection" in UDP. Many clients could send to the server. The server can get the address of the individual clients from its recvfrom and then turn around and use that address in its sendto.
I'm trying to load test a Java server by opening a large number of socket connections to the server, authenticating, closing the connection, then repeating. My app runs great for awhile but eventually I get:
java.net.BindException: Address already in use: connect
According to documentation I read, the reason for this is that closed sockets still occupy the local address assigned to them for a period of time after close() was called. This is OS dependent but can be on the order of minutes. I tried calling setReuseAddress(true) on the socket with the hopes that its address would be reusable immediately after close() was called. Unfortunately this doesn't seem to be the case.
My code for socket creation is:
Socket socket = new Socket();
socket.setReuseAddress(true);
socket.connect(new InetSocketAddress(m_host, m_port));
But I still get this error:
java.net.BindException: Address already in use: connect after awhile.
Is there any other way to accomplish what I'm trying to do? I would like to for instance: open 100 sockets, close them all, open 200 sockets, close them all, open 300, etc. up to a max of 2000 or so sockets.
Any help would be greatly appreciated!
You are exhausing the space of outbound ports by opening that many outbound sockets within the TIME_WAIT period of two minutes. The first question you should ask yourself is does this represent a realistic load test at all? Is a real client really going to do that? If not, you just need to revise your testing methodology.
BTW SO_LINGER is the number of seconds the application will wait during close() for data to be flushed. It is normally zero. The port will hang around for the TIME_WAIT interval anyway if this is the end that issued the close. This is not the same thing. It is possible to abuse the SO_LINGER option to patch the problem. However that will also cause exceptional behaviour at the peer and again this is not the purpose of a test.
Not using bind() but setReuseAddress(true) is just weird, I hope you do understand the implications of setReuseAddress (and the point of). 100-2000 is not a great number of sockets to open, however the server you are attempting to connect to (since it looks the same addr/port pair), may just drop them w/ a normal backlog of 50.
Edit:
if you need to open multiple sockets quickly (ermm port scan?), I'd very strongly recommend using NIO and connect()/finishConnect() + Selector. Opening 1000 sockets in the same thread is just plain slow.
Forgot you may need finishConnect() either way in your code.
I think that you should plan on the port you want to use to connect to be in use. By that I mean try to connect using the given port. If the connect fails (or in your case throws an exception), try to open the connection using the next port number.
Try wrapping the connect statement in a try/catch.
Here's some pseudo-code that conveys what I think will work:
portNumber = x //where x is the first port number you will try
numConnections = 200 // or however many connections you want to open
while(numConnections > 0){
try{
connect(host, portNumber)
numConnections--
}catch(){}
portNumber++
}
This code doesn't cover corner cases such as "what happens when all ports are in use?"