Bind - Address Already in Use - java

So i'm setting up a VoIP software and my connection thread to another peer has a UDP socket (to send audio) and a tcp socket for signaling/text. Now, to bypass firewalls and NAT, i need to use a TCP Hole punching technique, meaning i need to try and connect from this side of the call, which will open up holes in the firewall and NAT, and then i await a connection on the same port and the other peer should be able to connect to me.
try {
// UDP Socket
DatagramSocket callSocket = new DatagramSocket(null);
callSocket.setReuseAddress(true);
callSocket.bind(new InetSocketAddress(myIP, 0));
//Send/receive a few packets on callSocket
// Addresses to use
InetSocketAddress myAddress = new InetSocketAddress(myIP, callSocket.getLocalPort());
InetSocketAddress targetAddress = new InetSocketAddress(InetAddress.getByName("192.168.1.1"), 6800);
// TCP Hole Punch
Socket tcpSocket = new Socket();
tcpSocket.setReuseAddress(true);
tcpSocket.bind(myAddress);
try {
tcpSocket.connect(targetAddress, 50);
// this never connects. it's just meant to open a hole in a firewall
} catch (SocketTimeoutException ignore) {
System.out.println("Timeout!");
}
tcpSocket.close();
// Open up TCP socket
ServerSocket tcpTempSocket = new ServerSocket();
tcpTempSocket.setReuseAddress(true);
tcpTempSocket.bind(myAddress);
// accept connection and do stuff
} catch (Exception ex) {
ex.printStackTrace();
}
When i get to the 3rd and final bind, i get the "Bind Exception: Address already in use". I googled it up and read that the previous socket could still be hanging on something and wasn't closing, etc.
EDIT: this only happens in some computers. On others, it binds everything without an issue
EDIT: using "netstat", i can see that the connection is being hung up on "SYN_SENT" state on the computer where the bind goes wrong
Anyone have any tips on why this happens or how to i go around it?

Ok, so. The answer is... You can't go around it. This is an OS feature, which makes tcp connections get hung up on this port. On some computers it may take 5seconds to clear. On others, it may take over 2minutes.
Now, what i've done to get around this was... well, the only thing i could think of. When the program starts, it checks whether it supports tcp hole punching, or other ways of bypassing firewalls. The peers, when establishing the call, will trade parameters based on what they can do and, from a given priority list, choose a method they both support.
In my case, on my computer, TCP Hole Punch works. In my mum's laptop it doesn't, and i resorted to other techniques (UDP Hole Punch, UPnP, SOCKS, etc etc)

Related

What constitutes the condition "a server is up"

I'm looking for verification on the following:
In order to find out whether a server is up, I'm supposed to
establish a TCP connection to the host:port combination of the server given to me.
And in that case, "if a connection is established, then the service is up, otherwise -
if the connection is refused, the service is down".
So, should i be satisfied that the server is up when getRemoteSocketAddress() of Socket returns an object and not null? That is, does the following code always print the accurate info to the console?
Socket clientSocket = new Socket(hostName, port);
System.out.println("To console: The server is " + (clientSocket.getRemoteSocketAddress()==null?"down.":"up.") );
To me, it does. However, i haven't practical info on these things and won't make sure without a second opinion.
Note: I'm aware that, the server being up doesn't necessarily mean that it is accepting and processing requests. That goes by exchanging some greetings to see/hear one another on who's who and go from there based on the protocol in between. However, these aren't relevant on this one.
TIA
You would not even need to call
clientSocket.getRemoteSocketAddress();
because the constructor call from:
Socket clientSocket = new Socket(hostName, port);
will try to connect to the socket and will throw an IOException if it fails to do so. So I would rather do this:
public boolean hostUp(String hostName, int port) {
try {
Socket clientSocket = new Socket(hostName, port);
return true;
} catch(IOException e) {
return false;
}
}
That should do the trick.
Establishing TCP connection is a health-check at level 3 (OSI). It tells you that the service is up and running and listening on the port. However, it doesnt tells you anything about upper layers. For instance, if you use the server to serve http objects, you could do with http GET /sample.file on top of the established tcp connection. Alternatively, you could use this server for REST API, and then not only would you like to see 200 OK response from http layer, but maybe something more sophisticated in the response body.

OutputStream does not throw IOException although LAN-cable is not plugged

I established a TCP Connection with Java. The Server sends an "ALIVE"-Message to the Client every second to detect a broken connection.
but when I plug of the LAN-cable the IOException is thrown exactly after 23seconds, and not immediately after the send attempt.
My code to send looks like that
// out is an OutputStream
try {
out.write(String.format("%s\r\n", encryptedCommand).getBytes(Charset.forName("UTF-8")));
} catch (IOException e) {
fireConnectionClosed();
}
I'm pretty sure that this was working already, but now it doesn't any more
When a TCP packet fails to get through, the TCP stack resends the packet a few times. This allows the connection to stay up even if an occasional packet is lost. That prevents the problem of connections dropping whenever there's the least bit of congestion on the network. You can test this by unplugging the network for 5 or 10 seconds, then plugging it back in - the connection should be fine.
However, this feature also means that the TCP connection won't be recognized as having been lost until after a few retries.

java.nio.channels.ServerSocketChannel not closing properly

I have a java.nio.channels.ServerSocketChannel which I initialised as follows:
while(true)
{
ServerSocketChannel channel = ServerSocketChannel.open();
InetSocketAddress serverSocket = new InetSocketAddress(host,port);
channel.bind(serverSocket);
SocketChannel ch = channel.accept();
// Later on when I have read off data from a client, I want to shut this
// connection down and restart listening.
channel.socket().close(); //Just trying to close the associated socket
// too because earlier approaches failed
channel.close();
}
When I send the first message from client it is successfully delivered to server and the client program exits. Then trouble begins. When I initialise the client again and try to
establish at the same port and address of the server as I did the first time, I get a
java.net.BindException: Address already in use: connect
exception even though I closed the associated channel/socket.
I have been renewing the ServerSocketChannel and InetSocketAddressobjects because as my client instance has to shut down after a write, I have to disengage that channel and since I cannot reuse a channel after it has been closed, I have to make a new object everytime. My theory is since the channel reference is reassigned each time, the orphaned object becomes GC meat, but since the close() method apparently is not working properly, the channel is still alive and until GC collects it my port will be hogged.
Nevertheless I tried keeping the initialisation of ServerSocketChannel and InetSocketAddress objects before the while loop, but this did not help, and the same exception occurred after the first write, as before.
ServerSocketChannel channel = ServerSocketChannel.open();
InetSocketAddress serverSocket = new InetSocketAddress(host,port);
channel.bind(serverSocket);
while (true)
{
SocketChannel ch = channel.accept();
//read from a client
}
For clarity , here is how I connect from the client:
SocketChannel ch=SocketChannel.open();
ch.bind(new InetSocketAddress("localhost", 8077));
InetSocketAddress address=new InetSocketAddress("localhost",8079);
//the address and port of the server
System.out.print(ch.connect(address));
ByteBuffer buf=ByteBuffer.allocate(48);
buf.clear();
buf.put("Hellooooooooooooooooooooooooo".getBytes());
buf.flip();
while(buf.hasRemaining()) {
ch.write(buf);
}
ch.close();
It looks like you're confusing client and server. Normally, server starts only once and binds to s port. Usually, there's no need to close there anything as the port gets freed when the program exits. Obviously, you must close the Sockets obtained by ServerSocket.accept(), but that's another story.
I guess you've got confused by your variable names (just like it happened to me as I started with this). Try to call all things according to their type, here was Hungarian really helpful for me.
The code I wrote for testing this is long, stupid, and boring. But it seems to work.
It may also be helpful to do:
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
Search for information about this option to learn more.
do ch.close() as well to GC the client socket.

Java Threadpool TCP Server (Port keeps changing!!)

Good Day,
I was taking a look at this tutorial to do a TCP Threadpool server.
http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html
It works great for listening/RECEIVING to clients and processing, and returning a response. There is a class inside that I pass in WorkerRunnable into, and that basically prints out the remote socket address (who it was sent from)
public void run(){
synchronized(this){
this.runningThread = Thread.currentThread();
}
openServerSocket();
while(! isStopped()){
Socket clientSocket = null;
try {
clientSocket = this.serverSocket.accept();
} catch (IOException e) {
if(isStopped()) {
System.out.println("Server Stopped.") ;
return;
}
throw new RuntimeException(
"Error accepting client connection", e);
}
this.threadPool.execute(
new WorkerRunnable(clientSocket,
"Thread Pooled Server"));
}
this.threadPool.shutdown();
System.out.println("Server Stopped.") ;
}
The problem is. The remote address is supposed to stay fixed (I am working within my own home wifi router). However, the IP address of the sender stays the same, but the port keeps changing!!
This is a big problem for me..as I need to be able to return a response to the user for future tasks and I actually save this address to use again to send data. When I ran this in a single TCP thread..it stayed fixed (the port).
Why does the threadpool cause the TCP remote address port to keep changing?
With TCP, the client socket port is most of the time (almost 99%, except for specific protocols) randomly chosen. But to you don't have to know it, the only thing you have to do is to keep the clientSocket reference to write back data to the client. If you want to send data to the other host after that the connection is closed, you have to start a ServerSocket on both sides with a fixed port.
Even if you test from same machine the client port will be random by default. I am not sure if there is any way to set the client source port. However, if you use netstat or capture the packet you can be sure the source port is different for every connection.

What will happen to a TCP/UDP serversocket when I switch wifi network?

what will happen to the serversocket in my app when I suddenly change the wifi network? I guess it will shut down since my device will get a new IP, at least in TCP, is the UDP MulticastSocket prone to this as well? And how to end the previous Server socket thread and start a new one when the network changes? One solution is using time outs, another is using a flag that will indicate whether the infinite loop should end or not but since listening to a socket is a blocking function it will produce an exception/error anyways.
Any thoughts will be appreciated! :)
EDIT: sample of my server thread.
ServerSocket ss = new ServerSocket(4445);
while(true){
Socket socket = ss.accept();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Object obj = in.readObject();
Log.i("TAG", "Received: " + obj.toString());
in.close();
socket.close();
}
TCPIP connection will break. So client would have to connect again.
UDP will be ok provided your IP does not change after reconnection. Of course if you transmit UDP its not going to make a difference for that machine.
You should get an exception in case of TCPIP which you can handle.
UDP sockets that are not bound to the address will remain open, as they are stateless. TCP listening sockets not bound to the address will remain open as well.
Conntected TCP sockets may be severed (RST) or just linger until a timeout hits.
It is a little known fact that IP mandates it that a device by default will accept packets directed to any address it has configured on any interface, no matter on which interface the packet arrives. If this were not so, routing would be broken. One can use packet filters to filter out packets with non-matching addresses depending on the interface.

Categories

Resources