simple server with multiple clients
I'm trying to implement simple server with multiple clients. It should receive data from necessary socket, process and then send data to other clients. I use select module from Python standard library. Here's server:
class ProcessingServer:
def __init__(self, bindaddress="localhost", portname=50001, maxqueue=5):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((bindaddress, portname))
self.socket.listen(maxqueue)
self.inputsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.data = ""
def connect_to_output(self, address, port):
self.inputsocket.connect((address, port))
def start(self):
rsocks = []
开发者_StackOverflowwsocks = []
rsocks.append(self.socket)
wsocks.append(self.inputsocket)
self.socket.accept()
while True:
try:
reads, writes, errs = select.select(rsocks, wsocks, [])
except:
return
for sock in reads:
if sock == self.socket:
client, address = sock.accept()
rsocks.append(client)
else:
self.socket.send(self.data)
rsocks.remove(sock)
for sock in writes:
if sock == self.inputsocket:
self.data = sock.recv(512)
wsocks.remove(sock)
print repr(self.data)
Here's simple client:
import socket
mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysocket.connect(("localhost", 50001))
while True:
data = mysocket.recv(512)
print repr(data)
mysocket.close()
Receiving part of server works fine, but server doesn't produce any output. I'm not experienced in network programming at all and It feels like I'm missing something.
There are a few things that seem odd in your script.
The standard usage of the select module is the following: you have one socket to listen to connections, and one socket per connection with the clients.
At first, only this socket is added to your potential readers list and your potential writers list is empty.
Calling select.select(potential_readers, potential_writers, potential_errors) will return 3 lists: - Sockets ready for reading - Sockets ready for writing - Sockets in error
In the list of sockets ready for reading, if the socket is the one listening for the connection, it must accept it and put the new socket in the potential reads, potential writes and potential errors.
If the socket is another one then, there is data to read from this socket. You shoud make a call to sock.recv(length)
If you want to send data, you should send it from your wlist returned by select.select.
The errlist is not used very often.
Now, for the solution for your problem, the way you describe your protocol (if I understood well), it might look like this:
import socket, select
sock_producer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_producer.bind(('localhost', 5000))
sock_producer.listen(5)
producers = []
clients = []
sock_consumer_listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Note: different port to differentiate the clients who receive data from the one who sends messages
sock_consumer_listener.bind(('localhost', 5001))
rlist = [sock_producer, sock_listener]
wlist = []
errlist = []
out_buffer = []
while True:
r, w, err = select.select(rlist, wlist, errlist)
for sock in r:
if sock == sock_producer:
prod, addr = sock.accept()
producers.append(prod)
rlist.append(prod)
elif sock == sock_consumer_listener:
cons, addr = sock.accept()
clients.append(cons)
wlist.append(cons)
else:
out_buffer.append(sock.recv(1024))
out_string = ''.join(out_buffer)
out_buffer = []
for sock in w:
if sock in clients:
sock.send(out_string)
I haven't tested this code so there might be a few errors, but this is close to how I would do it.
Yeah...use zeromq instead:
server.py
import zmq
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://127.0.0.1:50001")
while True:
msg = socket.recv()
print "Got", msg
socket.send(msg)
client.py
import zmq
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://127.0.0.1:50001")
for i in range(100):
msg = "msg %s" % i
socket.send(msg)
print "Sending", msg
msg_in = socket.recv()
精彩评论