0

Given the following function definitions in Python:

class NetworkClient:
 def __init__(self, ip):
 self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
 self.s.connect((str(ip), 7331))
 def readmem(self, address, length):
 if length == 0: raise BaseException, "Why are you giving me no length" #Please don't do this to me
 if not self.ValidMemory().validrange(address, length): return
 if not self.ValidMemory().validaccess(address, length, "read"): return
 self.s.send("\x04") #cmd_readmem
 request = struct.pack(">II", address, address + length)
 self.s.send(request)
 status = self.s.recv(1)
 if status == "\xbd": #Non-zero memory was found
 response = self.s.recv(length)
 elif status == "\xb0": #All zeroes
 response = "\x00" * length
 else: return #Something went terribly wrong
 return response

I now want to do the same in Java. As example I want to read the memory at address 0x10000003 with length 0x1 e.g. 1 byte.

So far I wrote the following code:

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class NetworkClient
{
 public static void main(String[] arguments) throws IOException, InterruptedException
 {
 try (Socket clientSocket = new Socket("192.168.178.35", 7331);
 PrintWriter outputWriter =
 new PrintWriter(clientSocket.getOutputStream(), true);
 BufferedReader inputReader =
 new BufferedReader(
 new InputStreamReader(clientSocket.getInputStream())))
 {
 System.out.println("Connected");
 byte readMemoryCommand = (byte) 4;
 int memoryAddress = 0x10000003;
 int length = 0x1;
 outputWriter.print(readMemoryCommand);
 outputWriter.print(memoryAddress);
 outputWriter.println(memoryAddress + length);
 System.out.println("Receiving");
 System.out.println(inputReader.read());
 System.out.println("Received");
 }
 }
 public static byte[] toByteArray(String letters)
 {
 return letters.getBytes(StandardCharsets.US_ASCII);
 }
}

Establishing the connection works but then after sending the data, there is no response. The server does not send anything back and my Java program is stuck on readLine(). The output is as follows:

Connected
Receiving

Replacing readLine() with read() does not help. Using a DataOutputStream with write and writeInt calls does not work either.

The difficulty I'm having here seems to be to prepare and send the request data correctly. For your information, the Python function struct.pack produces the following result in an interactive Python session:

>>> import struct
>>> struct.pack(">II", 10000003, 10000004)
b'\x00\x98\x96\x83\x00\x98\x96\x84'
>>>

Both integers are converted to hexadecimal and "packed" into a byte array.

The readmem command String is converted to an ASCII byte array I believe:

>>> print("\x04")
*Box with questionmark in it*
>>> s = "04"
>>> ":".join("{:02x}".format(ord(c)) for c in s)
'30:34'
>>>

The latter code for printing the bytes is taken from here.

So what is wrong with the Java code?

asked Sep 15, 2015 at 16:28
6
  • Actually, python's "\x04" is simply a single byte with the value 4. So sending a Java "04" is very different. Commented Sep 15, 2015 at 16:44
  • @RealSkeptic So I would rather convert the integer 4 to a byte and send that? In Java I'm doing this: outputWriter.print((byte) 4); However, this still didn't solve the problem Commented Sep 15, 2015 at 16:47
  • 1
    No, to send bytes in Java, you do not use a Writer and you do not use print. You use a byte-based OutputStream and use write. Better yet, use a channel rather than a stream and use a ByteBuffer. But you'll have to do some reading of the Java documentation. Commented Sep 15, 2015 at 16:52
  • @RealSkeptic I tried OutputStream outputStream = clientSocket.getOutputStream(); and write() calls for the 3 arguments and finally a flush() but it also didn't work Commented Sep 15, 2015 at 16:57
  • You should be using DataOutputStream instead of PrintWriter. Pay close attention to the documentation—the write and writeByte methods send one byte, while writeInt sends four bytes. Similarly, reading should be done with a DataInputStream, specifically the readByte and readFully methods, rather than BufferedReader. Commented Sep 15, 2015 at 18:15

1 Answer 1

1

You should be using DataOutputStream instead of PrintWriter. Pay close attention to the documentation—the write and writeByte methods send one byte, while writeInt sends four bytes. Similarly, reading should be done with a DataInputStream, specifically the readByte and readFully methods, rather than BufferedReader.

Writers and Readers deal with text, not bytes. PrintWriter.print sends an ASCII representation of a number, rather than the byte itself. BufferedReader (and most Readers) will try to decode the incoming bytes into text, instead of reading the bytes directly.

answered Sep 16, 2015 at 16:42
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.