在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
我现在想在Java
中做同样的事情。例如,我想读取长度为0x10000003
的地址0x1
的内存,例如1个字节。
到目前为止,我编写了以下代码:
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);
}
}
建立连接有效,但在发送数据后,没有响应。服务器不会发回任何内容,我的Java程序卡在readLine()
上。输出如下:
Connected
Receiving
用readLine()
替换read()
无济于事。使用DataOutputStream
write
和writeInt
来电也无效。
我在这里遇到的困难似乎是准备和正确发送请求数据。为了您的信息,Python函数struct.pack
在interactive Python session
中生成以下结果:
>>> import struct
>>> struct.pack(">II", 10000003, 10000004)
b'\x00\x98\x96\x83\x00\x98\x96\x84'
>>>
两个整数都转换为十六进制和#34;打包"到一个字节数组。
readmem
命令字符串转换为ASCII字节数组我相信:
>>> print("\x04")
*Box with questionmark in it*
>>> s = "04"
>>> ":".join("{:02x}".format(ord(c)) for c in s)
'30:34'
>>>
后一个打印字节的代码取自here。
那么Java代码有什么问题?
答案 0 :(得分:1)
您应该使用DataOutputStream而不是PrintWriter。密切关注文档 - write
和writeByte
方法发送一个字节,而writeInt
发送四个字节。同样,阅读应使用DataInputStream,特别是readByte
和readFully
方法,而不是BufferedReader。
作家和读者处理文本,而不是字节。 PrintWriter.print发送一个数字的ASCII表示,而不是字节本身。 BufferedReader(和大多数读者)将尝试将传入的字节解码为文本,而不是直接读取字节。