I'm devolping an SMS application that uses UDP protocol . My application need to do the following , client send to another client a message doesn't exceed 160 and he/she know the other client IP address . It will send through a server which will save it in case client is offline .
I started working on it but then I stopped ! I was having problem with these things .
How can multiple clients sends to server ? I searched about and I read about something called mutithreading , can anyone explain or give me example for it ?
also , I couldn't imagin the process of taking messages from clients and then saving it . I mean how the server know which message belong to which client ?
this is the code which I'm working on it
server :
import java.io.*;
import java.net.*;
class Server {
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new DatagramSocket(9876);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while(true)
{
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String(receivePacket.getData());
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
String senderSentence = "From "+IPAddress+" Msg "+sentence;
sendData = senderSentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress,
port);
serverSocket.send(sendPacket);
} } }
client :
import java.io.*;
import java.net.*;
public class Client {
public static void main(String args[]) throws Exception
{
String sentence;
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
DatagramSocket clientSocket = new DatagramSocket();
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
do {
System.out.println("Enter a msg , NOTE: don't exceed 160 charcter");
sentence = inFromUser.readLine();
}
while(sentence.length() >= 160);
System.out.println("Enter the adress of the other user");
String ip=inFromUser.readLine();
InetAddress IPAddress = InetAddress.getByName(ip);
sendData = sentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
clientSocket.send(sendPacket);
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String modifiedSentence =
new String(receivePacket.getData());
System.out.println("FROM SERVER:" + modifiedSentence);
clientSocket.close();
} }
Thank you ~
I'm not sure why you need to use UDP - but if this isn't some special requirement you might want to look at using a web server.
I quite like the Play Framework for Java, which is going to handle the threading for you. Every time you send a message to the server it is just like sending a request for a web page, so you can reply with JSON or XML or whatever you think is best.
This is going to be a lot easier than handling all the socket communication yourself - but as I say, maybe you have a special requirement.
Hope this helps!
Related
I have written UDP server client program. The problem that i am facing is that when i am running server program, it is not waiting for client to connect. Whole code is executing after running till the end. And when i am running client side in between of execution of server side, client side is receiving data from its point of execution. Here is my server code-
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new DatagramSocket(4321);
byte[] sendData;
String sentence = null;
FileInputStream file = new FileInputStream(new File("E:\\Deepak.txt"));
InetAddress IPAddress=InetAddress.getByName("localhost");
BufferedReader in = new BufferedReader(new InputStreamReader(file));
do{
while((sentence = in.readLine()) != null)
{
Thread.sleep(3000);
System.out.println(sentence);
sendData = sentence.getBytes();
DatagramPacket sendPacket =new DatagramPacket(sendData, sendData.length,IPAddress,9876);
serverSocket.send(sendPacket);
}
}while(true);
}
Here is my client side code-
public static void main(String args[]) throws SocketException, UnknownHostException, IOException
{
DatagramSocket clientSocket = new DatagramSocket();
byte[] receiveData = new byte[1024];
String sentence ;
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
receivePacket.getLength();
System.out.println(receivePacket.getLength());
clientSocket.receive(receivePacket);
sentence = new String( receivePacket.getData());
}
}
UDP is connectionless, so there is no such thing as a connection in it.
You can only send a packet (in a fire and forget way, send in java will send the data to the port specified in the Datagram) or receive packet on the port (receive in java will block until there is a packet received).
So you would need to implement your own connection on top of UDP if you want to have a server that only sends data if client "connects" to it.
So summing up:
send won't wait for anything, it will just throw the datagram on the wire
receive will wait for a datagram to arrive
Having the above information you would need to write your own protocol to keep the connection.
I have a question regarding how server can send udp packet to my laptop successfully when my laptop is behind a router and the server is using my external ip address. I was trying out udp client and server code. The code that i have used is in the following link.
http://systembash.com/content/a-simple-java-udp-server-and-udp-client/
Here is what i did.
First, i uploaded the server to a remote host.
import java.io.*;
import java.net.*;
class UDPServer
{
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new DatagramSocket(9876);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String( receivePacket.getData());
System.out.println("RECEIVED: " + sentence);
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
}
}
}
Then, i ran this client code from my laptop and it worked as suggested.
import java.io.*;
import java.net.*;
class UDPClient
{
public static void main(String args[]) throws Exception
{
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
DatagramSocket clientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String sentence = inFromUser.readLine();
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
clientSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String modifiedSentence = new String(receivePacket.getData());
System.out.println("FROM SERVER:" + modifiedSentence);
clientSocket.close();
}
}
But, my confusion is this.
In the following section in the server code
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
The server uses my external ipaddress. This request becomes successful since the client receives the sent packet. How is it possible since my laptop is behind a router?
To test if i can have the client send request to a server sitting in my laptop to check if it is really possible to send udp packets on machines behind a router, I put the server code in my laptop and then ran the client code in a remote machine. In the client code i updated the ipaddress to my external ipaddress which i got from printing the ipaddress of the received packet in the server code.
InetAddress IPAddress = receivePacket.getAddress();
System.out.println(IPAddress)
int port = receivePacket.getPort();
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
But, this approach doesn't work i.e the client at the remote machine cannot find the ipaddress of laptop which is expected.
But, how did the server send the request udp packet to my laptop successfully is my question? Thanks!
Usually, the server doesn't know your internal IP address, and it couldn't send you a packet there even if it did. What happens is that the router remembers that you sent a packet with a certain source port and forwards any replies back to you.
As stated in my title, I'm trying to build a very simple file transfer service in java. Right now, all I have been able to do in construct a simple client/server that can send and receive strings of text. Here is the code:
UDPClient.java:
import java.io.*;
import java.net.*;
class UDPClient {
public static void main(String args[]) throws Exception
{
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader
(System.in));
DatagramSocket clientSocket = new DatagramSocket();//port # is assigned by OS to the client
InetAddress IPAddress =
InetAddress.getByName("localhost");
byte[] receiveData = new byte[1024];
String sentence = inFromUser.readLine();
byte[] sendData = sentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length,
IPAddress, 7777); //data with server's IP and server's port #
clientSocket.send(sendPacket);
DatagramPacket receivePacket =
new DatagramPacket(receiveData,
receiveData.length);
clientSocket.setSoTimeout(1000);
clientSocket.receive(receivePacket);
// we still need to catch the exception and retry
String modifiedSentence =
new String(receivePacket.getData(),
0,
receivePacket.getLength());
System.out.println("FROM SERVER:" +
modifiedSentence);
clientSocket.close();
}
}
UDPServer.java
import java.io.*;
import java.net.*;
class UDPServer {
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new
DatagramSocket(7777); //server will run on port #9876
byte[] receiveData = new byte[1024];
while(true)
{
DatagramPacket receivePacket =
new DatagramPacket(receiveData,
receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String(
receivePacket.getData(),
0,
receivePacket.getLength());
InetAddress IPAddress =
receivePacket.getAddress(); //get client's IP
int port = receivePacket.getPort(); //get client's port #
System.out.println("client's port # =" + port);
System.out.println("client'sIP =" +IPAddress);
System.out.println("client's message =" +sentence);
String capitalizedSentence =
sentence.toUpperCase();
byte[] sendData = capitalizedSentence.
getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData,
sendData.length,
IPAddress, port);
serverSocket.send(sendPacket);
}
}
}
Ultimately what I'd like to do is send a file path to the server, have the server return the file, and then save it to a predetermined location like C:\Desktop\Folder.
I'm really at a loss for how to advance past where I am, so any advice, pointers, or resources that you could share would be great. I'm very new at this and feeling way out of my depth.
Thanks!
Unlike TCP UDP uses a non-persistent connection. Therefore, you will have to maintain state in the request and response packets.
For example, the request packet could look as follows.
2 bytes - File name length
(variable) - File name 4 bytes - Start position
4 bytes - Seq. no.
4 bytes - Max chunk size
Server will read upto 'Max chunk size' bytes from 'Start position' and return to client in following format. The Seq. no. will be echoed back from request so client can relate request with response.
1 byte - Response code
4 byte - Seq. no.
4 bytes - Payload length
(variable) - Payload
I have to send a UDP packet and get a response back from UDP server. I though UDP was analogous with a java.net.DatagramPacket in Java, but the documentation for DatagramPacket seems to be that you send a packet but don't get anything back, is this the right thing to use or should I be using java.net.Socket
Example of UDP datagram sending and receiving (source):
import java.io.*;
import java.net.*;
class UDPClient
{
public static void main(String args[]) throws Exception
{
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
DatagramSocket clientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String sentence = inFromUser.readLine();
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
clientSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String modifiedSentence = new String(receivePacket.getData());
System.out.println("FROM SERVER:" + modifiedSentence);
clientSocket.close();
}
}
You have to use a DatagramPacket and a DatagramSocket. When you send a packet you just send a packet. However when you receive a packet you can get a packet which was sent from another program (e.g. the servers reply)
http://docs.oracle.com/javase/7/docs/api/java/net/DatagramSocket.html
Socket is only for TCP connections.
The Java documentation does cover how to write a client and a server.
http://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html
You want to look at DatagramSocket#receive
That's precisely the distinction between UDP and TCP sockets.
UDP is broadcast, whereas TCP with java.net.Socket is point to point. UDP is fire-and-forget, analogous to publishing a message on a JMS Topic.
See: http://docs.oracle.com/javase/tutorial/networking/datagrams/index.html
This is kind of a followup to the question I had yesterday. I had a homework assignment to send and receive data with a client/server TCP socket connection. I would like to make a version of it using UDP. The idea is that I can redirect standard I/O and send the streams using UDP. For example, if I type in:
server: java UDPServer 5555 < file1.txt
client: java UDPClient localhost 5555 > file2.txt
It should send the data in file1.txt from the server to client's file2.txt. When I run the client/server pair in separate terminals, file2.txt is created but the data is never actually sent. Instead it seems like I am stuck in an infinite loop, where I cannot enter anything into the terminal unless I kill the application.
The server code is:
public static final int BUF_SIZE = 256;
public static void main(String[] args) throws IOException{
port = Integer.parseInt(args[0]);
DatagramSocket serverSocket = new DatagramSocket(port);
BufferedInputStream input = new BufferedInputStream(System.in);
BufferedOutputStream output = new BufferedOutputStream(System.out);
byte[] receiveData = new byte[BUF_SIZE];
byte[] sendData = new byte[BUF_SIZE];
byte[] buf = new byte[BUF_SIZE];
String sentence;
if(System.in.available() > 0) {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
InetAddress address = receivePacket.getAddress();
int bytesRead = 0;
while((bytesRead = input.read(buf, 0, BUF_SIZE)) != -1) {
sentence = new String(buf, 0, bytesRead);
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, address, port);
serverSocket.send(sendPacket);
}
} else {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
sentence = new String(receivePacket.getData());
output.write(sentence.getBytes());
}
serverSocket.close();
input.close();
output.close();
}
And the client code is:
public static final int BUF_SIZE = 256;
public static void main(String[] args) throws IOException{
String hostName = args[0];
port = Integer.parseInt(args[1]);
DatagramSocket clientSocket = new DatagramSocket();
InetAddress address = InetAddress.getByName(hostName);
BufferedInputStream input = new BufferedInputStream(System.in);
BufferedOutputStream output = new BufferedOutputStream(System.out);
byte[] sendData = new byte[BUF_SIZE];
byte[] receiveData = new byte[BUF_SIZE];
byte[] buf = new byte[BUF_SIZE];
String sentence;
if(System.in.available() > 0) {
int bytesRead = 0;
while((bytesRead = input.read(buf, 0, BUF_SIZE)) != -1) {
sentence = new String(buf, 0, bytesRead);
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, address, port);
clientSocket.send(sendPacket);
}
} else {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
sentence = new String(receivePacket.getData());
output.write(sentence.getBytes());
}
clientSocket.close();
input.close();
output.close();
}
I am still new to socket programming so I am basing this off of example code in my textbook. Is there some glaring mistake that I am making that is preventing the data from being transferred? Thanks very much for your patience and help!
The first problem you have is that client.main doesn't run because your shell command is wrong. For some reason, with Java you can't redirect output how it's traditionally done. You can simply put a few print statements at the beginning of client.main to see nothing executes. Try this:
java UDPClient localhost 5555 | tee file2.txt
See redirect Java output.
The other problem you have is that both the client and server are waiting to receive a datagram. You have in the server code:
if(System.in.available() > 0) {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
And you have in the client code:
else {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
sentence = new String(receivePacket.getData());
output.write(sentence.getBytes());
}
Note that the else statement will always execute because System.in.available will always return 0. Remember your not redirecting input to the client, so there's nothing in System.in. To fix this you need to first send a client datagram so that the server can respond with the contents of file2.txt.
You're missing all the things you need to do to make this work. Where's the code to do transmit pacing, retransmissions, acknowledgements, reordering, and so on? If you want to use UDP, you have to do yourself all the things TCP does for you.
See, for example RFC 1350 for an example of a file transfer protocol layered on top of UDP.