Here is my Sender program
import java.net.*;
class Send{
public static void main(String[] args) {
try{
//setup
DatagramSocket socket=new DatagramSocket();
byte[] buffer=new byte[100];
InetAddress address=InetAddress.getLocalHost();
System.out.println("Address:"+address);
DatagramPacket packet=new DatagramPacket(buffer,buffer.length,address,10000);
//get data
String data="Hello";
//send data
buffer=data.getBytes();
System.out.println("Sending data");
socket.send(packet);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
Here is the Receiver Program
import java.net.*;
class Listen{
public static void main(String[] args) {
try{
//set up
DatagramSocket socket=new DatagramSocket(10000);
byte[] buffer=new byte[100];
DatagramPacket packet=new DatagramPacket(buffer,buffer.length);
//recieve
System.out.println("Started Listening");
socket.receive(packet);
//print
String receivedData=new String(packet.getData());
System.out.println(receivedData);
System.out.println("Done!");
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
What I get is, when the Listener is running, it seems to be waiting for the sender to send data(prints "started Listening"). When sender is executed, it seems to run properly as well(prints "Sending data"). receiver executes further as well(prints "Done!"), but the packet remains empty.
What might be the problem?
The problem is that you never put anything in the packet. First you create an empty packet, then you fill a buffer with data - but that buffer isn't used in the packet.
Reverse the order of things:
String data="Hello";
//get data
// HERE : first put data in the buffer, THEN build the packet
byte[] buffer=data.getBytes();
InetAddress address=InetAddress.getLocalHost();
System.out.println("Address:"+address);
DatagramPacket packet=new DatagramPacket(buffer,buffer.length,address,10000);
//send data
System.out.println("Sending data");
socket.send(packet);
As Jon Skeet mentioned, you also need to worry about character encodings on both ends. If you don't specify an encoding when you do String.getBytes() or new String(byte[]) on the receiving side, then you will use the default character encoding on your computer. Which is fine if you're on the same computer, but can create a lot of problems if the sender and receiver are on different computers and the computers have different platform default character encodings.
So you need to specify the encoding, and your best best is probably UTF8, if most of the text you send is using the Latin script.
So on the sending side:
byte[] buffer = data.getBytes(StandardCharsets.UTF_8);
And on the receiving side:
String receivedData = new String(packet.getData(), StandardCharsets.UTF_8);
You are creating the data packet before filling the buffer with your data, hence you're sending an empty buffer.
Change the order of the lines as follows and your program works as expected:
//get data
String data="Hello";
buffer=data.getBytes();
DatagramPacket packet=new DatagramPacket(buffer,buffer.length,address,10000);
Related
I have written a client and server that are currently in an endless loop, that allow one message at a time to be sent and received. I need it to be able to continuously send/receive messages rather than be limited to one at a time.
Any idea on how I may go about this?
I am new to threads and not entirely sure how they work but i was thinking maybe a thread?
Client:
import java.io.*;
import java.net.*;
public class ClientChat {
DatagramSocket Socket;
public ClientChat(){
}
public void createAndListenSocket() throws SocketException, IOException{
while(true){
Socket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getLocalHost();
System.out.println("Type your message:");
BufferedReader message = new BufferedReader(new InputStreamReader(System.in));
byte[] incomingData = new byte[256];
String sentence = message.readLine();//"Testing from client";
byte[] data = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(data, data.length, IPAddress, 9876);
Socket.send(sendPacket);
System.out.println("Client: " + sentence);
DatagramPacket incomingPacket = new DatagramPacket(incomingData, incomingData.length);
Socket.receive(incomingPacket);
String reply = new String(incomingPacket.getData());
System.out.println("Server: " + reply);
//Socket.close();
}
}
public static void main(String[] args) throws IOException{
ClientChat client = new ClientChat();
client.createAndListenSocket();
}
}
Server:
import java.io.*;
import java.net.*;
public class ServerClient {
public void run() throws Exception{
DatagramSocket Server = new DatagramSocket(9876);
while(true){
byte[] buf = new byte[1024];
DatagramPacket incomingPacket = new DatagramPacket(buf, buf.length);
Server.receive(incomingPacket);
String message = new String(incomingPacket.getData());
System.out.println("Client: " + message);
System.out.print("Server: ");
BufferedReader response = new BufferedReader(new InputStreamReader(System.in));
String reply = response.readLine();
InetAddress IPAddress = incomingPacket.getAddress();
int port = incomingPacket.getPort();
byte[] data = reply.getBytes();
DatagramPacket replyPacket = new DatagramPacket(data, data.length, IPAddress, port);
Server.send(replyPacket);
}
}
public static void main(String[] args) throws Exception {
ServerClient Server = new ServerClient();
Server.run();
}
}
You are correct. You should use two threads - one for sending and one for receiving. You will also need two buffers to store the data while it's waiting to be send or processed after receiving. Most likely, you'll want FIFO buffers (a simple two-sided synchronized queue). Then, your main thread can only deal with reading/writing data to the queue, and the sending/receiving threads will take care of the rest in the background.
The sending thread should try to read from sending queue in a loop. The read operation on queue should block (pause the thread) until data is available.
The receiving thread should run in a loop to read a datagram from network and store it into a "received" queue. Reading datagram from network will block, while storing into a queue will return immediately unless the queue is full.
When the program is finished, you have to somehow "break" the threads from their loop. For example, you can set "shouldExit" boolean to true in your main thread, and check it in your send/receive threads. If you don't care, you can also set threads to daemon mode or just call System.exit().
Size your queues appropriately. If too small, messages will get lost and/or threads will be blocked a lot of time. If too large, you will waste memory. For example, estimate (or observe) the average and maximum number of messages in a queue, and add a safety margin.
We have some network controllers(Aruba) that can send HMAC-SHA1 signed messages to RTLS server on UDP port. We have written and simple Java program and deployed on a Linux server that receives the data packets on the UDP ports. The controllers use a key to sign the messages and hence we are getting the messages in the digested format as below. Is there a way we can extract the actual messages from this using the shared key ?
RECEIVED: *gdrÈ$�p��s�~�����q���2
RECEIVED: ,$drÈ�H)��5�r�[�b×C�` ��
RECEIVED: 0�
�����a��#�A�cL�i �?��
RECEIVED: +�dr��#J~e%��S�����??
Java code that receives the message:
public class UDPServer
{
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new DatagramSocket(9999);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String response = new String(receivePacket.getData(), 0,
receivePacket.getLength(), "UTF-8");
System.out.println("RECEIVED: " + response);
//
}
}
}
We found the message was serialized using google protubuf. Using the .proto file we were able to generate the required object and deserialize.
I know TCP is better to send file but I have a homework about sending file via udp protocol . Is there any code example in C# or Java about sending file?
I have server-client example to send and recieve message. I tried to send the file using the same way but could not succeed. I may need an algorithm to divide the file small parts and send them via datagram, and I have an idea to put "md5" of the part as header of the array to check if the packet is lost or not.
Here is my try , my server side in java;
// 1. creating a server socket, parameter is local port number
sock = new DatagramSocket(7777);
// buffer to receive incoming data
byte[] buffer = new byte[65536];
DatagramPacket incoming = new DatagramPacket(buffer, buffer.length);
byte []bigByteArray=new byte[1024*1024*1024*1024];
// 2. Wait for an incoming data
echo("Server socket created. Waiting for incoming data...");
ByteBuffer target = ByteBuffer.wrap(bigByteArray);
// communication loop
while(true)
{
try
{
sock.receive(incoming);
String s = new String(incoming.getData());
if(s=="finish") break;
target.put(incoming.getData());
}
catch(Exception e)
{
}
}
fos.write(bigByteArray);
fos.close();echo("RECIEVED");
and my client side;
String s;
Path path=Paths.get("C:\\Users\\Toshiba\\Desktop\\aa.txt");
byte[] data = Files.readAllBytes(path);
try
{
sock = new DatagramSocket();
InetAddress host = InetAddress.getByName("localhost");
//take input and send the packet
byte [] part;
for (int i = -1; i < data.length; i=i+100)
{
if(sock.isConnected())
{
part=Arrays.copyOfRange(data,i+1,i+100 );
}
else i=i-100;
}
byte [] f="finish".getBytes();
DatagramPacket finalpac = new DatagramPacket(f ,f.length , host , port);
sock.send(finalpac);
}
Thank you in advance.
Several issues:
The following isn't correct:
sock.receive(incoming);
String s = new String(incoming.getData());
The final line should be
String s = new String(incoming.getData(), incoming.getOffset(), incoming.getLength());
and if you aren't receiving text you shouldn't be converting the data to a String at all.
Remove the sock.isConnected() test. DatagramSockets are not usually connected, and you certainly haven't connected this one.
The loop in which this is embedded does nothing useful. You are only sending the word "finish".
I just want to send data to another device (PC) using UDP by clicking on a button. So I made a method for it in which I put the UDP code and made a relation when button is clicked. But according to the IDE, the byte which contains the String data I want to send is not well created.
Here's the code:
String argv = "WhatISend";
int port = 9268;
byte[] buffer= new byte[argv.lenght()];
try {
InetAddress server = InetAddress.getByName("172.16.19.14");
buffer = argv.getBytes();
DatagramSocket socket = new DatagramSocket();
DatagramPacket udp_emission = new DatagramPacket(buffer, buffer.length, server, port);
socket.send(udp_emission);
socket.close();
} catch (Exception e) {
System.out.println("Fail socket");
}
the problem is on "byte[] buffer= new byte[size];"
Based on the wording of your question, it sounds like you want buffer to contain the characters of the original string. However, the byte array actually does not contain the string data. The code you have shown us just creates a byte array that has the same length as the input string. You have not assigned the individual characters over to the buffer.
What you probably want is this:
buffer = argv.getBytes();
For more information, see String.getBytes().
I have a project require using UDP protocol to transfer file but still guaranty the feature of TCP protocol. That means we have the speed of UDP and the file not lost.
I've already have:
Server:
public class UDPServer {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
// TODO code application logic here
int port = 6788;
DatagramSocket sk = new DatagramSocket(port);
byte[] buf = new byte[1000];
while(true){
DatagramPacket request = new DatagramPacket(buf, buf.length);
sk.receive(request);
String msg = (new String(request.getData()));
DatagramPacket reply = new DatagramPacket(msg.getBytes(), msg.getBytes().length, request.getAddress(), request.getPort());
sk.send(reply);
}
}
}
Client:
public class UDPClient {
public static void main(String[] args) throws SocketException, UnknownHostException, IOException {
DatagramSocket sk = new DatagramSocket();
String msg = "message send";
InetAddress addr = InetAddress.getByName("localhost");
int port = 6788;
DatagramPacket request = new DatagramPacket(msg.getBytes(), msg.getBytes().length, addr, port);
sk.send(request);
byte[] buf = new byte[1000];
DatagramPacket reply = new DatagramPacket(buf, buf.length);
sk.receive(reply);
System.out.println("packet da nhan duoi client" + new String(reply.getData()));
sk.close();
}
}
and can you help me any suggest to guaranty file not lost ?. tks
You have quite big task, if you really want to implement fast and reliable file transfer with UDP.
With very small files (that fits in a single IP packet), it could be easy to avoid some overhead of TCP (like TCP connection opening and closing handshakes).
But If you are going to transfer bigger files, then you must implement many difficult features, like: flow control, selective acknowledges, re-transmissions and so on.
So I suggest to use TCP, instead of implementing own similar protocol.
You just CAN'T. It's not designed to be reliable.
If you manage to do it... it just means that you've implemented TCP yourself!, it will be much slower though.