【问题标题】:Python socket receives incomplete message from Java PrintWriter socketPython 套接字从 Java PrintWriter 套接字接收到不完整的消息
【发布时间】:2014-11-28 04:07:13
【问题描述】:

我创建了一个 python“队列”(类似于 JMS 协议),它将接收来自两个 Java 客户端的问题。 python-server 将接收来自其中一个 Java 客户端的消息,第二个将读取问题并发布答案。连接和消息传递有效,当 Java 客户端回答一个很长的字符串时,问题就来了。

python收到的响应不完整!更糟糕的是,消息被切割成一定数量的字符,并且始终保持相同的长度,但是,如果其他人托管服务器,则该数字会有所不同。 (即:friend1 托管服务器,friend2 发送响应,收到的长度:1380chars。Friend2 托管服务器,friend1 发布答案,收到的长度:1431chars)这是服务器端 python 代码:

s = socket.socket()         
host = socket.gethostname() 
# host = "192.168.0.20"
port = 12345  
s.bind((host, port))

s.listen(5)                 
while True:
    c, addr = s.accept()     
    # print 'Got connection from', addr
    message = c.recv(8192) #Is this length a problem?

    # print message
    message = message.strip()
    ipAddress = addr[0]

我在 StackOverflow 上阅读了这里的问题,c.recv() 对大量字节应该没有问题,我们的响应接近 1500 个字符。这是java客户端:

private void openConnection(){
        try {

            socket = new Socket(HOST, PORT);

            out = new PrintWriter(socket.getOutputStream(), true);

            in = new BufferedReader(new InputStreamReader(
                    socketPregunta.getInputStream()));    

            stdIn = new BufferedReader(new InputStreamReader(System.in));


        } catch (Exception e) {}

}

public void sendAnswer(String answer) throws IOException{
        openConnection();

        out.write("PUBLISH-" + answer); //This answer is send incomplete!
        out.flush();

        closeConnection();
}

提前致谢!

【问题讨论】:

    标签: java python sockets printwriter


    【解决方案1】:

    来自文档:

    recv(buffersize[, flags]) -> 数据

    从套接字接收最多 buffersize 个字节。对于可选 flags 参数,请参阅 Unix 手册。当没有数据可用时,阻止 直到至少有一个字节可用或直到远程端 关闭。当远端关闭并读取所有数据时,返回 空字符串。

    所以recv() 可以返回比您要求的更少的字节,这就是您的情况。 socket howto 对此进行了讨论。

    基本上,您需要继续调用recv(),直到您收到完整的消息,或者远程对等方已关闭连接(由recv() 发出信号,返回一个空字符串)。你如何做到这一点取决于你的协议。选项有:

    1. 使用固定大小的消息
    2. 有某种分隔符或标记来检测消息的结尾
    3. 让客户端提供消息长度作为消息的一部分
    4. 让客户端在发送完消息后关闭连接。显然,在这种情况下它将无法收到响应。

    查看您的 Java 代码,选项 4 可能对您有用,因为它正在发送消息然后关闭连接。这段代码应该可以工作:

    s = socket.socket()         
    host = socket.gethostname() 
    # host = "192.168.0.20"
    port = 12345  
    s.bind((host, port))
    
    s.listen(5)                 
    while True:
        c, addr = s.accept()     
        # print 'Got connection from', addr
    
        message = []
        chars_remaining = 8192
        recv_buf = c.recv(chars_remaining)
        while recv_buf:
            message.append(recv_buf)
            chars_remaining -= len(recv_buf)
            if chars_remaining = 0:
                print("Exhausted buffer")
                break
            recv_buf = c.recv(chars_remaining)
    
        # print message
        message = ''.join(message).strip()
        ipAddress = addr[0]
    

    【讨论】:

    • 谢谢你的回答,也许我应该在问题中包含这个,但是java客户端是这样工作的:有一个线程总是打开连接,检查从服务器读取的问题然后关闭连接;这同样适用于答案。它打开连接,发布答案并立即关闭它。因此,它可以作为第四个选项吗?
    • 您好,我尝试使用您的方法阅读消息,但服务器现在挂起。有没有可能通过调用 c.recv() 当它没有读取内容时挂起服务器?再次感谢
    • 我几乎不知道您的服务器在做什么,但它不应该因为客户端而挂起。顺便说一句,您应该在完成后关闭客户端套接字c
    • 是的,我正在接收消息,用它做一些事情并在 while true 重新启动之前关闭连接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-28
    相关资源
    最近更新 更多