我正在尝试创建一个非常简单的聊天。使用PyZMQ库。由于套接字不是线程安全的,我使用两个套接字并在每个套接字上运行一个线程。一个检查传入消息,一个检查发送消息。
但我的程序正在给我,错误信息:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Python27\lib\multiprocessing\forking.py", line 381, in main
self = load(from_parent)
File "C:\Python27\lib\pickle.py", line 1384, in load
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Python27\lib\multiprocessing\forking.py", line 381, in main
self = load(from_parent)
File "C:\Python27\lib\pickle.py", line 1384, in load
return Unpickler(file).load()
File "C:\Python27\lib\pickle.py", line 864, in load
return Unpickler(file).load()
File "C:\Python27\lib\pickle.py", line 864, in load
dispatch[key](self)
File "C:\Python27\lib\pickle.py", line 1089, in load_newobj
dispatch[key](self)
File "C:\Python27\lib\pickle.py", line 1089, in load_newobj
obj = cls.__new__(cls, *args)
File "zmq\backend\cython\socket.pyx", line 279, in zmq.backend.cython.socket.Socket.__cinit__ (zmq\backend\cython\socket.c:3456)
TypeError: context must be specified
obj = cls.__new__(cls, *args)
File "zmq\backend\cython\socket.pyx", line 279, in zmq.backend.cython.socket.Socket.__cinit__ (zmq\backend\cython\socket.c:3456)
TypeError: context must be specified
我无法弄清楚为什么我会得到它们,或者如何解决它。
这也是我的逻辑错误吗?:
我们启动创建套接字并将其绑定到端口的服务器。然后它监听消息/连接的套接字。然后我们创建另一个套接字并将其绑定到同一个端口。我们创建一个新线程,使我们等待在第一个套接字上收到消息然后发送到第二个套接字。 然后我们有一个连接到第一个套接字的客户端。我们为它创建一个新线程,以便它可以在另一个套接字上侦听传入的消息,因此它可以使用第一个线程通过第一个套接字发送消息。
server.py
from communication import Communication
from multiprocessing import Process
import zmq
import random
import sys
import time
if __name__ == '__main__':
if len(sys.argv) > 1:
port = sys.argv[1]
else:
port = "5556"
c = Communication(port)
c.bind()
recieverP = Process(target=c.reciever)
recieverP.start()
print("first process")
c2 = Communication(port)
c2.connect()
senderP = Process(target=c2.sender)
senderP.start()
print("second process")
client.py
from communication import Communication
from multiprocessing import Process
import zmq
import random
import sys
import time
if __name__ == '__main__':
if len(sys.argv) > 1:
port = sys.argv[1]
else:
port = "5556"
c = Communication(port)
c.connect()
recieverP = Process(target=c.reciever, args=())
senderP = Process(target=c.sender,args=())
recieverP.start()
senderP.start()
communications.py
import zmq
class Communication:
def __init__(self, port):
context = zmq.Context.instance()
self.port = port
self.socket = context.socket(zmq.PAIR)
def connect(self):
self.socket.connect("tcp://localhost:%s" % self.port)
def bind(self):
self.socket.bind("tcp://*:%s" % self.port)
def sender(self):
while True:
msg = raw_input("> ")
self.socket.send(msg)
def reciever(self):
while True:
msg = self.socket.recv()
print("> " + msg)
答案 0 :(得分:1)
这些是进程而不是线程。出现此问题是因为在后台Python必须将Communication
对象的副本发送到子进程。但是,您的对象包含无法序列化的套接字对象。使用threading
和Thread
对象代替Process
,您将不会遇到此问题。这是因为线程在同一进程中运行。
答案 1 :(得分:1)
以下完全正常工作的版本。我做了一些改动:
client.py
和server.py
合并为一个带有“角色”参数的app.py
。 (这只是为了避免大量重复的代码。)KeyboardException
,因此您可以按Ctrl + C退出。c2
中的server.py
。我不确定那是什么目的,我不知道这是否有用。 (好像你是connect
而不是bind
ing?)port
改为int
而不是str
,因为它是。{ : - )app.py:
import argparse
from threading import Thread
import time
from communication import Communication
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("role", help="either 'client' or 'server'", choices=['client', 'server'])
parser.add_argument("--port", "-p", type=int, help="port number", default=5556)
args = parser.parse_args()
c = Communication(args.port)
if args.role == 'client':
c.connect()
else:
c.bind()
receiverP = Thread(target=c.receiver)
senderP = Thread(target=c.sender)
receiverP.daemon = True
senderP.daemon = True
try:
receiverP.start()
senderP.start()
while True:
time.sleep(100)
except (KeyboardInterrupt, SystemExit):
pass
communication.py:
import zmq
class Communication:
def __init__(self, port):
self.port = port
context = zmq.Context.instance()
self.socket = context.socket(zmq.PAIR)
def connect(self):
self.socket.connect("tcp://localhost:%d" % self.port)
def bind(self):
self.socket.bind("tcp://*:%d" % self.port)
def sender(self):
while True:
self.socket.send(raw_input())
def receiver(self):
while True:
print(self.socket.recv())