I'm new to java network programming.
I try to send more than one instance of an object named Packet over UDP.
Sender: changes String to charArray, then sends each char in an object.
Receiver: receives the Datagrampacket and readObject then prints it out.
Sender is ok, but the receiver just takes the first instance of the object, and prints it as many times as the length of the charArray. Here is my code:
Receiver
public class Receiver {
public static void main(String args[]) throws Exception
{
DatagramSocket rcvSocket;
DatagramPacket rcvPacket;
ByteArrayInputStream bis;
ObjectInputStream ois;
byte[] rcvData;
Packet SnWPacket;
rcvSocket = new DatagramSocket(7777);
rcvData = new byte[1024];
rcvPacket = new DatagramPacket(rcvData, rcvData.length);
while(true)
{
rcvSocket.receive(rcvPacket);
byte[] in = rcvPacket.getData();
bis = new ByteArrayInputStream(in);
ois = new ObjectInputStream(bis);
SnWPacket = (Packet) ois.readObject();
System.out.println("RECIEVED: " + SnWPacket);
ois.close();
bis.close();
}
}
}
Sender
public class Sender {
public static void main(String args[]) throws Exception
{
DatagramPacket sndPacket;
DatagramSocket sndSocket;
ByteArrayOutputStream bos;
ObjectOutputStream oos;
InetAddress addr;
Scanner sc;
char[] charArray;
int seqNo = 0;
byte sndData[];
Packet SnWPacket;
addr = InetAddress.getByName("localhost");
sndSocket = new DatagramSocket();
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
sc = new Scanner(System.in);
System.out.println("Input: ");
String in = sc.nextLine();
charArray = in.toCharArray();
for (int i = 0; i < charArray.length; i++) {
SnWPacket = new Packet("data", seqNo, charArray[i]);
oos.writeObject(SnWPacket);
oos.flush();
sndData = bos.toByteArray();
bos.flush();
sndPacket = new DatagramPacket(sndData, sndData.length, addr, 7777);
sndSocket.send(sndPacket);
System.out.println("SENT: " + SnWPacket);
seqNo += 1;
}
oos.close();
bos.close();
sndSocket.close();
}
}
Packet
public class Packet implements Serializable{
private String type;
private int seqNo;
private char data;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getSeqNo() {
return seqNo;
}
public void setSeqNo(int seqNo) {
this.seqNo = seqNo;
}
public char getData() {
return data;
}
public void setData(char data) {
this.data = data;
}
public Packet(String type, int seqNo, char data)
{
this.type = type;
this.seqNo = seqNo;
this.data = data;
}
public Packet()
{
this.type = "";
this.seqNo = 0;
this.data = ' ';
}
#Override
public String toString() {
return "Packet: \tType: " + this.type + "\tseqNo: " + this.seqNo + "\tdata: " + this.data;
}
}
Assume that I send: "abc"
Sender:
SENT: Packet: Type: data seqNo: 0 data: a
SENT: Packet: Type: data seqNo: 1 data: b
SENT: Packet: Type: data seqNo: 2 data: c
Receiver:
RECIEVED: Packet: Type: data seqNo: 0 data: a
RECIEVED: Packet: Type: data seqNo: 0 data: a
RECIEVED: Packet: Type: data seqNo: 0 data: a
Problem is that receiver prints three "a". Please help me figure it out. Thanks!
To debug this sort of thing, it helps to use tcpdump or similar to track what is actually going on the network:
$ tcpdump -i lo port 7777
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
19:53:20.818460 IP zoo.59305 > zoo.7777: UDP, length 83
19:53:20.822292 IP zoo.59305 > zoo.7777: UDP, length 100
19:53:20.822410 IP zoo.59305 > zoo.7777: UDP, length 117
This tells you you're sending the 3 packets you expect, but each packet gets 17 bytes larger than the previous (instead of all being the same size). Examining your sending code carefully explains this -- you use a single ObjectOutputStream to construct the packets, and you don't reset it between Packet objects, so the first packet sent contains the first Packet object, while the second contains TWO packet objects (a copy of the first one, and then the scond one), and the third one contains all three.
On the receiver side, you only decode the first Packet object in the recieved packet and print it, so you print the first one three times...
Related
I have a client-server program trying to send a jpg file.
I'm trying to add an ACKNOWLEDGE byte and the DATA's BlockNumber byte to a UDP packet. I'm having trouble in this part of the code (this section of the code is just the DATA Block handling code from the Client program):
if(pType == TftpUtil.DATA){ //If byte 0 = 2 meaning it's a DATA block.
private int blockNumber = 1;
byte[] bn = intToBytes(blockNumber);
ByteBuffer buff = ByteBuffer.allocate(8); // For 2 ints, an int is 4 bytes long
buff.put(TftpUtil.ACK); // This is an "ACKNOWLEDGE byte", at position zero.
buff.put(bn); // This is supposed to be a byte containing the integer "blockNumber" meaning, what DATA block in the series it is.
buff.rewind(); // Not sure what this does. What does this do? Saw it in the code I copied.
DatagramPacket dataPacket = new DatagramPacket(buff.array(), buff.limit(), echoServerIP, 69); //Create datagramPacket
System.out.println("TftpClient sending a ACK on port " + clientSocket.getLocalPort());
clientSocket.send(dataPacket);
blockNumber++;
}
The above code doesn't work with the server I have, and the server was made by the Teacher. I've checked the server code, looks great.
For some reason it hangs on the part where it's supposed to send an ACKNOWLEDGE byte that contains the integer, "3" meaning "Acknowledged". And it's supposed to contain that ACK byte in position zero of the buff.array(). But the server says there's no acknowledge byte being received.
TftpUtil starts off like this:
public class TftpUtil {
//read request packet
public static final byte RRQ = 1;
//data packet
public static final byte DATA = 2;
//ack packet
public static final byte ACK = 3;
//error packet
public static final byte ERROR = 4;
//the maximum number of resent
public static final int MAX_RESEND = 5;
//data buffer size: 512
public static int DATA_BUFFER_SIZE = 512;
//packet buffer size: 2 bytes header + 512 bytes file data;
public static int PACKET_BUFFER_SIZE = DATA_BUFFER_SIZE + 2;
}
What the server's doing is it's sending a .jpg file, in DATA blocks of 512 bytes. The server picks up that there's a connection made, and tries to send the file. It sends the first DATA block, which seems to come through because when I check the folder, there is an asd.jpg file of 512 bytes. But when the client goes to send the ACK byte back, the server says it's incorrect and times out.
Can you see what's wrong with the code I've pasted or should I paste more code?
Thanks.
UPDATE full server code:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class server_v004 {
private InetAddress serverAddress;
private int serverPort;
private DatagramSocket serverSocket;
private static final ExecutorService exec = Executors.newFixedThreadPool(10);
public void startServer()
{
try {
String serverIpAddress = "192.168.1.32";
InetAddress echoServerIP = InetAddress.getByName(serverIpAddress);
serverSocket = new DatagramSocket(serverPort, echoServerIP);
System.out.println("TftpServer on port " + serverSocket.getLocalPort());
while(true) {
byte[] buf = new byte[1472];
DatagramPacket p = new DatagramPacket(buf, 1472);
System.out.println("waiting for connection ....");
serverSocket.receive(p);
server_v004ServerWorker worker = new server_v004ServerWorker(p);
exec.execute(worker);
}
}
catch(Exception e) {
System.err.println("Exception: " + e);
}
serverSocket.close();
return;
}
public static void main(String[] args) {
server_v004 tftpServer = new server_v004();
//tftpServer.checkArgs(args);
try{
tftpServer.parseArgsAndInit(args);
tftpServer.startServer();
}
catch(Exception e){
e.printStackTrace();
}
}
private void checkArgs(String[] args){
if(args.length <0) { //<1 //<2
System.out.println("Usage: TftpServer"); //server_port server_ip
System.exit(0);
}
}
private void parseArgsAndInit(String[] args) throws Exception{
//serverAddress = InetAddress.getByName(args[0]);
serverPort = 12345; //Integer.parseInt(args[1]);
}
}
class server_v004ServerWorker implements Runnable
{
//use to store RRQ request
private DatagramPacket req;
//client address who sent the RRQ request
private SocketAddress clientAddress;
//socket used to send the file data packets to client
private DatagramSocket sendfileSocket;
//byte buffer to store the file data
private byte[] dataBuffer = new byte[TftpUtil.DATA_BUFFER_SIZE];
//the first block sequence
private byte currentBlockSeq = 1;
//use to retrieve the ack packet, only two bytes long
private DatagramPacket ackDP = new DatagramPacket(new byte[2], 2);
private int TIME_OUT = 1000; //1 second
public void run(){
try{
sendfileSocket = new DatagramSocket(69);
System.out.println("TftpServer sending a file on port " + sendfileSocket.getLocalPort());
byte pType = TftpUtil.checkPacketType(req);
clientAddress = req.getSocketAddress();
//checking if the first packet from client is a RRQ packet
if(pType == TftpUtil.RRQ){
String filename = getFileName(req);
System.out.println("Requested file name:" + filename);
//if the file doesn't exist, send ERROR packet and close socket
if(!(new File(filename)).exists()) {
DatagramPacket errorDP = TftpUtil.packErrorPacket(filename);
errorDP.setSocketAddress(clientAddress);
sendfileSocket.send(errorDP);
}
else{
//the file does exist, send file
sendfile(filename);
}
}// end if
}catch(Exception e){
e.printStackTrace();
}
sendfileSocket.close();
return;
}
private void sendfile(String filename) throws Exception{
FileInputStream fileInput = new FileInputStream(filename);
while(true){
int rec = fileInput.read(dataBuffer);
//the file size is a multiple of 512, send empty packet
if(rec == -1){
sendDataPacket(new byte[0],0);
System.out.println("The last packet [0 byte in size]:#"+currentBlockSeq);
break;
}
//send a file data packet
boolean successed = sendDataPacket(dataBuffer,rec);
//tried five times
if (!successed) {
System.out.println("Tried five times, give up");
System.exit(0);
}
// the last packet (the file size if not a multiple of 512)
if (rec < 512 && rec > 0 ) {
System.out.println("The last packet ["+rec+" bytes in size]:#"+currentBlockSeq);
break;
}
currentBlockSeq++;
}//while
fileInput.close();
}
//
private boolean sendDataPacket(byte[] databuffer,int length) throws Exception{
int resendCount = 0;
DatagramPacket dataPacket = packFileDataPacket(databuffer,length);
//try five times
while(resendCount < TftpUtil.MAX_RESEND){
try{
sendfileSocket.send(dataPacket);
sendfileSocket.setSoTimeout(TIME_OUT);
System.out.println("sent data block #"+currentBlockSeq+", waiting for ack #" + currentBlockSeq);
//ack arrives
sendfileSocket.receive(ackDP);
byte ackedBlockseq = TftpUtil.extractACKNumber(ackDP);
System.out.println("received ack #" + ackedBlockseq);
if(ackedBlockseq != currentBlockSeq) {
//the acked block seq is not the seq of block sent
//ignore this ack and resend
resendCount++;
continue;
}
//this data packet has been acked, return
return true;
}//end of try
catch(SocketTimeoutException ste){
resendCount++;
System.out.println("timeout #" + resendCount );
}
}//end of while
return false;
}
private DatagramPacket packFileDataPacket(byte[] dataBuffer, int length){
int packetLength = 2 + length;//type (1) + block seq (1) + data length
ByteBuffer byteBuffer = ByteBuffer.allocate(packetLength);
byteBuffer.put(TftpUtil.DATA);//type
byteBuffer.put(currentBlockSeq);//block seq
byteBuffer.put(dataBuffer,0,length);//data
DatagramPacket dataPacket = new DatagramPacket(byteBuffer.array(), packetLength);
dataPacket.setSocketAddress(clientAddress);
return dataPacket;
}
private String getFileName(DatagramPacket dataDP){
byte[] data = dataDP.getData();
int dataLength = dataDP.getLength();
ByteBuffer byteBuffer = ByteBuffer.allocate(dataLength-1);
//remove the packet type (RRQ)
byteBuffer.put(data,1,dataLength-1);
return new String(byteBuffer.array());
}
public server_v004ServerWorker(DatagramPacket req)
{
this.req = req;
}
}
and full TftpUtil code:
import java.net.DatagramPacket;
import java.nio.ByteBuffer;
public class TftpUtil {
//read request packet
public static final byte RRQ = 1;
//data packet
public static final byte DATA = 2;
//ack packet
public static final byte ACK = 3;
//error packet
public static final byte ERROR = 4;
//the maximum number of resent
public static final int MAX_RESEND = 5;
//data buffer size: 512
public static int DATA_BUFFER_SIZE = 512;
//packet buffer size: 2 bytes header + 512 bytes file data;
public static int PACKET_BUFFER_SIZE = DATA_BUFFER_SIZE + 2;
//return the type (RRQ, DATA, ACK or ERROR) of a packet
public static byte checkPacketType(DatagramPacket dataDP){
byte[] payload = dataDP.getData();
return payload[0];
}
//return a RRQ packet
public static DatagramPacket packRRQDatagramPacket(byte[] filename) throws Exception{
return packDatagramPacket(RRQ, filename);
}
//return a "file not found" error packet
public static DatagramPacket packErrorPacket(String filename) throws Exception{
String errorMessage = filename + " not found";
return packDatagramPacket(ERROR, errorMessage.getBytes());
}
/*
* utility method that wrap a packet type, data into a DatagramPacket
*/
private static DatagramPacket packDatagramPacket(byte type, byte[] payload) throws Exception{
int dataLength = 1 + payload.length;
ByteBuffer byteBuffer = ByteBuffer.allocate(dataLength);
byteBuffer.put(type);
byteBuffer.put(payload);
return new DatagramPacket(byteBuffer.array(), dataLength);
}
//return the ack number of a ACK packet
public static byte extractACKNumber(DatagramPacket ackDP){
byte[] payload = ackDP.getData();
return payload[1];
}
//print the string content of a ERROR packet
public static void printErrorString(DatagramPacket p){
byte[] data = p.getData();
int dataLength = p.getLength();
ByteBuffer byteBuffer = ByteBuffer.allocate(dataLength-1);
//ignore the packet type
byteBuffer.put(data,1, dataLength-1);
System.out.print(new String(byteBuffer.array()));
}
//return the block sequence of a data packet
public static byte extractBlockSeq(DatagramPacket dataDP){
byte[] payload = dataDP.getData();
if(payload.length <=1) return -1; //-1: no block sequence in data
int type = payload[0];
if(type == DATA){
return payload[1];
}
return -1; //-1: not a data packet
}
}
I am working on a device which would work to measure some readings through sensors. Device is operated by an Android app. I have to take readings from TCP layer. This is the code to send data on TCP
TcpClient.java
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
/**
* Created by shahbaz on 25/4/17.
*/
public class TcpClient {
public static final String SERVER_IP = "192.168.1.76"; //server IP address
public static final int SERVER_PORT = 1800;
// message to send to the server
private String mServerMessage;
// sends message received notifications
private OnMessageReceived mMessageListener = null;
// while this is true, the server will continue running
private boolean mRun = false;
// used to send messages
private PrintWriter mBufferOut;
// used to read messages from the server
private BufferedReader mBufferIn;
/**
* Constructor of the class. OnMessagedReceived listens for the messages received from server
*/
public TcpClient(OnMessageReceived listener) {
mMessageListener = listener;
}
/**
* Sends the message entered by client to the server
*
* #param message text entered by client
*/
public void sendMessage(String message) {
if (mBufferOut != null && !mBufferOut.checkError()) {
mBufferOut.println(message);
mBufferOut.flush();
}
}
/**
* Close the connection and release the members
*/
public void stopClient() {
mRun = false;
if (mBufferOut != null) {
mBufferOut.flush();
mBufferOut.close();
}
mMessageListener = null;
mBufferIn = null;
mBufferOut = null;
mServerMessage = null;
}
public void run() {
mRun = true;
try {
//here you must put your computer's IP address.
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.e("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
Socket socket = new Socket(serverAddr, SERVER_PORT);
try {
//sends the message to the server
mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//receives the message which the server sends back
mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in this while the client listens for the messages sent by the server
while (mRun) {
mServerMessage = mBufferIn.readLine();
if (mServerMessage != null && mMessageListener != null) {
//call the method messageReceived from MyActivity class
mMessageListener.messageReceived(mServerMessage);
}
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
//the socket must be closed. It is not possible to reconnect to this socket
// after it is closed, which means a new socket instance has to be created.
socket.close();
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
//Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
//class at on asynckTask doInBackground
public interface OnMessageReceived {
public void messageReceived(String message);
}
}
Packet Structure
Packet format contains,
While communicating with the device on TCP, boundaries between packets are not identified, in this case if the packets are out of sequence or if any of the packets is missed one can identify a new packet using ‘header start’.
So, first 2 bytes in the packet represent the start of the packet.
Header start: Two-byte field that indicates the start of every packet. 0x55AA is a 2 bytes number used as header start.
Protocol version: One-byte field to specify the version of the protocol in use. Version specified in the payload will decide the payload structure. At any given moment a device will support single protocol version. Present protocol version is ‘1’.
DSN: Sequence number is 1-byte field which will identify the packet uniquely. Requester of the packet will have to fill this field in request payload; responder has to fill the same unique identifier in the response payload.
Request Id: One-byte field specifies the command id. The parsing of the payload will be done on the basis of the command id. In case of request payload this field will be non zero and in case of response it will be zero.
Payload length: Two-byte field specifies the length of the payload in bytes. It specifies the number of bytes followed payload length field. In the payload length, header length and CRC is not included. Currently, Max payload length supported by gateway device is 512 (bytes).
CRC: 1 byte field which will be calculated by XORing all the bytes and add the XOR count of 0.
And it is working. But according to docs I have to send packet using binary communication protocol. Including header start, payload data, etc. How can I send these params in packet structure? How can I create packet?
Any help is appreciated.
The main mistake was that I was not thinking much about size of primitive data types.
byte = 1 byte
short = 2 bytes
int = 4 bytes
long = 8 bytes
float = 4 bytes
double = 8 bytes
char = 2 byte
After referencing the size of primitive datatypes I realised we should track the size and index of packet because we are dealing with byte array.
TcpPacket.java
public class TcpPacket {
private static int header_start = 0x55AA;
private static int protocol_version = 1;
private PacketUtils packetUtils = new PacketUtils();
public byte[] getHandshakePacket()
{
int request_id = 1;
byte[] header_data = packetUtils.ItoBA2(header_start);
byte[] payload_data = packetUtils.ItoBA4(packetUtils.getDateTime());
byte[] payload_length = packetUtils.ItoBA2(4);
byte[] a_data = new byte[]{header_data[0], header_data[1], (byte) protocol_version, packetUtils.getDSN(), (byte) request_id, payload_length[0], payload_length[1],
payload_data[0], payload_data[1], payload_data[2], payload_data[3]};
byte[] b_data = new byte[]{ packetUtils.getCRC(a_data)};
byte[] packet_data = packetUtils.concatBytes(a_data,b_data);
return packet_data;
}
}
PacketUtils.java
public class PacketUtils {
public byte[] ItoBA4(int value) { // integer to bytes function (return byte array of 4 bytes)
return new byte[] {
(byte)(value >>> 24),
(byte)(value >>> 16),
(byte)(value >>> 8),
(byte)value};
}
public byte[] ItoBA2(int value) { // integer to bytes function (return byte array of 2 bytes)
return new byte[] {
(byte)(value >>> 8),
(byte)value};
}
public byte getDSN() // return one byte random number
{
char[] chars = "1234567890".toCharArray();
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < 1; i++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
byte output = Byte.valueOf(sb.toString());
return output;
}
public byte getCRC(byte[] packet) // required CRC function (return byte)
{
try
{
if (packet == null)
{
//Logger.Error("empty packet received");
return (byte)0;
}
byte XORCheckSum = 0;
byte zeroCount = 0;
byte FFCount = 0;
for (int i = 0; i < packet.length; i++)
{
XORCheckSum ^= packet[i];
if (packet[i] == (byte) 0)
{
zeroCount++;
continue;
}
if (packet[i] == (byte)255)
{
FFCount++;
continue;
}
}
XORCheckSum ^= zeroCount;
XORCheckSum ^= FFCount;
return XORCheckSum;
}
catch (Exception ex)
{
//Logger.Error(ex);
return (byte)0;
}
}
byte[] concatBytes(byte[]...arrays) // concatenate byte arrays
{
// Determine the length of the result array
int totalLength = 0;
for (int i = 0; i < arrays.length; i++)
{
totalLength += arrays[i].length;
}
// create the result array
byte[] result = new byte[totalLength];
// copy the source arrays into the result array
int currentIndex = 0;
for (int i = 0; i < arrays.length; i++)
{
System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length);
currentIndex += arrays[i].length;
}
return result;
}
public int getDateTime()
{
int dateInSec = (int) (System.currentTimeMillis() / 1000);
return dateInSec;
}
}
I have a multi-threaded scenario in which a Sender class which uses a ConcurrentLinkedQueue of type Packet is used. Packet is a POJO defined as:
class Packet {
int seq;
byte[] data;
}
Sender class is defined as:
class Sender implements Runnable {
private static ConcurrentLinkedQueue<Packet> queue;
public Sender() {
if (ccl == null)
ccl = new ConcurrentLinkedQueue<Packet>();
}
public static boolean enqueue(Packet p) {
if (queue == null) {
queue = new ConcurrentLinkedQueue<Packet>();
}
//System.out.println(p.toString());
return queue.add(p);
}
#Override
public void run() {
TcpSend tcp = new TcpSend();
while (true) {
Packet p = queue.remove();
// some code here
//System.out.println(p.toString());
tcp.send(p);
}
}
}
From another java class I am reading a file into byte array and adding it to ConcurrentLinkedQueue. When I print the details of packet in enqueue(), I get the correct details. But when I print the details in run() i.e. after removing the packet from queue, I get the correct seq but I get the data of the last packed that was added to the queue. This happens for all the packets which are removed from the queue.
The data is added by the following method
public void addPacket() {
int bytesRead = 0;
int seq = 1;
byte[] fileInBytes = new byte[1500];
BufferedInputStream in = new BufferedInputStream(new
FileInputStream(fileName));
while((bytesRead = in.read(fileInBytes)) != -1) {
Sender.enqueue(new Packet(seq, fileInBytes);
seq++;
}
}
Please suggest. TIA
You are using the same byte array (fileInBytes) to read from the stream:
byte[] fileInBytes = new byte[1500];
BufferedInputStream in = new BufferedInputStream(new
FileInputStream(fileName));
while((bytesRead = in.read(fileInBytes)) != -1) {
Sender.enqueue(new Packet(seq, fileInBytes);
seq++;
}
I guess that the constructor of Packet does not copy the byte array:
class Packet {
int seq;
byte[] data;
public Packet(int seq, byte[] data) {
this.seq = seq;
this.data = data;
}
}
That means that all of your Packet.data fields point to the same byte array which is overwritten each time your read from the stream.
You need to use a copy:
byte[] fileInBytes = new byte[1500];
BufferedInputStream in = new BufferedInputStream(new
FileInputStream(fileName));
while((bytesRead = in.read(fileInBytes)) != -1) {
byte[] packetBytes = Arrays.copyOf(fileInBytes, bytesRead);
Sender.enqueue(new Packet(seq, packetBytes );
seq++;
}
I have a task to do this.
Create a client and server socket interaction which accepts byte data and converts the byte data data received at server in the String and send back the response with the confirmation of the data conversation with success/unsuccess as the data passed will be with fix data length format so the validation should be done at server end.
As for e.g.
there are fields which ur sending to server like,
field 1 - number
field 2 - String
field 3 as Floating number i.e. 108.50
After conversion from byte to String :
152|any msg|108.50
In Byte it will be something like this,
10101|1001010010000000011000000000|1110111011
I have tried the following programs to do this
Server.java
public class Server extends Thread
{
private ServerSocket serverSocket;
public Server(int port) throws IOException
{
serverSocket = new ServerSocket(port);
//serverSocket.setSoTimeout(100000);
}
public void run()
{
while(true)
{
try
{
Socket server = serverSocket.accept();
byte Message[]=null;
DataInputStream in =
new DataInputStream(server.getInputStream());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = in.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
System.out.println("On this line"); //This doesnt get printed
buffer.flush();
data= buffer.toByteArray();
System.out.println(data);
String convertmsg = new String(data);
System.out.println("Msg converted "+convertmsg);
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
System.out.println("below dataoutputstream");
out.write("Success".getBytes());
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = 4003;
try
{
Thread t = new Server(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
client
public class Client {
public static void main(String args[]) throws IOException
{
int userinput =1;
while(userinput==1)
{
String serverName = "192.168.0.8";
int port = 4003;
try
{
System.out.println("Connecting to " + serverName
+ " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to "
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out =
new DataOutputStream(outToServer);
System.out.println("above out.wirte()");
out.write("any msg".getBytes());
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
System.out.println("converting array "+in);
byte[] data = IOUtils.toByteArray(in);
System.out.println(data);//This line doesnt get printed
//System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
System.out.println("Enter userinput ");
DataInputStream dis = new DataInputStream(System.in);
String s = dis.readLine();
userinput = Integer.parseInt(s);
}
}
}
If i send data from client to server in bytes,it reads it and prints it.Also then the line "Enter userinput " gets printed and if the user enters '1' the program continues.
But the problem is this program given above. If i try to send data from server stating "success"(meaning the data has been converted from bytes to String successfully) then the program stucks and the cursor doesnt go below the line which are in comments "This line doesnt get printed".There is no error printed and none of the program terminates.I am new to socket programming and dont understand much about networking.
Any help will be truly appreciated.
You're reading the input until end of stream, but the peer isn't closing the connection, so end of stream never arrives.
I suggest you read and write lines, or use writeUTF() and readUTF().
I am trying to set up a program that looks into UDP performance of packets and response times on my network. I have a client and server side class, for which I am specifying the packet size which to send pieces of text. For example, if I want to send a word of "Tester" in a 4 byte packet, it will send the "TEST" part but not reiterate through the rest of the word. I have tried to add in a while loop, but i don't think what I have is correct as it continuously sends the first 4 bytes. Does anyone know what sort of loop I need and where abouts it should be placed to get the outcome I am after? Code for the client is below. Many thanks in advance for any guidance.
//UDP Client
//Usage: java UDPClient [server addr] [server port]
import java.io.*;
import java.net.*;
public class UDPClient extends variable {
// static Integer portNo = 4444;
static Integer byteSize = 4;
public static void main(String[] args) throws Exception {
SocketForm form = new SocketForm();
long startTime; // Starting time of program, in milliseconds.
long endTime; // Time when computations are done, in milliseconds.
double time;
//get server address
String serverName = "localhost";
if (args.length >= 1)
serverName = args[0];
InetAddress serverIPAddress = InetAddress.getByName(serverName);
//get server port;
int serverPort = form.cliportNo;
if (args.length >= 2)
serverPort = Integer.parseInt(args[1]);
//create socket
DatagramSocket clientSocket = new DatagramSocket();
//get input from keybaord
byte[] sendData = new byte[byteSize];
BufferedReader inFromUser = new BufferedReader(new InputStreamReader (System.in));
while (true){ //incorrect as it is only repeating the first four bytes of the word typed in the console
String sentence = inFromUser.readLine();
startTime = System.currentTimeMillis();
sendData = sentence.getBytes();
//construct and send datagram;
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverIPAddress, serverPort);
clientSocket.send(sendPacket);
//receive datagram
byte[] receiveData = new byte [byteSize];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
//print output
String sentenceFromServer = new String(receivePacket.getData());
System.out.println("From Server:" + sentenceFromServer);
//close client socket
//clientSocket.close();
endTime = System.currentTimeMillis();
time = endTime - startTime;
//System.out.println("Time :" + time);
}
} //end of main
} //end of UDPClient
Do you mean like this?
private void sendChunked( String msg, int chunkSizeInBytes ) {
byte[] msgBytes = msg.getBytes();
for( int index = 0; index < msgBytes.length ; index += chunkSizeInBytes ) {
DatagramPacket packet = new DatagramPacket( msgBytes, index, Math.min( chunkSizeInBytes, msgBytes.length-index ));
send( packet ); // You know how that works ...
}
}