【问题标题】:Converting Python Networking Code To Java将 Python 网络代码转换为 Java
【发布时间】: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() 没有帮助。将DataOutputStreamwritewriteInt 调用一起使用也不起作用。

我在这里遇到的困难似乎是正确准备和发送请求数据。供您参考,Python 函数 struct.packinteractive 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。请密切注意文档——writewriteByte 方法发送 一个字节,writeInt 发送四个字节。同样,应该使用DataInputStream 进行读取,特别是readBytereadFully 方法,而不是BufferedReader。

标签: java python sockets networking


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    相关资源
    最近更新 更多