Sending Java Packets to Python Server? - java

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.

Related

Can't receive UDP Packets in Java

I'm trying to receive some UDP packets on a Java MulticastSocket.
I can see the packets arriving in wireshark and the code works for other people, but not for me.
I honestly don't know what I'm doing wrong.
I have disabled my firewall and antivirus.
I'm running Windows 10 and IntelliJ 2017.2.5.
I'm creating a MulticastSocket with a portnumber (2000 or 2001) as a parameter.
My JRE is 1.8.0_152 and I'm using the JDK supplied by JetBrains.
This is how I'm creating the MulticastSocket:
this.socket = new MulticastSocket(this.portNum);
//this.socket = new MulticastSocket();
this.socket.setReceiveBufferSize(1 << 17);
this.socket.joinGroup(InetAddress.getByName(this.ip));
And, in a while loop, I try to receive data like this:
while(!this.socket.isClosed())
{
byte[] buffer = new byte[500];
DatagramPacket incomingPacket = new DatagramPacket(buffer, buffer.length);
try
{
this.socket.receive(incomingPacket);
...
Things to check are:
Make sure you bind your UDP socket to the interface you want to receive on. This is different for Windows and for Linux. For Windows: Bind to the IP address of the interface you want to receive on. On Linux bind to 0.0.0.0 to receive on all interfaces. (Receiving just on a specific interface is non-trivial on Linux.)
Make sure your this.ip is your multicast address, e.g. 224.1.2.3.
The problem has been solved, it was an unrelated concurrency issue.

Is it possible to transfer (a String, for example) from a TCP Server to a UDP Client?

I'm working on TCP and UDP just to learn the basics of how networks and protocols work in Java, and the task my professor has set me is to have the following:
A TCP Client that connects to a TCP Server, which communicates with a UDP Client that connects to a UDP Server, which gets/alters data from a Database.
I have everything set up and working, but right now the TCP Server calls the UDP Client as an object, and passes its information through a method call, rather than over the internet.
For TCP I'm using server sockets and input stream / buffered stream readers, and for the UDP I'm using datagram packets. So I'm not really sure how I can send from one to the other directly, or if it's even possible.
Thanks in advance for any help/advice/guidance!
Jona
**EDIT:
What I mean by passing through a method call:
//In TCPServer class
UDPClient udpc = new UDPClient();
String result = udpc.GetFromUDPServer(clientCommand);
//In UDPClient class
public class UDPClient{
public String GetFromUDPServer(String clientCommand){
try{
//Create a datagram socket
DatagramSocket sock = new DatagramSocket();
byte[] buffer = clientCommand.getBytes("UTF-8");
InetAddress ipAddress = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, ipAddress, 447);
...

Java DatagramSocket sending but not receiving

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)

Why different DatagramSocket constructors behave so different? (BindException)

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.

UDP multicast sending on wrong NIC (Java, Mac OS X)

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.

Categories

Resources