【问题标题】:TCP Socket unable to send data even after executing sendall ()TCP Socket 执行 sendall() 后也无法发送数据
【发布时间】:2017-04-12 05:07:23
【问题描述】:

您好,我有多个系统使用 TCP 连接通过消息进行通信。

在两者之间的通信过程中,我首先发送一个消息作为“启动进程”,作为回报它应该回复为“进程启动”

但是,其他系统没有收到“Process Started”消息,而没有任何异常地执行了sendall(“Process Started”)行。

我的示例代码如下:

TCP 初始化:

def __init__(self):
    self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, struct.pack('ll',0,1))
    self.tcp.bind('',12000)
    self.tcp.listen(1)
    self.client, seld.address = self.tcp.accept()
    (self.Ip,self.port)= self.address

主要功能:

while True:
    msg =""
    try:
       msg = self.client.recv(512)
    except socket.error as e:
       if e[0] == 11:
           # exception for RECVTIMEO used in the socket creation.
           pass
    if (msg == "Start Process"):
          send = "Process Started"
          self.client.sendall(send)
          print "status sent"

在执行这段代码时,我能够收到消息“开始进程”。但是在执行self.client.sendall(send)行时没有发送“进程启动”,我已经在wireshark中捕获了数据包,我得到了包含“启动进程”的数据包,但没有获得“进程启动”的数据包

有人可以帮我吗???

【问题讨论】:

    标签: python c++ sockets tcp wireshark


    【解决方案1】:

    您的代码有几个问题,但您现在遇到的问题是,如果您使用 telnet 连接到端口 12000 并发送“启动进程”并按 Enter,您实际上将发送和接收启动进程\n 而不是启动进程和你的 if 语句不匹配。如果你去掉尾随换行符,你可以减轻这种情况:

    try: 
        msg = self.client.recv(512)
        msg = msg.strip()
    

    不过,您的程序可能需要一些调整。当您将套接字设置为非阻塞时,当您尝试接受尚不存在的连接时, self.tcp.accept() 会引发异常。在您收到正确的消息后,self.client.recv() 也是如此。当您添加条时,您的 if 子句将匹配并且您将得到响应。但是,它只会继续响应,因为它会立即再次尝试 recv(512),但因异常而失败,然后您将其捕获并再次执行 if 子句。 msg 仍然是“Start Process”,因为它没有改变(连续的 recv 刚刚失败,它没有返回“”或 None)。

    尝试将 if 子句移动到 try/except 结构中,并且仅在您确实收到 msg 时才比较 msg。

    这个程序也非常浪费,因为它大部分时间都在一个繁忙的循环中运行,等待连接或消息。如果您需要使用非阻塞套接字,则需要解决此问题。

    更好的方法可能是使用线程来拥有一个阻塞线程来侦听和接受新连接,并且对于每个连接都会产生一个工作线程。然后这些线程可能会在 recv() 中阻塞,直到收到消息。

    只是一个想法。

    汉努

    【讨论】:

    • 更新了上述代码,我在循环中将 msg 重置为 NULL。我没有在问题中包含我的其他程序,它稍后会向该程序发送“启动进程”,该程序只是在等待其他程序启动,它通过 TCP 绑定,当它收到“启动进程”时它应该发送 "Process Started" ,但它没有这样做。
    • 我确实在 recv() 和 sendall 之间使用了 time.sleep,然后它工作了,但我无法理解这种行为的原因
    • ...你得到“状态发送”打印输出,确认 sendall() 已执行?
    • 我没有在您的代码中标记的另一个问题是您的 recv() 不一定会收到整个消息。它在函数调用时接收接收缓冲区中的任何内容。如果你睡在某个地方,你更有可能——但不能保证——接收到整个消息,而不仅仅是前五个字节。在任何情况下,您都应该将其构建到您的代码中,并以某种方式确保您在处理之前收到了完整的消息。否则,您最终可能会在不同的迭代中比较“Star”和“t Process”,但两者都不会匹配。
    • 是的“状态已发送”已获得,您所说的问题,因为我在开头和结尾使用了一些解析标签,例如 /yyy/ 在开头和 /xxx/ 在结束,然后检查收到的消息并相应地拆分它,我希望你假设我是如何获取消息的。它正在执行 sendall()。但仍然在wireshark它无法捕获数据包,对于类似的情况,在sendall()之前使用time.sleep(0.05)它能够发送并且数据包也被捕获在wireshark中。我想了解这种行为
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多