Java: DataOutputStream through socket is wrong on other side (which is Python) - java

I've got a Socket, s and an long, 1312992.
DataOutputStream out = new DataOutputStream(s.getOutputStream());
out.writeLong(hwnd);
out.flush();
Doing
self.hwnd, = struct.unpack('!Q', self.appletconn.recv(8))
print(self.hwnd)
on the (python) receiving side prints out 51. I presume something's wrong with my sending code.
Thanks.

Use a packet capture tool like tcpdump or wireshark and check what is going on the wire. I am guessing, you might be mixing text and binary on sending and/or receiving side.

Related

Java socket writeByte and newline

I got a question for something I can't seem to understand.
If I use the snippet:
DataOutputStream dataoutput = new DataOutputStream(Socket.getOutputStream());
dataoutput.writeBytes(diagnostics);
dataoutput.flush();
The output:diagnostics that is sent from server to client hangs, where even using .flush() will not help. Only closing the socket will release the data packet.
However, if I add a newline character:
dataoutput.writeBytes(diagnostics+"\n");
it works perfectly. And if you duplicate the code,
dataoutput.writeBytes(diagnostics);
dataoutput.writeBytes(diagnostics);
You get the same output as the one with the /newline without duplicate data. Why?
EDIT: Client-side.
incoming = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
response = incoming.readLine();
Like the good lads puts in the comment you should use a flush to force send the payload to destination of the stream. But if that isn't working i suggest to try the following :
DataOutputStream dataoutput = new DataOutputStream(System.out);
dataoutput.writeBytes(diagnostics);
dataoutput.flush();
So now the destination will be the "local" console. and no remote connection is between the source and the destination of the stream, perhaps you can try for yourself if anything is working properly "locally" (and focus in the DataOutputStream behaviour) and then start to tackle the remote streaming process.
Is it not to much, but hope it helps a little!
Greetings!!

How does Ruby's handling of socket output streams differ from Java's?

I have a Python server that listens for json requests. The "receiving" section of the code looks like this:
while True:
next_message = conn.recv(1024)
response = Foo.do_some_stuff(next_message)
conn.send(response)
I built a Sinatra application that uses the Python API.
client = TCPSocket.new("localhost", 5000)
client.puts("foobar")
response = client.gets
All of the above code functions perfectly. Now, I'm doing something similar with some Java code.
Socket client = new Socket("localhost", 5000);
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(new client.getOutputStream(), true);
out.println("foobar");
String response = in.readLine();
The problem is that this code works for the first request, but on subsequent requests the Python server hangs, still waiting for the message. My question is what is the Ruby implementation of output stream appending to the message to signal the message's end that the Java implementation isn't?
Relevant details:
I'm using the Google Gson package in the Java code to create Json objects that I send to the Python server.
I'm using auto-flush on the PrintWriter.
I read that perhaps subsequent requests alter the size of the data being sent to the Python server - because of the underlying TCP protocol, and that the Python socket will keep listening until the connection ends or it's read 1024 bytes. This would make sense, except that the Ruby implementation works perfectly.
I've been digging through Java, Python, and Ruby docs for the past two days trying to figure this out. Any help would be greatly appreciated.

How can a server know when the message it receives is actally over?

I'm trying to implement a server and it does something like this when it receives a message:
try{
ObjectInputStream is = new ObjectInputStream(clientSocket.getInputStream());
String message = (String)is.readObject();
ActivateCommand(message,clientSocket);
is.close();
}
and the ActivateCommand:
private void ActivateEwolfCommand(String msg, Socket clientSocket) throws IOException
{
ObjectOutputStream os = new ObjectOutputStream(clientSocket.getOutputStream());
Gson gsonObject = new Gson();
.
//code which makes a Json string
.
os.writeObject(json);
os.close();
}
now, when i tested it with sending a message to the local host with a junit test it worked. But when tried connecting to the server from a C# client, the client connected but the server throw an EOF exception when getting to the point of clientSocket.getInputStream().
I'm guessing it happens because the server did not know when the message is suppose to end but i don't know if thats really the case and if it is, then how can i fix it?
When there is no more data available on the InputStream to read() - that basically is what causes an EOF. How much data is available is determined by the client - the data that it writes to the Socket's OutputStream on its side appears as such on the InputStream of Socket of the server side. You can call InputStream.available() to get an estimate of number of bytes that can be still read().
However your code is trying to read an Object using an ObjectInputStream - this class has its own protocol to read a serialized byte stream and convert that to an object - if it does not find the bytes to complete the task this can throw the EOF exception. If your client is in C# - the format of bytes this writes for a serialized object will definitely not be the same as expected by the ObjectInputStream on the server side.
This is why it's a bad idea to create your own client-server protocol with a socket and object streams. Many people have spent many years bringing you, oh, well:
SOAP
REST
RMI
Hessian
CORBA
Thrift
and the multitude of other protocols out there. Surely one of them, if not 5 or 6, is good enough to solve your problem, including all issues of framing.
If you want to send strings over a socket, then an ObjectInputStream or ObjectOutputStream isn't the right stream implementation. These stream implementations use Java object serialization. Even if you serialize String instances, the resulting bytes are not the same as plain string to byte conversion with the appropriate character encoding.
And a C# application doesn't understand Java serialization at all.
Consider using a PrintWriter to write strings to your stream and a BufferedReader for reading.
PrintWriter writer = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"));
writer.println(...);
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"));
String line = reader.readLine();
Then you can read and write strings line by line.
This is only a starting point. If you want to implement your own protocol you have to pay attention to some more points. As an example you can read the specifications for some TCP protocols like POP3, FTP or HTTP 1.0.

Java server Socket, reading content from DataInputStream

So I have set up a basic client/server connection and I am trying to send a message to one another on connection, I got the client to receive the message from the server, but the server doesn't recieve the clients message. Here is my current code for reading the sent data from the client:
ServerThread.socket = new ServerSocket(5556);
Socket client = ServerThread.socket.accept();
DataInputStream in = new DataInputStream
(
new BufferedInputStream(client.getInputStream())
);
String s = in.readUTF();
System.out.println("Client: " + s);
Using that it doesn't print out anything, Not even just 'Client: '
Here is my code for my client connection, and sending the message. Note: I wrote this part in VB:
client = New TcpClient()
client.Connect("myiphere", 5556)
Dim stream As NetworkStream = client.GetStream()
Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes("Hello server")
stream.Write(sendBytes, 0, sendBytes.Length)
Is there any reason why the data isn't being recieved? Or why it is being delayed? I have tried surronding the Java portion of the code with a try catch block but no error is emitted.
Any help will be appreciated.
UTFs in a DataInputStream are prepended with 0 and the length.
I haven't done much with VB, so I don't know if there are other errors, but try:
stream.Write(0, sendBytes.Length, sendBytes)
I shouldn't suggest code in a language I don't know. If you want to read it with readUTF, you'll have to send a 0 byte and a byte equal to the length of the string before you send your text bytes.
Edit:
You really might not want to use DataInputStream at all, though. It's intended for storing binary streams. If you're receiving text, try this on the Java side:
BufferedReader in = new BufferedReader(
new InputStreamReader(
client.getInputStream()
)
);
String s = in.readLine();
If you're not sending text, just create a BufferedInputStream as you did and read the bytes off of it.
As maybeWeCouldStealAVan pointed out, readUTF expects two bytes indicating how many more bytes of content there are. See http://docs.oracle.com/javase/6/docs/api/java/io/DataInput.html#readUTF() for details.
However, his/her solution using InputStreamReader doesn't work because InputStreamReader is expecting UTF-16 input (two bytes per character), but your VB client is sending ascii. I would suggest making your VB client send UTF-16 if you can (then using maybeWeCouldStealAVan's java code). If you can't do that (sorry, I don't know what encodings VB allows), then just write the extra two bytes needed to make readUTF work.

How do I send telnet option codes?

I've written a socket listener in Java that just sends some data to the client.
If I connect to the server using telnet, I want the server to send some telnet option codes. Do I just send these like normal messages?
Like, if I wanted the client to print "hello", I would do this:
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.print("hello");
out.flush();
But when I try to send option codes, the client just prints them. Eg, the IAC char (0xff) just gets printed as a strange y character when I do this:
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.print((char)0xff);
out.flush();
If you use the default character encoding I would expect 0xff to be turned into two characters.
I suggest you use the plain OutputStream without a PrintWriter. That way the bytes will be sent without translation.
I just answered that here

Categories

Resources