将Python网络代码转换为Java

时间:2015-09-15 16:28:09

标签: java python sockets networking

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 writewriteInt来电也无效。

我在这里遇到的困难似乎是准备和正确发送请求数据。为了您的信息,Python函数struct.packinteractive 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代码有什么问题?

1 个答案:

答案 0 :(得分:1)

您应该使用DataOutputStream而不是PrintWriter。密切关注文档 - writewriteByte方法发送一个字节,而writeInt发送四个字节。同样,阅读应使用DataInputStream,特别是readBytereadFully方法,而不是BufferedReader。

作家和读者处理文本,而不是字节。 PrintWriter.print发送一个数字的ASCII表示,而不是字节本身。 BufferedReader(和大多数读者)将尝试将传入的字节解码为文本,而不是直接读取字节。