所以,我有一个服务器脚本从客户端脚本接收图像,并且应该发送一个“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云虚拟机实例上运行。
请帮忙。 谢谢。
答案 0 :(得分:0)
这里
while True:
data=c.recv(1024)
if not data:
break
f.write(data)
它会在收到消息后循环回等待消息,因为您在接收数据后不会中断while循环。自if not data:
停止后,recv()
不执行任何操作,并等待收到消息,因此data
永远不会发生任何事情。您应该在收到消息后通过在break
之后添加f.write(data)
来中断循环,或者在循环中发送OK。
答案 1 :(得分:0)
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
接收。收到的数据可能或多或少,并且由应用程序决定数据的框架,以确保它准确地收到预期的数量。