【问题标题】:Cant receive data from socket无法从套接字接收数据
【发布时间】:2016-11-08 17:29:32
【问题描述】:

我正在制作一个客户端-服务器程序,但客户端部分有问题。 问题在于无限接收数据。我已经在 python 解释器中测试了下面列出的这个特定的类。我已经成功(可能没有)连接到谷歌,但随后程序在 data = self.socket.recv(1024) 中的函数 recvData() 中停止

class client():
def __init__(self, host, port):
    self.host = host
    self.port = port

    self.socket = self.connect()
    self.command = commands()


def connect(self):
    '''
    Connect to a remote host.
    '''
    try:
        import socket
        return socket.create_connection((self.host, self.port))
    except socket.error:
        print(":: Failed to connect to a remote port : ")

def sendCommand(self, comm):
    '''
    Send command to remote host
    Returns server output
    '''
    comman = comm.encode()
    # for case in switch(comman):
    #         if case(self.command.RETRV_FILES_LIST.encode()):
    #             self.socket.send(b'1')
    #             return self.recvData()

    #         if case():
    #             print(":: Got wrong command")

    if (comman == b'1'):
        self.socket.send(b'1')
        return self.recvData()

def recvData(self):
    '''
    Receives all the data
    '''
    i = 0
    total_data = []
    while(True):
        data = self.socket.recv(1024)
        if not data: break
        total_data.append(data)
        i += 1
        if i > 9:
            break
    return total_data

关于评论部分: 我认为Case实现有问题,所以只使用了if-then语句。但事实并非如此。

【问题讨论】:

  • 你打电话给recvData,它会永远挂起?
  • 您能否添加更多关于运行代码结果的信息(您是否遇到异常?静默结束?挂起?),以及您期望的结果是什么?
  • 是的,它会阻止接收数据
  • @glibdud 它以静默方式结束,当我使用 telnet 连接到谷歌并发送 '1' 它以 404 html 响应时,我想要的结果与 telnet 相同
  • 这里没有足够的信息可以肯定地说,但我想服务器正在等待更多数据。如果您只是发送字符“1”,那么这不是一个完整(或有效)的 HTTP 请求。

标签: python sockets


【解决方案1】:

您的问题是self.socket.recv(1024) 仅在服务器端关闭套接字并且已接收到所有数据时才返回空字符串。您对客户端进行编码的方式,它不知道已收到完整的消息并等待更多消息。你如何处理这个问题很大程度上取决于服务器使用的协议。

考虑一个网络服务器。它发送一个以行分隔的标头,包括一个content-length 参数,告诉客户端它应该读取多少字节。客户端扫描换行符,直到标头完成,然后使用该值执行recv(exact_size)(如果很大,它可以改为读取块),这样当最后一个字节进入时,recv 就不会阻塞。

即便如此,也需要做出决定。客户端知道网页有多大,但可能希望将部分数据发送给调用者,以便它可以在收到所有数据之前开始绘制页面。当然,调用者需要知道发生了什么——API 本身有一个协议或一组规则。

您需要定义客户端如何知道消息已完成,以及它传递回其调用者的确切内容。解决这个问题的一个好方法是让一些其他协议,例如 [zeromq](http://zeromq.org/ 为你工作。一个简单的 python 客户端/服务器可以用xmlrpc 实现。还有很多其他方法。

你说你正在实现一个客户端/服务器程序,然后你提到了“连接到谷歌”和 telnet...这些都是非常不同的东西,单一的客户端策略不会适用于所有这些。

【讨论】:

  • 感谢您的回答!问题在于向 google 发送消息时没有行尾 '\n' 但是感谢 zeromq,它非常适合我的宠物项目 :)
  • @Fireship 太棒了!简单地阅读 zeromq 模式是对这个星球上网络编程的最佳介绍。
猜你喜欢
  • 1970-01-01
  • 2017-02-05
  • 2015-11-26
  • 2020-03-13
  • 2012-12-28
  • 2020-02-29
  • 2017-04-09
  • 2018-05-18
  • 2016-08-04
相关资源
最近更新 更多