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)
Related
I have a thread which periodically sends a datagram packet with the following setup:
DatagramSocket mySocket;
try {
mySocket = = new DatagramSocket(9999);
mySocket.connect(new InetSocketAddress(dstAddress, dstPort));
} catch (SocketException e) {
e.printStackTrace();
return;[![enter image description here][1]][1]
}
byte[] sentPacketBuffer = new byte[1];
DatagramPacket sentPacket = new DatagramPacket(sentPacketBuffer, sentPacketBuffer.length);
For each call of the send method:
mySocket.send(sentPacket);
I get a different source port on the receiver side.
I'v looked into this question, but the answer is actually related to setting the source port for the listener side.
Is there a way to make the source port (of the sender) persistent?
Edit
I used Android's VPNService to capture the received packets, and I dumped them to Wireshark:
As you can see only 1 packet has the correct source port.
Then I figured it might be related to the destination IP. The destination IP is not reachable from this device.
If I do make this address reachable (by connecting to 192.168.49.1, and having an interface in the same subnet) I get correct source port for all packets:
So, my question is now why does the destination reach-ability (or available interfaces) is related to the source port?
You are mistaken. The source port of datagrams sent by this code is always 9999.
NB Keep using the same socket. Creating and destroying a new one per datagram is pointless.
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.
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.
I'm just starting to learn about sending UDP packets, and I'm running into a problem. I've written a Java client and server which easily communicate with each other, and I've done a Python client/server combo, but I'm not sure how to send a UDP packet from Java and receive it in Python. Here's what I have for the Java client:
import java.io.*;
import java.net.*;
public class testclient {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
byte[] buf = new byte[256];
InetAddress address = InetAddress.getLocalHost();
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, Integer.parseInt(args[0]));
System.out.println("Sending...");
socket.send(packet);
System.out.println("Receiving...");
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
System.out.println(received);
System.out.println("Done!");
socket.close();
}
}
And the Python server:
from sys import *
from socket import *
host = gethostname()
port = int(argv[1])
address = (host, port)
print "Binding..."
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(address)
print "Receiving..."
data, client = sock.recvfrom(256)
print "Sending to", client
sock.sendto("Hi", client)
print "Closing..."
sock.close()
print "Done!"
All I'm trying to do here is send a request from the Java client to the Python server, then have the Python server send "Hi" back to the Java client, and have the client print the string. What happens for me is the client sends the packet, and the server waits at the sock.recvfrom(256) and never receives the packet (or that's what it looks like anyway).
Any ideas? I'm guessing it's some difference between how Java and Python handle the packets but, I'm not sure.
EDIT: Just for clarification, the port number is passed in via command-line arguments for both of these applications.
The problem must be within your code, they should be able to communicate: this
is a good example of writing a client server pair in java.
So, to start, I'm on Ubuntu 10.10.
I went into /etc/hosts and it looks like 127.0.0.1 was assigned to localhost.localdomain, while 127.0.1.1 was assigned to my machine's name. So, Python was using the localhost address, while Java was using my machine name address. I changed localhost to my machine name and everything works now.
Thanks everybody for trying to help!
In Java, I see where you create the packet, but I don't see you actually putting any data into the packet using setData before sending it.
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.