【发布时间】:2015-12-12 00:13:32
【问题描述】:
给定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
用read() 替换readLine() 没有帮助。将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'
>>>
两个整数都转换为十六进制并“打包”到一个字节数组中。
readmem 命令字符串被转换为我相信的 ASCII 字节数组:
>>> print("\x04")
*Box with questionmark in it*
>>> s = "04"
>>> ":".join("{:02x}".format(ord(c)) for c in s)
'30:34'
>>>
后一个用于打印字节的代码取自here。
那么 Java 代码有什么问题呢?
【问题讨论】:
-
其实python的
"\x04"只是一个值为4的单字节。所以发送一个Java的"04"是很不一样的。 -
@RealSkeptic 所以我宁愿将整数 4 转换为一个字节并发送它?在 Java 中我正在这样做:
outputWriter.print((byte) 4);但是,这仍然没有解决问题 -
不,要在 Java 中发送字节,不要使用
Writer,也不要使用print。您使用基于字节的OutputStream并使用write。更好的是,使用频道而不是流并使用ByteBuffer。但是您必须阅读 Java 文档。 -
@RealSkeptic 我尝试了
OutputStream outputStream = clientSocket.getOutputStream();和write()调用 3 个参数,最后调用了flush(),但它也没有工作 -
您应该使用 DataOutputStream 而不是 PrintWriter。请密切注意文档——
write和writeByte方法发送 一个字节, 而writeInt发送四个字节。同样,应该使用DataInputStream 进行读取,特别是readByte和readFully方法,而不是BufferedReader。
标签: java python sockets networking