我已经写了两个.py代码来在每个外部之间进行通信。 A.py侦听端口8888并将数据发送到7777 B.py侦听端口7777并将数据发送到8888 这两个客户端部分在启动服务器后陷入无限循环。 问题出在哪儿 ?? 如果我只使用A.py中的服务器和B.py中的客户端(反之亦然)而没有任何线程,则它们可以正常工作。
A.py:
import socket
import threading
import thread
import time
class server(threading.Thread):
s = ''
host = 0
port = 0
def __init__(self):
threading.Thread.__init__(self)
global s,host,port
s = socket.socket()
host = socket.gethostname()
port = 8888
def run(self):
global s,host,port
print 'Server started!'
print 'Waiting for clients...'
s.bind((host, port))
s.listen(5)
c, addr = s.accept()
print 'Got connection from', addr
while True:
time.sleep(2)
msg = c.recv(1024)
if len(msg)==0 : break
print addr, ' >> ', msg
class client(threading.Thread):
s = ''
host = 0
port = 0
def __init__(self):
threading.Thread.__init__(self)
global s,host,port
s = socket.socket()
host = socket.gethostname()
port = 7777
def run(self):
try:
time.sleep(5)
global s,host,port
print 'Connecting to ', host, port
s.connect((host, port))
print "Connectd"
while True:
time.sleep(2)
msg = raw_input('CLIENT >> ')
if len(msg)==0:break
s.send(msg)
except:
print "Waiting"
self.run()
thread1 = server()
thread2 = client();
thread1.start()
thread2.start()
thread1.join()
thread2.join();
B.py:
import socket
import threading
import thread
import time
class server(threading.Thread):
s = ''
host = 0
port = 0
def __init__(self):
threading.Thread.__init__(self)
global s,host,port
s = socket.socket()
host = socket.gethostname()
port = 7777
def run(self):
global s,host,port
print 'Server started!'
print 'Waiting for clients...'
s.bind((host, port))
s.listen(5)
c, addr = s.accept()
print 'Got connection from', addr
while True:
time.sleep(2)
msg = c.recv(1024)
if len(msg)==0 : break
print addr, ' >> ', msg
class client(threading.Thread):
s = ''
host = 0
port = 0
def __init__(self):
threading.Thread.__init__(self)
global s,host,port
s = socket.socket()
host = socket.gethostname()
port = 8888
def run(self):
try:
time.sleep(5)
global s,host,port
print 'Connecting to ', host, port
s.connect((host, port))
print "connected"
while True:
time.sleep(2)
msg = raw_input('CLIENT >> ')
if len(msg)==0:break
s.send(msg)
except:
print "waiting"
self.run();
thread1 = server()
thread2 = client();
thread1.start()
thread2.start()
thread1.join()
thread2.join();
答案 0 :(得分:2)
使用global s, host, port
是导致问题的原因。在A.py,
例如,服务器和客户端类都在改变
相同变量s
,host
和port
。通过将端口更改为相同的值,您要么弄乱服务器还是客户端(以先运行的方式)。
如果您不需要,请不要使用global
,而且您很少需要。
在这种情况下,您的问题可以通过使用实例属性来解决。
client.run
方法
致电self.run()
。 Python对递归调用的数量有限制
你可以做,如果客户端必须等待太长时间,递归
在这里调用可能会导致程序失败。相反,你可以使用
while
循环。 (见下文)。import argparse
import socket
import threading
import thread
import time
class server(threading.Thread):
def __init__(self, port):
threading.Thread.__init__(self)
self.s = socket.socket()
self.host = socket.gethostname()
self.port = port
def run(self):
print 'Server started!'
print 'Waiting for clients...'
self.s.bind((self.host, self.port))
self.s.listen(5)
c, addr = self.s.accept()
print 'Got connection from', addr
while True:
time.sleep(2)
msg = c.recv(1024)
if len(msg) == 0 : break
print addr, ' >> ', msg
class client(threading.Thread):
def __init__(self, port):
threading.Thread.__init__(self)
self.s = socket.socket()
self.host = socket.gethostname()
self.port = port
def run(self):
while True:
time.sleep(5)
print 'Connecting to ', self.host, self.port
try:
self.s.connect((self.host, self.port))
break
except Exception as err:
print "Waiting", err
print "Connectd"
while True:
time.sleep(2)
msg = raw_input('CLIENT >> ')
if len(msg) == 0:break
self.s.send(msg)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--server_port', type = int, default = 8888)
parser.add_argument('--client_port', type = int, default = 7777)
args = parser.parse_args()
thread1 = server(args.server_port)
thread2 = client(args.client_port)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
使用
运行它test.py --server 8888 --client 7777
test.py --server 7777 --client 8888
答案 1 :(得分:0)
我感觉你的问题至少部分是由Python的Global Interpreter Lock造成的,它限制了CPython解释器在单个线程上执行字节码。因此,即使您的脚本使用多个线程,也只能执行其中一个线程。程序挂起的原因是因为服务器实例在等待输入时阻塞,因此它永远不会释放GIL,从而阻止客户端能够发送数据。
幸运的是,有几个解决方法:
- 使用Python的multiprocessing包,让程序使用进程而不是线程。因为无论如何使用TCP套接字在类之间共享数据,这应该是最小的代码更改
- IronPython和Jython在他们的实现中不使用GIL,因此如果您已经开始使用线程而不是进程,那么您可能需要调查其中一个项目。
如果你有兴趣,David Beazley几年前创建了一个interesting presentation about the GIL。