如何在 Python 中使用套接字建立双向通信?
How to establish a 2 way communication using sockets in 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"))
,客户端会收到消息。但是如果如代码所示在服务器端进行接收(图像文件)和确认的组合,则服务器端无法响应。
需要注意的重要一点是,在 KeyBoardInterrupt-ing 上面的程序中,它显示服务器端脚本在 data=c.recv(1024)
行中是 hanged/stuck。但是如果删除确认行,同样的问题就消失了。
注意:- 客户端脚本是 运行 在我的本地计算机上,服务器端脚本是 运行 在 Google 云 VM 实例上。
请帮忙。
谢谢。
这里
while True:
data=c.recv(1024)
if not data:
break
f.write(data)
它在收到消息后循环返回等待消息,因为您在接收数据后没有中断 while 循环。 if not data:
不做任何事情,因为 recv()
停止并等待它收到消息,因此 data
永远不会什么都没有。您应该在收到消息后通过在 f.write(data)
之后添加 break
来打破循环,或者在循环中发送 OK。
嗯...我不认为我完全相信你对行为的描述。但我知道哪里出了问题。您的服务器处于接收循环中是完全合理的,因为客户端尚未向连接发出 EOF 信号。在什么情况下你认为这实际上会 break
?
if not data:
break
答案是客户端需要close
套接字,或者使用shutdown(SHUT_WR)
来表明它将不再发送任何数据。所以在客户端做你想做的事:
...
f.close()
s.shutdown(socket.SHUT_WR)
...
现在服务器下次调用 recv
时,它会返回一个空字符串,上面的 break
将被采用。
这使连接在一个方向上打开,但在另一个方向上不打开。因此客户端将无法发送更多数据。但是,在 it 关闭套接字(或使用 shutdown
本身)之前,服务器仍然能够发送给客户端。
还有一个更微妙的问题。您假设您的第一个 server-side recv
将只接收包含您的文件名的字节。 99.9% 的时间都可以。但是当服务器第一次调用 recv
时,来自下一个 client-side send
的数据可能 也 可用。这可能会给您一个伪造的文件名(虽然不一定是非法文件名)并且肯定意味着您的文件没有如实传输。
您永远不应该假设一个对等方的单个 send
提供的数据将被另一侧相应的单个 recv
接收。接收到的数据可能或多或少,这取决于应用程序来构建数据以确保它接收到准确的数量。
所以,我有一个服务器脚本,它从客户端脚本接收图像,并应该发送一个确认 "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"))
,客户端会收到消息。但是如果如代码所示在服务器端进行接收(图像文件)和确认的组合,则服务器端无法响应。
需要注意的重要一点是,在 KeyBoardInterrupt-ing 上面的程序中,它显示服务器端脚本在 data=c.recv(1024)
行中是 hanged/stuck。但是如果删除确认行,同样的问题就消失了。
注意:- 客户端脚本是 运行 在我的本地计算机上,服务器端脚本是 运行 在 Google 云 VM 实例上。
请帮忙。 谢谢。
这里
while True:
data=c.recv(1024)
if not data:
break
f.write(data)
它在收到消息后循环返回等待消息,因为您在接收数据后没有中断 while 循环。 if not data:
不做任何事情,因为 recv()
停止并等待它收到消息,因此 data
永远不会什么都没有。您应该在收到消息后通过在 f.write(data)
之后添加 break
来打破循环,或者在循环中发送 OK。
嗯...我不认为我完全相信你对行为的描述。但我知道哪里出了问题。您的服务器处于接收循环中是完全合理的,因为客户端尚未向连接发出 EOF 信号。在什么情况下你认为这实际上会 break
?
if not data:
break
答案是客户端需要close
套接字,或者使用shutdown(SHUT_WR)
来表明它将不再发送任何数据。所以在客户端做你想做的事:
...
f.close()
s.shutdown(socket.SHUT_WR)
...
现在服务器下次调用 recv
时,它会返回一个空字符串,上面的 break
将被采用。
这使连接在一个方向上打开,但在另一个方向上不打开。因此客户端将无法发送更多数据。但是,在 it 关闭套接字(或使用 shutdown
本身)之前,服务器仍然能够发送给客户端。
还有一个更微妙的问题。您假设您的第一个 server-side recv
将只接收包含您的文件名的字节。 99.9% 的时间都可以。但是当服务器第一次调用 recv
时,来自下一个 client-side send
的数据可能 也 可用。这可能会给您一个伪造的文件名(虽然不一定是非法文件名)并且肯定意味着您的文件没有如实传输。
您永远不应该假设一个对等方的单个 send
提供的数据将被另一侧相应的单个 recv
接收。接收到的数据可能或多或少,这取决于应用程序来构建数据以确保它接收到准确的数量。