How to receive only actual data from a socket - java

i am sending 20 bytes of data from my udpserver to a client in java. At the client side i am receiving like this
byte[] buf = new byte[25];
final DatagramPacket recv = new DatagramPacket(buf,25);
String data = new String(recv.getData());
when i print data it is printing additional things. How can i only get my actual data. Please suggest.

You are sending 20 bytes, but you are allocating a receive buffer that can receive up to 25 bytes. The received datagram can be smaller, but you need to take the actual received length into account when constructing the String, eg:
String data = new String(recv.getData(), 0, recv.getLength());

Related

Socket connection between Java and Python

I have a simple Java Socket connected to my Python socketserver.
In the client I want to send some data with size given in input: I want first sent an Integer with the size of the data and then the chunk of byte data.
This is the client:
Integer size = 1234
Socket so = new Socket("10.151.0.248", 8000);
byte[] bytes = new byte[size];
DataOutputStream out = new DataOutputStream(so.getOutputStream());
out.writeInt(size);
out.write(bytes);
From the server side I would like to read the amount of data that will arrive first and then read the stream again till everything is received; as final step I will send back an ACK to the client.
Here is the server:
def handle(self):
tot_data = []
length = self.request.recv(4)
size = struct.unpack("!i", length)[0]
while len(tot_data) < size:
data = self.request.recv(size - len(tot_data))
if not data: break
tot_data.append(data)
data = bytes(b"ACK")
# just send back the ack when transfer completed
self.request.sendall(data)
I am able to retrieve the size of the data in the server, but when I try to read the actual data from the stream, just 4 bytes are retrieved again and then the recv() remain blocked waiting for more data. I would like, first, to retrieve all the data, and then send back the ACK once the transfer is completed.
Any suggestions?
There one problem in the handle method Python side. self.request.recv returns a string (for Python 2.x, it will be bytes for Python3), and you assemble strings in an array. So the length of the array is just the number of chunks and not the number of bytes received.
You should write:
def handle(self):
tot_data = b""
length = self.request.recv(4)
size = struct.unpack("!i", length)[0]
while len(tot_data) < size:
data = self.request.recv(size - len(tot_data))
if not data: break
tot_data += data
data = bytes(b"ACK")
# just send back the ack when transfer completed
self.request.sendall(data)

Query an OpenTTD server

I am using the following java code to try to send a PACKET_UDP_CLIENT_FIND_SERVER (source) packet to query an OpenTTD server:
InetAddress address = InetAddress.getByName("publicserver-new.openttdcoop.org");
DatagramSocket socket = new DatagramSocket();
byte[] buf = new byte[]{0}; // 0 is number for CLIENT_FIND_SERVER, no extra data is needed (?)
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 3983);
socket.send(packet);
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
packet.getData(); //
socket.close();
However, when I run the program the server never returns any packets. I have very little experience working with packets, and have been trying to figure out what to do by looking at PHP and Python source code that does the same thing. Hopefully someone will be able to help.
Thanks
EDIT:
I realized that the packet should actually contain the data 03 00 00, the first two bytes contain the length, but I still haven't been able to get a response using a Packet Sender. Maybe I am listening on the wrong port?
I figured out what I had been doing wrong. This line:
byte[] buf = new byte[]{0};
should be:
byte[] buf = new byte[]{0x03, 0x00, 0x00} (hex for clarity)
The problem was that the first two bytes store the length of the data
The third byte is the actual request
In addition, the DatagamPacket needs to be reset to allow more than 3 bytes to be read

UDP Packet sent not being read by server correctly

I'm sending two packets from a client to server. The issue I'm having is the data being read on the server makes both strings the same length with regards to the longest string sent. For example:
if string 1 was : 1234
and string 2 was: abcdefghi
the server would read
1234efghi
abcdefghi
It should just display
1234
abcdefghi
My code is:
byte[] toSendUser = new byte[1024];
byte[] toSendPass = new byte[1024];
String name = "1234";
String password = "abcdefghi";
toSendUser = name.getBytes();
toSendPass = password.getBytes();
DatagramPacket packSend = new DatagramPacket (toSendUser, toSendUser.length, ipConn, 9876);
connection.send(packSend);
DatagramPacket packSendtwo = new DatagramPacket (toSendPass, toSendPass.length, ipConn, 9876);
connection.send(packSendtwo);
Could it be a server issue or is my code wrong in my client?
DatagramPackets in Java keep shrinking to the size of the smallest one received so far. You have to either create a new one per receive(), or at least reset the length every time before the next receive().

getOffset() of a packet returns 0 on the receiver's end

I have a lengthy text file that I am trying to transport across UDP on localhost so naturally I have to break up the byte buffer to send the file in packets.
The problem I'm having is this:
On the server side, I send a packet of data with the offset into the byte buffer set to say 500:
byte[] buf = text.getBytes();
InetAddress address = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(buf, 500, BYTES_PER_PACKET, address, udp_port_num);
System.out.println("Offset at server: " + packet.getOffset());
udpSocket.send(packet);
The print statement returns the expected answer of 500.
But then on the client side:
byte[] buf = new byte[BYTES_PER_PACKET];
DatagramPacket packet = new DatagramPacket(buf, BYTES_PER_PACKET);
udpSocket.receive(packet);
String received = new String(packet.getData());
System.out.println(received);
System.out.println("Offset: " + packet.getOffset());
It prints the correct text from the offset of the file in received, but packet.getOffset() always returns 0. Why isn't it returning the same 500 from the server and/or how can I get it to return the same 500 from the server?
Thanks in advance
The meaning of all this is:
At the sender you created a DatagramPacket using bytes 500..BYTES_PER_PACKET-500 of the source array.
You sent the packet. It went over the wire as a UDP datagram. It arrived as a UDP datagram.
At the receiver, you constructed a new byte array, and constructed a new DatagramPacket around it, specifying offset = 0, or no offset parameter. You received into the DatagramPacket. Java put the UDP datagram into the byte array in the DatagramPacket, starting at the offset you specified: zero.
Note that the sender's DatagramPacket did not itself go over the wire, nor the sender's byte array either.

Failed to convert data from UDP packet into the initial data which is sent using Java

I'm writing a UDP Client to transfer a file to a UDP server. First I try to measure the length of the file, devided by the buffer length to be sent in UDP packet, to get the number of packets required to be sent. I send this number to the server first to acknowledge it. But on the server side, the transform from byte array of the receiving packet into the initial number just failed. Can anyone help me out of this? Here is my code on the client side:
DatagramSocket socket=new DatagramSocket();
File f = new File(filename);
long fileSize = f.length();
byte[] buffer = new byte[16384];
long packetNumber = (fileSize/(buffer.length))+1;
DatagramPacket sendPacket=new DatagramPacket(buffer,buffer.length,addr,srvPort);
String str=Long.toString(packetNumber);
buffer = str.getBytes();
socket.send(sendPacket);
And here is the code on the server side:
DatagramSocket socket=new DatagramSocket(port);
byte[] buffer=new byte[16384];
DatagramPacket receivePacket=new DatagramPacket(buffer, buffer.length);
while(true)
{
socket.receive(receivePacket);
if (receivePacket.getData().toString().trim()!=null)
{
String str=receivePacket.getData().toString();
System.out.println(str);
long pcount=Long.parseLong(str);
System.out.println(pcount+" packets to be received.");
break;
}
}
But on the server side the variable pcount can always not be resolved, and when I try to print out the str, it writes out some "[B#60991f" or sth, weird.
This code doesn't make any sense.
Most networks won't let you send a datagram over 534 bytes reliably.
At present you are sending 16384 bytes of zero value, because you aren't putting anything into the buffer: instead you are creating a new buffer after creating the DatagramPacket. So you aren't sending anything yet.
And you aren't receiving anything yet either. The result of String.trim() cannot be null. You must reset the byte array in a DatagramPacket before every receive(), because it shrinks to the size of the actual received packet, so unless you reset it it keeps getting smaller and smaller. The result of toString() on a byte array does not include its contents, so parsing it is futile.
You need to study several basic Java programming concepts: too many to answer here.
You're receiving a byte array, using toString() won't give you anything.
You should reconstruct the String from the bytes array using new String

Categories