我正在尝试为我的命令行服务器创建一个gui客户端。但是,我遇到了一些似乎无法解决的烦人问题。
我不是100%确定实际问题是什么,因为有时代码会起作用,有时候它不会。我认为最主要的问题是我最初尝试了
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调用收到一个文件名,但是在一个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 "---------------------------------"
答案 0 :(得分:3)
您在第一部分中遇到的问题是套接字是基于流的,而不是基于消息的。您需要在流的顶部提出消息抽象。这样管道的另一端知道发生了什么(作为一个命令的一部分需要多少数据),而不是猜测应该发生什么。
答案 1 :(得分:2)
使用抽象层(Pyro,XML-RPC,zeromq)或定义自己的协议来区分消息。
例如,作为自己的协议,您可以在每个字符串之前将消息的长度作为“标题”发送。在这种情况下,您应该使用struct
模块将长度解析为二进制格式。再问一遍,如果你想这样做,但我强烈建议你选择一个提到的抽象层。
答案 2 :(得分:2)
您的代码存在不同的问题。
让我们从一些人已经注释的基础开始,send()和recv()之间没有关系,你不能控制在recv(调用)上返回哪部分数据,你需要某种在你的情况下,它可以像使用“\ n”终止命令字符串一样简单,并在服务器上检查“\ n”以使用数据。
现在还有其他问题:
答案 3 :(得分:0)
我的源代码:
def readReliably(s,n):
buf = bytearray(n)
view = memoryview(buf)
sz = 0
while sz < n:
k = s.recv_into(view[sz:],n-sz)
sz += k
# print 'readReliably()',sz
return sz,buf
def writeReliably(s,buf,n):
sz = 0
while sz < n:
k = s.send(buf[sz:],n-sz)
sz += k
# obj = s.makefile(mode='w')
# obj.flush()
# print 'writeReliably()',sz
return sz
这些功能的使用:
# Server
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
s.bind((host,port))
s.listen(10) # unaccepted connections
while True:
sk,skfrom = s.accept()
sz,buf = io.readReliably(sk,4)
a = struct.unpack("4B",buf)
print repr(a)
# ...
io.writeReliably(sk,struct.pack("4B",*[0x01,0x02,0x03,0x04]))
另请参阅有关recv_into(...)
,https://docs.python.org/2/library/socket.html#socket.socket.recv_into的官方文档