Despite me knowing that my UDP packets are arriving as expected (via Wireshark), and having the Windows firewall turned off - my very simple Java code never receives any packets.
byte[] buffer = new byte[2048];
DatagramSocket socket = new DatagramSocket( 50000 );
DatagramPacket packet = new DatagramPacket( buffer, buffer.length );
socket.receive( packet );
I have 3 network adapters on my machine, so I tried being very specific about IPs. I tried setting the socket to look at the local address the packets were arriving on - didn't receive anything. And I also tried connecting the socket to the remote IP the packets were being sent on - didn't receive anything. All the while Wireshark is seeing all the 160 packets per second arriving...
My only other thought was that I'm not calculating the UDP checksum on the sending end (the UDP packets are assembled 'by hand' on an embedded system), it is just being set to 0x0000 - does DatagramSocket discard UDP packets without a checksum!?
I wrote a simple test server to aid diagnosing the problem per #Andreas' suggestion.
InetAddress outAddr = InetAddress.getLocalHost();
InetAddress inAddr = InetAddress.getByName( "192.178.178.0" );
byte[] buffer = ( "Hello" ).getBytes();
DatagramSocket socket = new DatagramSocket( 50000, outAddr );
while ( true ) {
DatagramPacket packet = new DatagramPacket( buffer, buffer.length,
inAddr, 50000 );
socket.send( packet );
try {
Thread.sleep( 500 );
} catch ( InterruptedException e ) {
// Ignore.
}
}
Wireshark dutifully notes that it is receiving them all - but my client still doesn't, even when the receiving IP is explicitly set:
InetAddress inAddr = InetAddress.getByName( "192.178.178.0" );
DatagramSocket socket = new DatagramSocket( 50000, inAddr );
...
socket.receive( packet );
Something odd I have just noticed though, when I check which NetworkInterface is being used for sending and receiving, Java reports back the right one (the one 'owning' 192.178.178.0) - but Wireshark only sees my test server packets on a different network device. Any ideas on what is going on?
Ok, well this is embarassing. I turned off the Windows firewall for Private and Work networks - but it turns out Windows considered the one I actually needed to be a Public network...
It works fine now. I considered deleting this question, but hopefully it will help some other muppet.
Related
I'm working on a project that is suppose to send a file from one machine to another using DatagramPackets and DatagramSockets. The implementation is suppose to mimic the TCP protocol. So once the receiver gets a packet it sends back an ACK to the sender, confirming the packet was delivered. My program so far without making any checks for ACKs. Im having trouble implementing the ACK messages. On my receiver program, it shows that the ACKs are being sent, but the sender application is not getting them.
I keep getting an error from creating the socket. "java.net.BindException: Address already in use: Cannot bind". I'm confused because nowhere else in the sender applicaion have a specified the port. I simply use DatagramSocket socket = new DatagramSocket();
but I do use
DatagramPacket packet = new DatagramPacket(packetData, packetData.length, internetAddress, 49000);
socket.send(packet); when sending packets.
I have tried removing the datagram declaration in my waitForAck() method and used the same datagramSocket I used to send packets. But socket.receive(packet); will hang and never recieve anything because it hasnt been assigned a port to listen on.
This is my method to listen for ACKs:
public void waitForACK(){
//listen for ack for a period of time
//if ACK received, then break send next packet
//if ACK not received or time out, send last packet
//TODO: implement a timeout
System.out.println("### Sender waiting for ACK");
try {
DatagramSocket receivingSocket = new DatagramSocket(49000);
while (!ACKreceived) {
byte[] buf = new byte[1500]; // Actual Ethernet packet size is 1500 bytes
// receive request
DatagramPacket packet = new DatagramPacket(buf, buf.length);
receivingSocket.receive(packet); //socket.receive(packet); <--
byte[] packetData = Arrays.copyOf(packet.getData(), packet.getLength());
ACKreceived = checkACK(packetData);//check the recieved packet contains an ACK message
}
System.out.println("### Sender recieved ACK");
} catch (Exception e) {
System.out.println("### never got ACK");
System.out.println(e);
}
}
I've also tried this but the scoket will hang and never actualy recieve anything. Even though the application that recieves the file successfully reports sending an ACK. I'm guessing its because it does not know to recieve the ACK on port 49000.
public void waitForACK(){
//listen for ack for a period of time
//if ACK received, then break send next packet
//if ACK not received or time out, send last packet
//TODO: implement a timeout
System.out.println("### Sender waiting for ACK");
try {
while (!ACKreceived) {
byte[] buf = new byte[1500]; // Actual Ethernet packet size is 1500 bytes
// receive request
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet); //<--- HANGS RIGHT HERE
byte[] packetData = Arrays.copyOf(packet.getData(), packet.getLength());
ACKreceived = checkACK(packetData);//check the recieved packet contains an ACK message
}
System.out.println("### Sender recieved ACK");
} catch (Exception e) {
System.out.println("### never got ACK");
System.out.println(e);
}
}
You're leaking sockets.
Don't create a new socket just to wait for an ACK. You should have exactly one DatagramSocket open for the life of the application.
Try to use the netstat command to check if another program (or even your program) is active on the port. On unix netstat -lp as su will show you, on windows netstat exists too with different command line options
Before we get into the problems with your code: Why is the client trying to listen on port 49000?
If you don't already realize this: the local port and peer port do not have to be the same, and generally are not. When you call DatagramSocket(), you get an arbitrary local port assigned by the OS. The fact that you sent to 49000 doesn't change your local port. And if the other side of the connection just sends back to the tuple it received a packet from, that won't arrive at 49000, it will arrive at your local port.
If that's your problem, the fix is to use the second version (just use your existing socket to listen as well as sending), and then fix the other side (that you haven't shown us the code for) to send the ACK to the complete address tuple of the packet's sender, not port 49000 on the sender's host.
If you realize that, but think that both sides need to have local port 49000 for some reason… well, they probably don't. Generally, a protocol needs one side (the "server") to have a well-known port to connect, but the other side (the "client") doesn't need that. That's why you can use DatagramSocket() instead of DatagramSocket(49000) on the client and things work.
Again, same fix.
In the rare cases where both sides really do need to have a well-known port (e.g., so you can explicit open it in your company's internal firewalls), you almost certainly want the sending to also happen on that port.
So, instead of creating a DatagramSocket() to send from, and a DatagramSocket(48000) to listen on, just create a DatagramSocket(48000) in the first place and use it for both.
However, note that this solution, like any solution that uses a fixed port, has two additional problems:
First, if client and server both want to bind port 48000, they can't both run on the same machine. You can renumber one of them to 48001, or just accept that.
Second, if you expect to start and stop the client frequently, it's often going to try to bind port 49000 while the OS still has a socket for that port in TIME_WAIT state, so you're going to get a bind error. This is what SO_REUSEADDR is for; use it.
What if you really do want to use an arbitrary-port sender on the client, but a fixed-port listener? There are some cases where that makes sense, but unless you can explain why you really need this, you don't have one.
If you do, then, and only then, could you use something like your first version. But you still probably want to create the listener socket once, not each time you listen for ACKs; it just should be a different attribute from the sending socket. (And of course you still need to deal with the same things as in the last section.)
And if you really do want to create a new listener socket for each ACK, then you have to make sure you close it immediately, rather than waiting for the Java GC and the OS to collectively get around to closing it for you, or the next time you wait for an ACK, you're likely to get a bind error, because the old listener socket is still bound to it.
I'm working on a game in Java, and I'm trying to communicate between a client and server on the same computer over the internet, and eventually between multiple computers. I used to be able to, but now the server doesn't seem to be receiving any packets from the client. I'll try to post all the relevant code.
This is on the server:
private DatagramSocket m_Socket = new DatagramSocket( 8000 );
private DatagramPacket m_DatagramPacket = new DatagramPacket( new byte[ 1024 ], 1024 );
...
while( true )
{
m_Socket.receive( m_DatagramPacket );
byte[] data = new byte[ 1024 ];
data = m_DatagramPacket.getData( );
System.out.println( "SERVER RECEIVING: " + data );
}
This is on the client:
private DatagramSocket m_Socket = new DatagramSocket( null );
private DatagramPacket m_DatagramPacket = new DatagramPacket( new byte[ 1024 ], 1024 );
...
m_DatagramPacket.setAddress( InetAddress.getByName( "72.49.50.49" ) );
m_DatagramPacket.setPort( 8000 );
m_DatagramPacket.setLength( length );
m_DatagramPacket.setData( data );
// "data" is the byte array, "length" is the length of the array
m_Socket.send( m_DatagramPacket );
I'm seeing the packet in Wireshark so I know it's sending.
EDIT: I may not understand how Wireshark works, is the screenshot below sending or receiving the packet?
Wireshark:
Firewall exception:
Port forwarding:
EDIT:
I also ran this port tester program to test port 8000 and it says the port is open
UPDATE:
For some reason I guess our routers were just refusing connections from the source local IP to the external IP destination. I can connect to the server using the local IP from the same network and using the external IP from a different network
If your client side you are creating an unbounded DatagramSocket (By passing null to the DatagramSocket(SocketAddress bindaddr)) which means there will not be any originating port for that socket. Eventhough this might work, this is clearly not the correct approach. In your client side you must do the following change.
private DatagramSocket m_Socket = new DatagramSocket();
private DatagramPacket m_DatagramPacket = new DatagramPacket( new byte[ 1024 ], 1024 );
Using the Default DatagramSocket constructor will bind the socket to next available port and will guarantee that there is a source port involved in the communication.
And your firewall exception doesn't have a Source IP and Source Port pattern or restriction. Please check based on your Router whether this is required.
Firstly, assuming that your IP and other codes you write but not in above is correct,I have done a lot of test, even tried to change the settings of the firewall.But it still works.
So, I think that maybe because of the unreliability of UDP protocol, your server sometimes can not receive the data from the client.You can just try to use TCP protocol.
Secondly, in your screenshot of PcWinTech.com v3.0.0 , it seems that your computer is in the subnetwork. So I gust that maybe the IP("72.49.50.49") is your router's IP, and I suggest you to check the settings of the router whether the router can transmit the data to your computer ,say, port forwarding.And I have just find a article that may help you.
I know its an old Question But the answer is really simple,
make the client create a request:
Client UDP ----- data Request ----> to server
the server is receiving with DatagramPacket,
after a client make a request, you can send the data using client's address and port,
Example:
byte[] buff = new byte[20];
DatagramPacket receive = new DatagramPacket(buff, buff.length, InetAddress.getByName(ADDRESS), PORT);
socket.receive(receive); // the server will wait to a client to connect
lets say the client sent Hello server
after that you could just do (the endpoint is for the client):
DatagramPacket sendData = new DatagramPacket(buff, buff.length, receive.getAddress(), receive.getPort());
socket.send(sendData)
I'm building a program that will connect every computer in my LAN to my computer, through DatagramSocket's and DatagramPacket's (in other words, I'll be the server and the others will be clients). I made some research and read the documentation, and found out how it worked, and I've actually been able to send and recieve data across the network. I had two options for the data sending method in the client class, which I thought were equivalent, but it seems not.
The first one (Client1):
DatagramSocket socket = null;
DatagramPacket packet = null;
try
{
byte[] data= "test".getBytes();
packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.0.26"), 325);
socket = new DatagramSocket();
socket.send(packet);
}
catch (Exception ex)
{
...
}
And the second one (Client2):
DatagramSocket socket = null;
DatagramPacket packet = null;
try
{
byte[] data= "test".getBytes();
packet = new DatagramPacket(data, data.length);
socket = new DatagramSocket(325, InetAddress.getByName("192.168.0.26"));
socket.send(packet);
}
catch (Exception ex)
{
...
}
These two options came when I was making tests sending data to and from my own PC. My IP address is 192.168.0.26. With the first one I had no problems, but the second one throws two kinds of exceptions. I can verify that Client1 works running the next code in the computer at the same time
(Server)
byte data[] = null;
try
{
data= new byte[1000];
socket = new DatagramSocket(325);
packet = new DatagramPacket(datos, datos.length);
socket.receive(packet);
System.out.println(datos);
}
catch (Exception ex)
{
...
}
If I run Server first and then the Client1 option, it actually recieves the data. When I run the Client1 first and then the Server, obviously don't get any data but neither get any exceptions. The real problem (and actual question, sorry about so many, perhaps useless, info) is with Client2. If this is ran before Server, I get NullPointerException:
java.lang.NullPointerException: null address || null buffer
at java.net.DualStackPlainDatagramSocketImpl.send(DualStackPlainDatagramSocketImpl.java:115)
at java.net.DatagramSocket.send(DatagramSocket.java:676)
generated when method send() is invoked. I know maybe I should ignore this; even thought I'm a little bit newbie with Socket's, it seems wrong to send data if you know nobody will recieve it. In the other hand, when Server runs first and then Client2, I get BindException:
java.net.BindException: Address already in use: Cannot bind
at java.net.DualStackPlainDatagramSocketImpl.socketBind(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.bind0(DualStackPlainDatagramSocketImpl.java:65)
at java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:95)
at java.net.DatagramSocket.bind(DatagramSocket.java:376)
at java.net.DatagramSocket.<init>(DatagramSocket.java:231)
at java.net.DatagramSocket.<init>(DatagramSocket.java:284)
from the line when the socket is initialized.
Due to that Client1 works, I'll use it; but I'd really like to know why does it work but Client2 doesn't. I read in another forum here about that BindException, and I understood it was caused when you attempt to use one port which is already in use, but in this sense Client1 should fail too. Could someone explain me the difference between Client1 and Client2?
You are binding to the same port, if you are running it on the same machine/address, you need to bind to different ports.
Like on the server:
socket = new DatagramSocket(325); //server binds its UDP/IP socket to port 325
On the client 2:
socket = new DatagramSocket(325, InetAddress.getByName("192.168.0.26"));
you are binding to the same port on the same machine/address that the "server" is using
On client 1:
packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.0.26"), 325);
//you are specifying the destination address and port the packet should be sent.
socket = new DatagramSocket();
//but in the DatagramSocket contructor you don't pass any address or port to bind to, so it will use an available port, not 325 as it is in use by the server.
As you said you are newly to network communication, be in mind that this is UDP/IP sockets, there's TCP/IP and others. UDP/IP is not connection oriented by specification, and does not guarantee the packet to be delivered.
While working on a Java application under Mac OS X (Lion, 10.7.2, Java version "1.6.0_29"), I'm running into a strange problem while trying to send multicast UDP datagrams. The packets are only being sent on one NIC, and I have no control over which one.
The following example code illustrates what I am trying to do:
public class MCast {
public static void main(String[] args) throws IOException {
InetAddress multicastAddr = InetAddress.getByName("224.0.0.1");
int port = 58680;
byte[] data = "test".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, multicastAddr, port);
MulticastSocket socket = new MulticastSocket();
socket.joinGroup(multicastAddr);
socket.setNetworkInterface(NetworkInterface.getByName("en0"));
socket.send(packet);
System.out.println("Packet sent.");
}
}
Whilst executing this code, I am using Wireshark to examine all the traffic going out on en0. No packets are sent on the port specified. However, said packets do appear on the trace for en1.
When I disable en1, the packets go out on en0 properly.
I'm at a loss here. Does anyone know what's going on?
Multicast output interface is decided by the current routing table at the time you do the group join. In most cases that means default route, hence the en0. Adding an explicit route would help, but you can just reverse the two lines in your code to be:
socket.setNetworkInterface(NetworkInterface.getByName("en0"));
socket.joinGroup(multicastAddr);
Also, you don't need to join (nor bind()) the group if you are only sending and not listening to that multicast traffic. Instead, connect() to the group address.
You can pass a an address to the constructor of MulticastSocket. You can use it to bind it to the address you want.
We use socket.send(packet) function in java to send a "packet" to a given port.
My problem is that i have to send a packet to a shutdown system using UDP protocol.
The problem with send() function is that first it verifies whether the host IP is
multicast or not. Now my local area network is of broadcast type. So i am having
problem is using this function.
can anyone please give me a way ?
Do you know how send udp packets in java?
First of all, broadcasting must be enabled in your network.
Then, all your servers must join to agreed multicast address.
InetAddress address = InetAddress.getByName( "230.0.0.1" );
MulticastSocket socket = new MulticastSocket( 12345 );
socket.joinGroup( address );
When you want to activate the system shutdown, send an agreed message (for example, "die") to the multicast address.
DatagramPacket packet = new DatagramPacket( buf, buf.length );
socket.receive( packet );
String received = new String( packet.getData(), 0, packet.getLength() );
The servers when accept that message should initiate a shutdown flow.