我已经编写了一个客户端服务器程序,其中服务器向客户端发送程序,客户端执行接收到的程序。在本例中,它是OpenGL中的线条绘制程序。问题是,在运行服务器和客户端时,整个程序,即将程序发送到服务器和客户端,有时会执行,但有时不会执行。客户端连接起来,然后就卡住了。这个程序不会停止,在我的朋友系统中也是一样的,但在我的系统中,它只是偶尔起作用(大多数时候是不起作用的)。可能的原因是什么?我是不是遗漏了什么?
我的服务器代码:
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
import sys
import threading
import os
import socket
class ClientThread ( threading.Thread ):
# Override Thread's __init__ method to accept the parameters needed:
def __init__ ( self, channel, details ):
self.channel = channel
self.details = details
threading.Thread.__init__ ( self )
#Codes to be executed when thread is executed:
def run ( self ):
a1=self.channel.recv(1024)
print "client says:"+a1
print 'Received connection:', self.details [ 0 ]
finp = open("stringcheck.py","r")
#self.channel.send("#start\n")
info = finp.readlines()
for record in info:
self.channel.send(record)
#self.channel.send(info)
self.channel.send("#p")
server = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
server.bind ( ( '127.0.0.1', 4500) )
#Listens for connections made to socket.
#Specifies maximum number of queued connection.
server.listen ( 5 )
while True:
channel, details = server.accept()
#Create an instance of thread class and call its start method.
ClientThread ( channel, details ).start()我的客户端代码:
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
OpenGL.ERROR_CHECKING=False
import os
import socket
import threading
import thread
import subprocess
class ConnectionThread( threading.Thread ):
def run ( self ):
client = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
client.connect( ( '127.0.0.1', 9000) )
client.send("connected")
a=client.recv(1024)
b=a
f=1
while f:
print 'sdf'
a = client.recv(1024)
print 'qwe'
if a=="#p":
f=0
break
b+=a
print b
exec(b)
client.close()
ConnectionThread().start()
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
OpenGL.ERROR_CHECKING=False
import os
import socket
import threading
import thread
import subprocess
class ConnectionThread( threading.Thread ):
def run ( self ):
client = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
client.connect( ( '127.0.0.1', 9000) )
client.send("connected")
a=client.recv(1024)
b=a
f=1
while f:
a = client.recv(1024)
print 'qwe'
if a=="#p":
f=0
break
b+=a
print b
exec(b)
client.close()
ConnectionThread().start()发布于 2011-01-14 18:51:53
TCP socket是一个流(数据包是实现细节)。
网络堆栈经过优化,以限制发送的数据包数量。因此,当您在一个套接字上多次调用send()时,网络堆栈可以自由地在多个数据包之间拆分(或不拆分)数据。
在实际网络上运行的计算机上,如果在调用send()时仍有一个数据包等待发送,则新数据将被附加到等待的数据包。在接收端,网络堆栈可以自由地合并多个数据包(从套接字接收的数据被缓冲),以便一次显示数据。
因此,在服务器中,您可以这样写:
for record in info:
self.channel.send(record)
self.channel.send("#p") 最后一个分组可以包含连接在一起的节目的结尾和终止符。在客户端:
a = client.recv(1024)
if a=="#p":
break终止符可能不在接收到的数据包的开头,也可能不是数据包中存在的唯一字符。如果是这种情况,那么您将不会检测到终结器,也不会退出循环,再次调用recv(),并在此处停止,因为recv()是一个阻塞调用,服务器将不再发送任何数据。
因此,您必须选择另一种知道服务器何时完成数据发送的方法。有很多种可能性:
if a=="#p":,编写if a.endswith("#p"):。这纠正了您的代码中存在的问题recv()返回空字符串时,您会检测到连接已关闭,然后您就知道程序已收到。不幸的是,如果服务器在发送整个程序之前崩溃,您将在client上执行不完整的程序
有无数其他的可能性来纠正这个问题……
2.你的接收逻辑是错误的
现在,仔细看看接收逻辑(编辑代码以删除不相关的行)
1. a=client.recv(1024)
2. b=a
3. f=1
4. while f:
5. a = client.recv(1024)
6. if a=="#p":
7. f=0
8. break
9. b+=a在这里,您首先等待一些数据(第1行)。然后进入while循环(第4行),再次等待一些数据(第5行)!
recv()是一个阻塞调用:这意味着它不会返回,直到有一些数据要返回或连接关闭。如果服务器发送的数据少于1024字节(包括终止符),您将收到第1行(包括终止符)上的所有内容,但仍在等待第5行上的更多数据...
请注意,您的测试中仍然存在一个bug :如果分隔符被分成两个recv()调用(如果程序的长度正好是1023个字节,就会发生这种情况),a.endswith('#p')的计算结果永远不会是True。
所以这里是一个正确的接收逻辑,它在接收到一些数据后立即测试终结器:
a = client.recv(1024)
b = a
f = 1
while f:
if b.endswith("#p"):
f=0
break
a = client.recv(1024)
b += a请注意,通过删除不必要的变量,可以大大简化这一过程:
b = client.recv(1024)
while not b.endswith("#p"):
b += client.recv(1024)3.正确释放代码中使用的资源
我一开始并没有强调这一点,但你应该总是正确地关闭你的连接!
创建python语言的目的是,一旦保存连接的变量不再被引用(在您的例子中,当它超出范围时),连接就会隐式关闭。但是,显式地关闭它将清楚地表明您希望在哪个点关闭连接。
一些实现可能决定将资源的发布推迟到以后的时间(Jython用户可能已经遇到了这个问题),使连接保持打开状态……这不是问题,但当您的程序发展到功能更完整的产品时,可能会导致稍后出现奇怪的行为。
https://stackoverflow.com/questions/4690155
复制相似问题