Receiving UDP data in Java - java

I'm trying to receive UDP data broadcast by PlayCap to network address 192.168.103.255 port 3000 in Java, but I'm having trouble setting things up. Here's what I have:
DatagramSocket socket = new DatagramSocket();
InetSocketAddress address = new InetSocketAddress("192.168.103.255", 3000);
socket.bind(address);
I'm getting "java.net.SocketException: already bound" from the bind call. I'm pretty inexperienced with networking, so I may be doing something way wrong here. Any help is appreciated.
Here is the stacktrace:
java.net.SocketException: already bound
at java.net.DatagramSocket.bind(Unknown Source)
at runner.main(runner.java:16)

I dont want to revive and old thread but i don't think the answer to this question is correct. I faced the same issue when i used the similar code to create a DatagramSocket.
DatagramSocket socket = new DatagramSocket();
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(InetAddress.getByName("localhost"), 5566));
This results in a SocketException
Exception in thread "main" java.net.SocketException: already bound
at java.net.DatagramSocket.bind(DatagramSocket.java:376)
at testapplication.TestApplication.main(TestApplication.java:25)
Java Result: 1
Not because there is another process occupying the same port but i have created an already BOUND datagram socket when i use the default constructor.
new DatagramSocket()
According to javadoc:
DatagramSocket()
Constructs a datagram socket and binds it to any available port on the
local host machine.
So the reason for the exception is you are trying to bind an already bound socket. To make it work you need to create an unbond socket with below constructor
DatagramSocket socket = new DatagramSocket(null);
InetSocketAddress address = new InetSocketAddress("192.168.103.255", 3000);
socket.bind(address);
Hope this helps...

Do netstat -a -o -n and from this you can find that either this port is already bind or not(even from this you can get all the bound ports).If yes , then try any other port :)

Most probably your application is running twice. Or you might be executing the same code twice. Even the same application may fail when binding twice.
Happens a lot for beginners that they didn't shut down their previous attempt (happened to me, too), and then their port is already in use. Make sure to add proper exception handling, e.g. by popping up a message "Port already in use."
Note that for listening you usually will bind a port only, without an explicit address (you might need to use "0.0.0.0" for this). Then you can receive both broadcast and unicast.
The code I use for listening to broadcasts is simply:
DatagramSocket s = new DatagramSocket();
s.bind(new InetSocketAddress(port))
Note that I'm not binding to a particular address, but only to a port.

Check the port 3000 it may be already used by another application. Try using a different port.

Related

Why and how am i supposed to use socket.accept() in python?

This accept() method return a tuple with a new socket and an address but why do i need a new socket if i already have one, so why don't use it?
import socket
sock = socket.socket()
sock.bind(('', 9090))
sock.listen(1)
conn, addr = sock.accept()
print 'connected:', addr
while True:
data = conn.recv(1024)
if not data:
break
conn.send(data.upper())
conn.close()
ps: When i program sockets in Java, i don't really have this kind of accepting stuff and i only need one socket per client and one per server, which makes sense.
You have one listening socket active while the server is running and one new connected socket for each accepted connection which is active until the connection is closed.
Seems like you haven't implemented TCP in Java before.
The example you are providing with, uses a default AF_INET and SOCK_STREAM which by default is TCP:
socket.socket([family[, type[, proto]]])
Create a new socket using the given address family, socket type and protocol number. The address family should be AF_INET (the default), AF_INET6 or AF_UNIX. The socket type should be SOCK_STREAM (the default), SOCK_DGRAM or perhaps one of the other SOCK_ constants. The protocol number is usually zero and may be omitted in that case.
If you were implemented SOCK_DGRAM which is UDP, you wouldn't need to be using sock.accept()

UDP broadcast client in Java

I am using UDP broadcast for interservice communication The server is in Python and I can see the UDP messages using this code:
import sys
import socket
HOST = ''
PORT = 9002
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
s.bind((HOST,PORT))
while True:
try:
message = s.recv(8192)
print("Got data: " + message)
except KeyboardInterrupt:
sys.exit()
I can run as many of these clients simultaneously as I want on the same machine.
I'm trying to implement a similar client in Java using the DatagramSocket class, but I keep getting an "address already in use" error. Evidently I need to construct it differently than I am currently:
DatagramSocket socket = new DatagramSocket(broadcastPort);
Is it possible to get the same behavior as the Python code?
Try this:
// create an unbound socket
DatagramSocket socket = new DatagramSocket(null);
// make it possible to bind several sockets to the same port
socket.setReuseAddress(true);
// might not be necessary, but for clarity
socket.setBroadcast(true);
socket.bind(new InetSocketAddress(9002));
The null argument to the constructor is the key here. That wisdom is hidden in the second paragraph of the javadoc for the DatagramSocket(SocketAddress bindAddress) constructor:
if the address is null, creates an unbound socket.
Address already in use probably means you haven't properly terminated your programs. If you're using Eclipse, make sure you check all your open consoles and terminate all of them. (Top right corner, blue box - click it and it'll show all running programs)
In Eclipse, just because you "run" your program again, it doesn't terminate the previous one(s).
Another possible issue is that you may be using the same port as your python server. 2 Applications can't claim the same port, so just change the port number if that is the case.
Edit: Use a MulticastSocket.

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.

specifying source and destination port on socket

I am creating a socket for TCP communication and would like to know how to specify a source port.
Socket socket = new Socket();
socket.connect(dstAddress);
After creating your new socket, call bind() with the local port number you want to use, then connect to the remote host.
#EJP is correct, though. Don't do this lightly since you can end up not being able to create the socket if something else happens to be using that port or even if your program has recently used it and closed it.
If it's not working, you may need to look at the library you're using.
Socket has multiple constructors. Try this one
You have to use InetSocketAddress, declared in the package java.net. The easiest way to use it is:
InetSocketAddress(host, port)), something like this:
Socket socket = new Socket();
socket.connect(new InetSocketAddress("http://myserver.com", 80));
Which connect to the web server listening on the port 80 in myserver.com.

Android: java.net.DatagramSocket.bind: Invalid Argument Exception

Background: I'm writing a simple UDP application to ping a beta server I manage every minute or so to tell me it is still up and running (I can't enable ping on the server for those that are wondering). I plan to run this on my phone to warn me when the server is no longer responding.
I'm trying to use the seemingly simple java.net.DatagramSocket as such:
try
{
socket = new DatagramSocket();
socket.bind(null);
}
catch (SocketException e)
{
System.out.println(e.toString());
throw e;
}
Let me also say that I have enabled the Internet permissions through the android manifest and if I remove the uses clause to do so, I get a permissions error so I'm sure that is working OK. When I download this code to an Android Virtual Device (AVD) and execute it, on the call to bind() I am presented with this exception:
03-17 19:07:39.401: INFO/System.out(338): java.net.BindException: Invalid argument
According to this documentation, the null argument is correct:
public void bind (SocketAddress localAddr)
Since: API Level 1
Binds this socket to the local address and port specified by localAddr. If this value is null any free port on a valid local address is used.
But not trusting documentation, I decided to enumerate the IP addresses on my device like this:
ArrayList<NetworkInterface> allInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
NetworkInterface eth = allInterfaces.get(0);
InetSocketAddress addr = new InetSocketAddress(eth.getInetAddresses().nextElement(), port);
try
{
socket = new DatagramSocket();
socket.bind(addr);
}
catch (SocketException e)
{
System.out.println(e.toString());
throw e;
}
When I step through the code, it works great and I can see the two IP address on the AVD but I get the exact same exception on the bind() call. Does anybody out there see what i might be missing? I will continue to research and hopefully post a solution to my own problem, but I am hoping somebody out there will be able to shortcut this for me.
[Edited: if you saw my previous response I made the classic debugging mistake of changing two variable in one test and it was the other one that solved my problem.]
I found the problem. It is the way I'm declaring the DatagramSocket that appears to cause problems. If I use a DatagramChannel to open the DatagramSocket in the following way then the bind() call is successful.
DatagramChannel channel = DatagramChannel.open();
DatagramSocket socket = channel.socket();
I've stumbled across this problem either and have found the cause: if you call the parameterless constructor new DatagramSocket(), this creates "a UDP datagram socket which is bound to any available port on the local host using a wildcard address" (as per the API docs). So this actually means, the Socket is already bound. My "fix" for this is as follows:
SocketAddress socketAddress = new SocketAddress(yourInetAddress, yourPort);
DatagramSocket serverSocket = new DatagramSocket(null);
serverSocket.bind(socketAddress);
This explicitly creates an unbound Socket (through the DatagramSocket (SocketAddress localAddr) constructor), making it possible to bind the Socket in turn.
This is probably the more elegant solution than creating an unnecessary channel.
P.S.: Strangely enough, this is where DatagramSocket differs from a TCP ServerSocket: the parameterless constructor of the latter will create an unbound ServerSocket, not triggering this problem.

Categories

Resources