Reputation: 19195
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?
Upvotes: 0
Views: 195
Reputation: 44338
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.
Upvotes: 1