Python socket的Recv不正常,能否解释一下
我正在尝试为我的命令行服务器创建一个图形用户界面(GUI)客户端。不过,我遇到了一些烦人的问题,怎么也解决不了。
我不太确定实际的问题是什么,因为有时候代码能正常工作,有时候又不行。我觉得主要问题是我最开始尝试了这个
while 1:
self.data = s.recv(1024)
if not self.data():
break
else:
print self.data()
然后我用这个发送数据
for f in files:
s.send(f)
每个 f 是一个文件名的字符串。我原本以为在接收端每次调用 recv 时会收到一个文件名,但实际上在一次 recv 调用中,我收到了一个大块的文件名,我猜大约有 1024 个字符。
这让检查数据的结束变得不可能,因此循环一直没有退出。
这是我现在的代码
def get_data(self,size = 1024):
self.alldata = ""
while 1:
while gtk.events_pending():
gtk.main_iteration()
self.recvdata = self.s.recv(size)
self.alldata += self.recvdata
if self.alldata.find("\r\n\r\nEOF"):
print "recieved end message"
self.rdata = self.alldata[:self.alldata.find("\r\n\r\nEOF")]
break
print "All data Recieved: " + str(len(self.rdata)) + "Bytes"
print "All data :\n" + self.rdata + "\n-------------------------------------------------"
self.infiles = self.rdata.split("-EOS-")
for nf in self.infiles:
if len(nf) > 2:
self.add_message(self.incomingIcon,nf)
目前我正在尝试让客户端正确地从服务器读取数据。我希望发生的情况是,当输入命令列表并发送到客户端时,服务器会把数据发回来,每个文件名都添加到列表中。
有时候这能正常工作,但有时候只返回 1200 个文件中的一个。如果执行正常,如果我尝试输入另一个命令并发送,整个 GTK 窗口就会崩溃,程序变得无响应。
抱歉我无法更好地解释这个问题,我尝试了很多不同的解决方案,但都出现了不同的错误。
如果有人能解释一下 recv 命令以及它为什么可能会出错,我发送数据到客户端的方式是这样的
if(commands[0] == 'list'):
whatpacketshouldlooklike=""
print "[Request] List files ", address
fil = list_files(path)
for f in fil:
sdata = f
whatpacketshouldlooklike += sdata + "-EOS-"
newSock.send(sdata +"-EOS-")
#print "sent: " + sdata
newSock.send("\r\n\r\nEOF")
whatpacketshouldlooklike += "\r\n\r\nEOF"
print "---------------------------------"
print whatpacketshouldlooklike
print "---------------------------------"
4 个回答
2
你的代码有几个问题。
首先,有些人已经提到过一个基本的概念,那就是发送(sends())和接收(recv())之间没有直接的关系。你不能控制在调用recv()时返回哪些数据。你需要某种协议来管理数据。在你的情况下,可以简单地用"\n"来结束命令字符串,然后在服务器上检查"\n"来处理数据。
接下来还有其他问题:
- 你在使用send时没有检查返回的大小。send()并不保证数据会完全写入,如果你需要确保数据全部发送,请使用sendall()。
- 如果你在一个阻塞的套接字中使用recv(1024)(这是默认设置),你的服务器代码可能会一直等到接收到1024字节的数据,这样会导致你无法处理消息,直到收到完整的数据块。你需要使用非阻塞的套接字,并且使用select模块。
3
你在第一部分遇到的问题是,套接字(sockets)是基于流的,而不是基于消息的。你需要设计一种消息的抽象层,放在流的上面。这样,另一端就能知道发生了什么(比如,作为一个命令应该接收多少数据),而不是在猜测应该发生什么。