如何在Python中使用套接字建立双向通信?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Python中使用套接字建立双向通信?相关的知识,希望对你有一定的参考价值。

所以,我有一个服务器脚本从客户端脚本接收图像,并且应该发送一个确认“OK”。但承认永远不会通过。

服务器脚本 -

import socket,sys               

s = socket.socket()         
print("Socket successfully created")

port =80                

s.bind(('', port))        
print("socket binded to %s" %(port))
s.listen(5)     
print("socket is listening")            

while True:
   c, addr = s.accept()     
   print('Got connection from', addr)
   file_name=s.recv(1024)
   file_name=fil_ename.decode("utf-8")
   with open(file_name,"wb")as f:
      while True:
         data=c.recv(1024)
         if not data:
            break
         f.write(data)

   c.send(bytes('Thank you ! File received.',"utf-8"))
   c.close()

客户端脚本 -

import socket            

s = socket.socket()         

# Define the port on which you want to connect
port = 80              

s.connect(('IP address of my server', port))
s.send(bytes("hand.jpeg","utf-8"))
f=open("back.jpeg","rb")
data=f.read(512)
while data:
    s.send(data)
    data=f.read(512)
f.close()
print(s.recv(10))

服务器不发送任何确认,似乎卡在for循环中。但是,如果我从服务器脚本中删除行c.send(bytes('Thank you ! File received.',"utf-8")),代码运行良好。此外,如果我从服务器端删除接收部分并只发送确认部分,即c.send(bytes('Thank you ! File received.',"utf-8")),客户端将收到该消息。但如果在服务器端进行了receive(图像文件)和确认的组合,如代码所示,则服务器端无法响应。

需要注意的重要一点是,在KeyBoardInterrupting上面的程序中,它显示服务器端脚本被挂起/卡在data=c.recv(1024)行中。但是如果删除确认行,同样的问题就会消失。

注意: - 客户端脚本在我的本地计算机上运行,​​服务器端脚本在Google云虚拟机实例上运行。

请帮忙。谢谢。

答案

嗯......我不认为我完全相信你对这种行为的描述。但我确实知道什么是错的。您的服务器位于接收循环中是完全合理的,因为客户端没有向连接发出EOF信号。在什么情况下你认为这实际上是break

if not data:
    break

答案是客户端需要close套接字,或使用shutdown(SHUT_WR)表示它不会再发送任何数据。所以,在客户端做你想做的事:

...
f.close()
s.shutdown(socket.SHUT_WR)
...

现在,下次服务器调用recv时,它将返回一个空字符串,并且将获取上面的break

这使得连接在一个方向上打开而在另一个方向上打开。因此客户端将无法再发送任何数据。但是,服务器仍然能够发送到客户端,直到它关闭套接字(或使用shutdown本身)。

还有一个更微妙的问题。您假设您的第一个服务器端recv将仅接收包含您的文件名的字节。 99.9%的时间可行。但是当服务器第一次调用send时,下一个客户端recv的数据也可能可用。这可能会给你一个虚假的文件名(虽然不一定是非法的)并且肯定意味着你的文件没有忠实地转移。

你永远不应该假设一个对等体提供的单个send的数据将被另一方的相应单个recv接收。收到的数据可能或多或少,由应用程序决定数据的框架,以确保它完全收到预期的数量。

另一答案

这里

while True:
    data=c.recv(1024)
    if not data:
       break
    f.write(data)

它会在收到消息后循环回等待消息,因为您在接收数据后没有中断while循环。 if not data:没有做任何事情,因为recv()停止并等待它得到消息,因此data永远不会是什么。您应该在收到消息后通过在break之后添加f.write(data)来中断循环,或者在循环中发送OK。

以上是关于如何在Python中使用套接字建立双向通信?的主要内容,如果未能解决你的问题,请参考以下文章

Java:加密的服务器/客户端双向通信?

如何在不同进程中建立Activity和Service之间的双向通信?

R和Python之间的双向通信

12.5-全栈Java笔记:Java网络编程

网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

通过 ssh 隧道使用套接字进行双向通信