I'm trying to write simple code for server/client.
The server (in java) wait for string from client:
ServerSocket ss = new ServerSocket(4001);
Socket s = ss.accept() ;
DataInputStream dataStreamIn = new DataInputStream(s.getInputStream()) ;
byte buffer[] = new byte[100];
dataStreamIn.read(buffer);
if((new String(buffer)).equals("1"))
System.out.print("yes");//never printed
the client (objective-c) send string to server:
uint8_t buffer[1000] ={0};
sprintf((char*)buffer,"%s", "1");
NSInteger wrote = [self.networkStreamOut
write:buffer
maxLength:(uint8_t)strlen((char *)buffer)];
The problem is the buffer on server is indeed "1" BUT when I'm trying to compare with .equals() it return false!
EDIT:
When I'm tring to add to server this line:
System.out.println(Integer.valueOf(new String(buffer))) ;
I'm getting this error:
Exception in thread "main" java.lang.NumberFormatException: For input string: "1
You should explicitly state what encoding you expect your incoming data to be in, on both the client and server side. This is especially important to do when communicating between different platforms/languages.
But, of course, that's not what your problem is - your string is getting created with a bunch of non-printing characters because you allocated it with the entire byte array:
byte[] buffer = new byte[100];
new String(buffer);
Presumably the buffer is not completely filled after you read data into it, and the defaulted zero values in it are getting converted in your string into non-printing characters. You can validate this by printing the length of the string you created, you will find it to be greater than 1.
You have two remedies - either trim() the String before comparing its value, or keep track of the number of actual bytes read and create a new byte array of the correct length (before creating your String).
Related
A piece of Java code is residing on a server expecting about 64 bytes of information from a piece of hardware, sent via TCP. The packet has a 10 byte header. The first byte is a protocol identifier, the second two bytes gives the total number of bytes in the packet, including all the header bytes and checksum. The last 7 bytes are a UID.
Server Code:
public void run () throws Exception
{
//Open a socket on localhost at port 11111
ServerSocket welcomeSocket = new ServerSocket(11111);
while(true) {
//Open and Accept on Socket
Socket connectionSocket = welcomeSocket.accept();
//Alt Method
DataInputStream dis = new DataInputStream(connectionSocket.getInputStream());
int len = dis.readInt();
byte[] data = new byte[len];
if (len > 0) {
dis.readFully(data);
}
System.out.println("Recv[HEX]: " + StringTools.toHexString(data));
}
}
The issue is my readInt() line, that takes the first four bytes, however I need to determine the length based on the second two bytes. How can this be achieved?
And secondly, is my stringTools.toHexString(data) correct to dump the received buffer which I know should be readable as a HEX string?
Note: This question has its root here: Java TCP Socket Byte Heap Memory Issue
Only use DataInputStream if the other side is using DataOutputStream or it's exact format. The integers, for example, may be encoded big-endian or little-endian - DataOutputStream uses big-endian notation, if the other side uses different encoding, you cannot use DataInputStream. Using InputStream.read() gives you more control if you need it.
Now, since the format of message as you stated starts with one byte for protocol identifier, you first need to read that as a byte (dis.readByte() or InputStream.read()) and either check that the protocol is what you expect or handle different protocols. Then you read the message length, etc.
You can use ByteBuffer to read the int in the last two bytes
import static java.lang.System.out;
import java.nio.ByteBuffer;
class B {
public static void main( String ... args ) {
// test value
int a = 1238098;
// convert it into an arrays of bytes
ByteBuffer b = ByteBuffer.allocate(4);
b.putInt(a);
byte [] r = b.array();
// read last two
int size = ByteBuffer.wrap(new byte[]{0x0,0x0, r[2], r[3]}).getInt();
// print it
out.println("Original: " + String.format("%32s%n" , Integer.toString(a,2)).replace(' ', '0'));
out.printf("Last two: %32s%n" , Integer.toString(size,2));
out.printf("Decimal : %d%n" , size );
}
}
Output:
Original: 00000000000100101110010001010010
Last two: 1110010001010010
Decimal : 58450
However I would recommend to follow #Jiri answer about read using InputStream.read() instead of DateInputStream
I am creating a chat application in Java. User can send multiple new lines in a single message. Previously, I was not allowing the user to send new lines. So it was easy to use new line character as End OF Message. But now I am allowing the user to send new lines in a message. What character/string should I use to mark the end of the message.
You can easily avoid end of message by adding extra 4 byte. First 4 byte represent length of your message. Then add full message.
Sample sender code:
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
String msg = "its a test message";
byte[] byteMsg = msg.getBytes();
int length = byteMsg.length;
byte[] lengthByte = ByteBuffer.allocate(4).putInt(length).array();
byte[] finalMsg = new byte[length+4];
System.arraycopy(lengthByte, 0, finalMsg, 0, 4);
System.arraycopy(byteMsg, 0, finalMsg, 4, length);
bufferedOutputStream.write(finalMsg);
When you read your message then read first 4 byte. Convert this 4 byte to integer. This is your incoming message length. Then parse those byte.
It's your application so you're free to use whatever you like, including EOF and NUL characters suggested by Marko and KDM.
Just make sure it's a character your users won't be using in their messages.
I'm trying to get a very simple Client-Server system to work, where the Client will send a String over to the Server, and the server will then store that String into a file.
The client sends the string through:
//Other Code
sockStrm = new DataOutputStream (clientSocket.getOutputStream ());
//Other code
sockStrm.writeChars (line);
//Other code
And the Server receives the String with:
//Other code
strm = new BufferedReader (new InputStreamReader (clientSocket.getInputStream ()));
//Other code
stringLine = strm.readLine ();
//Other code
When I send the string STOP, the length of the String is 4 on the client side, and on the server side the length of the String is 9 and displays as STOP
I've tried to substring the received String on the Server side, without luck.
Any pointers on how to deal with this?
Use symmetric methods:
DataOutputStream sockStrm =...
sockStrm.writeUTF(str);
and
DataInputStream sockStrm = ...
String str = sockStrm.readUTF();
writeChars writes individual characters as two byte values. Readers follow the encoding to reconstruct the string from a sequence of bytes, which will definitely not be according to high-byte-low-byte for each character code. Hence you get some mish-mash of zero bytes with the original low-byte values so you still have a glimpse of the original string value.
Using \x00 to denote a NULL byte:
S-T-O-P => on the line: \x00-S-\x00-T-\x00-O-\x00-P => prints as STOP
Use a loop over the characters of the incoming string and display their integer values (str.charAt(i)) to see the above for yourself.
So I am creating an application using sockets. And I have the client who sends a message and it passes to the server using writeObject(new String("Name|Message"));.
And I read the message in the server using readObject();
I am trying to pass this string object to an array. But I get [Ljava.lang.String;#6bb9ae1a.
Here is what I am trying:
ObjectInputStream saida = new ObjectInputStream(client.getInputStream());
String[] read = saida.readObject().toString().split("|");
System.out.println(read);
I tried also to make variables for each split:
String readm = read[1];
String readn = read[0];
But it returns me "" as the name and "A" as the message (?)
Ow, and the socket is working, because if I do (String) saida.readObject(); it returns me the normal string.
use like that :
saida.readObject().toString().split("\\|");
and then
String readm = read[1];
String readn = read[0];
Because pipe symbol is the special character and splitting special chars is different. And you cannot use systemoutprintln to print the string array.
NOW here is the coding for j2me mobile for sending the string:
String s="hai";
try{
String url = "btspp://001F81000250:1;authenticate=false;encrypt=false;master=false";
StreamConnection stream = null;
InputStream in;
OutputStream out;
stream = (StreamConnection) Connector.open(url);
out=stream.openOutputStream();
String s=tf.getString();
byte size=(byte) s.length();
out.write(size);
out.write(s.getBytes());
out.flush();
out.close();
stream.close();
}
catch(Exception e){
}
NOW the coding for j2se for receiving the String :
StreamConnectionNotifier notifier=null;
try{
String url = "btspp://localhost:"+new UUID("1101", true).toString()+";name=PCServerCOMM;authenticate=false";
System.out.println(LocalDevice.getLocalDevice().getBluetoothAddress()+"\nCreate server by uri: " + url);
notifier= (StreamConnectionNotifier) Connector.open(url);
while(true){
System.out.println("waiting....");
StreamConnection con = notifier.acceptAndOpen();
System.out.println("Got connection..");
InputStream is=con.openInputStream();
//byte b[]=new byte[40];
/*
while(is.available()>0){
System.out.print((char)is.read());
}*/
//is.read(b, 0, 40);
int size=is.read();
byte b[]=new byte[size];
is.read(b, 0, size);
File f=new File("d://test.xml");
FileOutputStream fo=new FileOutputStream(f);
fo.write(b,0,b.length);
fo.close();
con.close();
System.out.println(new String (b));
}
//printing(f);
} catch(Exception e){
JOptionPane.showConfirmDialog(new JFrame(), e.getMessage());
}
I tried this coding for data transfer but it is not a successful one because when the string which we sent is too long then there is problem in receiving side. How can I solve this?
Is there any other way to transfer the data in rms to j2se, if so please help me.... please make your reply quick...
The way you are writing and reading here, only strings up to 255 characters in length, which additionally only take the same number of bytes in your default encoding, are written right.
On the writing side:
The statement byte size=(byte) s.length(); converts the length of the string in a byte, thus only takes the lower 8 bits of the length. So, only lengths up to 255 are written right.
Then you are converting the String to a byte array with s.getBytes() - this array could be longer (in bytes) than the original string in characters. This conversion uses the default encoding of your sending device.
On the reading side:
The statement int size=is.read(); reads the length written before, then you are creating a byte array.
is.read(b, 0, size); reads some bytes into this array - it does not necessarily fills the complete array.
Then you are converting your byte array (which may not even be filled completely) to a string, using the default encoding of the receiving device.
So, we have:
All strings longer than 255 characters are written wrongly.
If sending and receiving side are using different encodings, you may get a wrong output.
If the sending side uses an encoding like UTF-8 where some characters take more than one byte, the string is cut off at the end (if such characters occur).
How to solve this:
If you can use a DataInputStream and DataOutputStream on both sides (I don't know anything about J2ME), use them there, with their readUTF and writeUTF methods. They solve all your problems (if your strings take at most 65535 bytes in the modified UTF-8 encoding used here).
If not:
make a decision on how long the strings can be, and encode your length with the right number of bytes. 4 bytes are enough for every Java String.
measure the length after converting to a byte[], not before.
use a loop for reading into the array, to be sure to capture the whole string.
for the getBytes() and new String(...), use the variants which take an explicit encoding name and give them the same encoding (I recommend "UTF-8").