Java - sending message from one PC to another via UDP connection - java

When I tested with both client and server on localhost its works. But then I split the client and server to different machines with different IP addresses and now the packets are not being received on the client side. Can anyone spot the problem with my code:
Client:
class Csimudp {
public static DatagramSocket ds;
public static byte buffer[] = new byte[1024];
public static void Myclient() throws Exception {
while (true) {
DatagramPacket p = new DatagramPacket(buffer, buffer.length);
ds.receive(p);
System.out.println(new String(p.getData(), 0, p.getLength()));
}
}
public static void main(String args[]) throws Exception {
System.out.println("for quitting client press ctrl+c");
ds = new DatagramSocket(777);
Myclient();
}
}
Server:
class Ssimudp {
public static DatagramSocket ds;
public static byte buffer[] = new byte[1024];
public static void MyServer() throws Exception {
int pos = 0;
while (true) {
int c = System.in.read();
switch (c) {
case '~':
System.out.println("\n Quits");
return;
case '\r':
break;
case '\n':
ds.send(new DatagramPacket(buffer, pos, InetAddress
.getByName("117.201.5.150"), 777));
pos = 0;
break;
default:
buffer[pos++] = (byte) c;
}
}
}
public static void main(String args[]) throws Exception {
System.out.println("server ready....\n please type here");
ds = new DatagramSocket(888);
MyServer();
}
}

I would hazard a guess that your packets are being blocked by a firewall somewhere in their way. I'd start by opening the appropriate outgoing and incoming UDP ports in the firewalls of the client and the server respectively.
Or your server might be sitting behind a NAT gateway and you need to set up port forwarding rules for it to receive any packets. For example, most ADSL routers are actually set up as a NAT gateway.
Another potential issue is your port selection:
You are binding your client to a specific local port. There is no need for that - let the OS select a free port on its own. This would also remove the possibility of trying to use a port that is already in use.
You are using ports in the [0-1023] range. This port range is generally reserved for well-known services - as a matter of fact, on most Unix-like systems (e.g. Linux) you cannot bind a listening port in that range without root privileges. As a result, quite a few ISPs will filter that port range in their firewall, supposedly to protect their users.
Without more information on the networks that connect the client to the server, it's quite hard to provide a more concrete answer.
PS: There is no need to recreate the InetAddress object in every iteration of your loop - do it once beforehand...
PS.2: In general the computer that sends the first packet in a UDP session is considered the client, since it's also the one that can exist without a fixed address. Your assignment of the client/server roles is reversed in that respect. So when reading my points above, you will have to reverse the client/server specifications for them to apply to your code...

Related

Client Server communication and underlying TCP states

I run the following Client-Server code on a linux box
Server Code
public class MyServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(6868, 5);
while (true) {
Thread.sleep(5000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Client Code
public class MyClient {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket[] clients = new Socket[8];
for (int i = 0; i < 6; i++) {
clients[i] = new Socket("175.27.3.4", 6868);
System.out.printf("Client %2d: " + clients[i] + "%n", i);
//clients[i].close();
}
for (int i = 6; i < 10; i++) {
clients[i] = new Socket("175.27.3.4", 6868);
System.out.printf("Client %2d: " + clients[i] + "%n", i);
//clients[i].close();
}
}
}
Note-
I have not "ACCEPTED" the client request to test the ServerSocket
backlog argument.
The two loops in the client code are deliberate to help debug the
code.
The Server box is a Cent OS
The Client box is Cent OS (different physical server)
The client sockets are NOT closed deliberately.
After executing the Server code and later Client code I observe the following
On the server using netstat, I see 6 connections in ESTABLISHED
state
On the server using netstat, I see 4 connections in SYN_RECV
state(backlog queue full)
On the client machine, I see all 10 connections in ESTABLISHED
state- Is this normal?
In the wireshark on the server side (tcpdump) for the first 6
connections, I see a proper 3 way handshake for connection
establishment (SYN, SYN-ACK, ACK)
For the next 4 connections , in the wireshark on the server side, I
see (SYN [sometimes multiple], SYN-ACK, ACK, then many Duplicate
SYN-ACKS)
Question -
Are all the above observations normal?
Are the observations system dependent (OS) ?
Bigger Picture
Please refer here OR ServerFault for detailed explanation
I am trying to simulate the production issue on a smaller scale with
the above code
In the production code (which I did not write but I maintain it) the
server socket has a backlog argument as 100.
I suspect the backlog queue is full and hence the newer connections
are dropped.
I see plenty of SYN requests but not many SYN-ACKS in the production
wireshark which is a hour long. Does it ring a bell and can we draw
parallel with the toy code above?

Making a Multicast Socket accessible from another Thread

Right now I have a device sending out UDP messages to a multicast group. I wrote a small Java program that can detect these packets by joining the group and looking to the right port. I use the MulticastSocket.receive(packet); command. I am moving on to writing a program with a GUI for this purpose. I want a user to be able to specify an amount of time, and for my program to look for packets for this amount of time. I've done a lot of research and found that the best way of doing this, cutting off the receive command when it is blocking a port, is to close the port prematurely. In order to do this, I have my program open up another thread, and use the new thread to watch for the UDP packets while my main thread sleeps for the specified time. It is detecting the packets just fine. However, I cannot seem to access it from the main thread to close the port. Here is my code:
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
public class MulticastClient_v2 extends Thread
{
public volatile MulticastSocket socket;
public void run()
{
try {
//Declare the port and IGMP Group IP
MulticastSocket socket2 = new MulticastSocket(5000);
InetAddress address = InetAddress.getByName("224.0.1.2");
//Display connection information
System.out.println("Joining 224.0.1.2 on port 5000");
//Join the Multicast Group
socket.joinGroup(address);
//Declaring a DatagramPacket
DatagramPacket packet;
//Starting an infinite loop
//while (true)
//{
System.out.println("Waiting on packets..");
byte[] buf = new byte[1024];
packet = new DatagramPacket(buf, buf.length); //Declaring an internal DatagramPacket
socket.receive(packet); //Receiving a Packet
String received = new String(packet.getData(), 0, packet.getLength());
InetAddress senderAddress = packet.getAddress(); //Get the InetAddress object
String forFun = senderAddress.getHostAddress(); //Extract the IP address of sender in text format
if (received.indexOf("Product1") >= 0) //Searching the raw data for "Product1"
{
//If found, display the IP and device type
System.out.println("Product1 found at " + senderAddress);
}
if (received.indexOf("Product2") >= 0) //Searching the raw data for "Product2"
{
//If found, display the IP and device type
System.out.println("Product2 found at " + senderAddress);
}
//}
}
catch(IOException ex)
{
System.out.println (ex.toString());
}
}
public static void main(String[] args)
{
MulticastClient_v2 thread = new MulticastClient_v2();
thread.start();
try {
Thread.sleep( 3000 );
thread.socket2.close();
}
catch(InterruptedException in)
{
System.out.println("Interrupted Exception!");
}
System.out.println("Done.");
}
}
So, when I try to compile, I get the following error:
MulticastClient_v2.java:63: error: cannot find symbol
thread.socket2.close();
^
symbol: variable socket2
It seems to me, that the main method cannot see socket2 with is in another method. My question is how to I make it available to see? I experimented a bit with the
public volatile MulticastSocket socket;
and the main method can access it, but I can't connect to a certain port when I'm in the run method. The only thing I could find that may do this is bind(). But bind() requires both an IP and a port, whereas when I first declare a Multicast socket, I can declare just the port like so:
MulticastSocket socket2 = new MulticastSocket(5000);
Any help would be very much appreciated! I've been stuck on this a while now.
EDIT: I've gotten some suggestions. First, that I should declare and initialize at the class level, this is giving me the following IO error:
MulticastClient_v2.java:8: error: unreported exception IOException; must be caught
or declared to be thrown
public volatile MulticastSocket socket = new MulticastSocket(5000);
^
So next, I tried putting it in a try..catch block at the class level, and I get this:
MulticastClient_v2.java:8: error: illegal start of type
try{
^
So I guess what I really need to do is initialize the Multicast Port at the class level then put it in a try block inside a method, as JTMon suggested. But I can't figure out a way to pick just its port without doing it during initialization.
EDIT 2:
I'm having difficulty still. If I try to initialize it like so in the class level:
public volatile MulticastSocket socket;
How can I edit its port later on in the run() method?
socket2 is a local variable, so it's scope is just the try block in which it is defined. Using a MulticastClient_v2 instance you could only access fields of that class.
Isn't socket2 declared as a local variable inside the run method? It would not be accessible from anywhere outside that method. Try declaring it at the class level first and see what happens.
I will try to put some code here to explain what I meant exactly.
Declare the variable socket2 at the class level.
The MulticastClient_v2 class should have a public consturctor of the type:
public MulticastClient_v2(int portNumber){
try{
socket2 = new MulticastSocket(portNumber);
}catch(IOException e){
//Do something with exception here
}
}
If the port number does not change you can hard code it in but this way is more flexible.
In the run method you can now use the initialized socket and you can still access it from outside the class. Just for the record though I would prefer you make the access through another method on the thread, but that might be a discussion for another thread ;)

Java - UDP sending data over socket.. not rec. all data

It would seem that the Client - Server application i wrote does work however it seems that not all data is processed every time.
I am testing it on a local machine in Eclipse env.
Server:
private void sendData() throws Exception
{
DatagramPacket data = new DatagramPacket(outgoingData, outgoingData.length, clientAddress, clientPort);
InputStream fis = new FileInputStream(responseData);
int a;
while((a = fis.read(outgoingData,0,512)) != -1)
{
serverSocket.send(data);
}
}
Client:
private void receiveData() throws Exception
{
DatagramPacket receiveData = new DatagramPacket(incomingData, incomingData.length);
OutputStream fos = new FileOutputStream(new File("1"+data));
while(true)
{
clientSocket.receive(receiveData);
fos.write(incomingData);
}
}
I used to have if else in the while(true) loop to check if packet length is less than 512 bytes so it knew when to break;
I was thinking there was a problem whit that but seems that was oke for now i just wait few minutes and then stop the Client.java app
The file does transfer but the original file is 852kb and so far i got 777, 800, 850,.. but never all of it.
The fundamental problem with your approach is that UDP does not guarantee delivery. If you have to use UDP (rather than, say, TCP), you have to implement a scheme that would detect and deal with packets that got lost, arrive out of order, or are delivered multiple times.
See When is it appropriate to use UDP instead of TCP?
You should probably use TCP to transfer files. You are probably losing packets because you are sending them so fast in that while loop.
int a;
while((a = fis.read(outgoingData,0,512)) != -1)
{
serverSocket.send(data);
}
since you're sending so fast I highly doubt it will have a chance to be received in the right order. some packets will probably be lost because of it too.
Also since your sending a fixed size of 512 bytes the last packet you send will probably not be exactly that size, so you will see the end of the file "look wierd."

Need help with udp socket programming in java

Hey guys I am working on a project where I need to broadcast a UDP packet on the actual internet and also receive them on the client. Currently I am using the multicast socket for broadcasting the packet on the local lan. I had come across this project called jstunt for NAT traversal of a UDP datagram but cant find any relevant documentation on it and also no implementation. I am familiar with the concepts of Nat Traversal, UDP hole punching but am facing the same problem as above, no relevant documentation and implementation. So can anyone please help and also suggest some other techniques for achieving this.
As the other poster has mentioned, you can't really "broadcast" a packet freely to the internet. If that were possible, networks could easily be DOS'd and incredible congestion would result. Even within controlled networks, broadcasts are usually tightly controlled so that they do not get out of hand. That said, perhaps you don't really need to "broadcast" the packet.
If you need to create a UDP "tunnel" across the internet, such as how P2P software works, it can be done. The trick is usually NAT. You mentioned you were already familiar with UDP hole punching, but couldn't figure out how to make it work. Here are some Java libraries that can be used for this:
http://www.masquerade.cz/en/nat-tunel-metodou-udp-hole-punching-v-jazyce-java/
http://ulno.net/projects/jpunch/
http://samy.pl/pwnat/
Also check out UPNP: http://en.wikipedia.org/wiki/Universal_Plug_and_Play
And the STUNT library: http://nutss.gforge.cis.cornell.edu/stunt.php
It's highly unlikely that your ISP, and your clients', will support UDP broadcast, let alone what the Internet backbone may or may not allow. You need to investigate that first. It's not a programming problem yet, it's a feasibility problem.
ITS BASIC DAY TIME SERVER IMPLEMENTATION USING UDP SOCKET ITS HELP YOU
CLIENT
import java.io.*;
import java.net.*;
public class DayTime_Client_Udp
{
public static void main (String[] args) throws IOException
{
String hostname= "localhost";
int port=13;
if ((args.length == 1))
{
hostname=args[0];
}
else if ((args.length==2))
{
hostname=args[0];
port=Integer.parseInt(args[1]);
}
InetAddress host = InetAddress.getByName(hostname);
DatagramSocket socket = new DatagramSocket ();
DatagramPacket packet=new DatagramPacket (new byte[100], 0,host, port);
socket.send (packet);
packet.setLength(100);
socket.receive (packet);
socket.close ();
byte[] data = packet.getData ();
String time=new String(data); // convert byte array data into string
System.out.println(time);
}
}
SERVER
import java.io.*;
import java.net.*;
public class DayTime_Server_Udp
{
public static final int DEFAULT_PORT = 3001;
public static void main (String[] args) throws IOException
{
if (args.length > 1)
{
throw new IllegalArgumentException ("Syntax: DaytimeServer [<port>]");
}
DatagramSocket socket = new DatagramSocket(args.length == 0 ?
DEFAULT_PORT : Integer.parseInt (args[0]));
DatagramPacket packet = new DatagramPacket (new byte[1], 1);
while (true)
{
socket.receive (packet);
System.out.println("Received from: " + packet.getAddress () + ":" +
packet.getPort ());
byte[] outBuffer = new java.util.Date ().toString ().getBytes ();
packet.setData (outBuffer);
packet.setLength (outBuffer.length);
socket.send (packet);
}
}
}
IF MORE HELP REQUIRED THAN COMMENT IT I ALSO HAVE OTHER PROGRAM WITH UDP BASD SO ITS HELP UU

Keep trying to contact server until response comes

I need to write a program with machines P0, P1 such that either machine can be started first and needs to contact other. Lets say P1 starts then it needs to keep trying contacting P0 until it gets an acknowledgment from P0. How can I do this using socket programming in Java.
If an exception is raised saying that P0 is not running then it still needs to keep trying rather than throwing exception for that. Or even if it throws an exception, how can I handle exception in such a way that it again repeats same things. I know that P0 will be manually run in few min.
Here's what I am doing
int P1Ack = 1;
while(P1Ack != 1) // where P1Ack is the acknowledgment that P0 sends if it gets a message from P1
{
P1connectsP0();
}
public void P1ConnectsP0()
{
String str = "Hello";
{
Socket clientSock = new Socket(lamport.P0Ip, lamport.P0Port);
ObjectOutputStream clientWriter = new ObjectOutputStream(clientSock.getOutputStream());
ObjectInputStream clientReader = new ObjectInputStream(clientSock.getInputStream());
clientWriter.writeObject(str);
clientWriter.flush();
}
catch(IOException ex)
{
System.out.println("Error : P1 unable to talk to P0");
ex.printStackTrace();
}
You seem to be using a Socket object here, which is a TCP socket in Java. The TCP protocol guarantees delivery of packets, so you don't need to do manual acknowledgement.

Categories