optimizing simple server with multiple clients
I've successfully implemented simple server with multiple clients:
class ProcessingServer:
def __init__(self, bindaddress="127.0.0.1", 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 start(self):
rsocks, wsocks = [], []
rsocks.append(self.socket)
rsocks.append(self.inputsocket)
print "Waiting for connection..."
self.inputsocket.connect(("192.168.1.1", 1234))
print "Connected."
clients = []
try:
while True:
try:
reads, writes, errs = select.select(rsocks, wsocks, [])
except:
return
for sock in reads:
if sock == self.socket:
client, address = sock.accept()
print "Client ", address, " connected"
wsocks.append(client)
clients.append(client)
elif sock == self.inputsocket:
self.data.append(sock.recv(256))
outstring = ""
if len(self.data) > 1:
msg_list = self.data[0].split('\n')
for msg in msg_list:
if msg != '':
curr_msg = msg.split(',')
process_message(curr_msg)
outstring = ','.join(curr_msg)
print curr_msg
self.data = []
for sock in writes:
if sock in clients:
if outstring != "":
sock.send(outstring)
except KeyboardInterrupt:
print "Server was stopped"
self.inputsocket.close()
self.socket.close()
for sock in writes:
sock.close()
for sock in reads:
sock.close()
for sock in clients:
sock.close()
process_message
just adds some fields
Everything works fine, but when client connects to server, CPU load goes to 100%.
Here's client:
import socket
mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysocket.connect(("127.0.0.1", 50001))
while True:
data = mysocket.recv(512)
mysocket.close()
outfile.close()
Here are profiler stats:
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 34.563 34.563 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 <string>:1(bind)
1 0.000 0.000 0.000 0.000 <string>:1(connect)
6870763 6.408 0.000 9.030 0.000 <string>:1(fileno)
1 0.000 0.000 0.000 0.000 <string>:1(listen)
1 0.000 0.000 0.000 0.000 server.py:113(__init__)
1 4.409 4.409 34.556 34.556 server.py:123(start)
1 0.007 0.007 34.563 34.563 server.py:176(main)
91 0.002 0.000 0.010 0.000 server.py:80(process_message)
3 0.000 0.000 0.000 0.000 socket.py:182(__init__)
1 0.000 0.000 0.000 0.000 socket.py:196(accept)
18 0.000 0.000 0.000开发者_高级运维 0.000 {getattr}
2290358 0.906 0.000 0.906 0.000 {len}
1 0.000 0.000 0.000 0.000 {method 'accept' of '_socket.socket' objects}
186 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'bind' of '_socket.socket' objects}
1 0.000 0.000 0.000 0.000 {method 'connect' of '_socket.socket' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
6870763 2.622 0.000 2.622 0.000 {method 'fileno' of '_socket.socket' objects}
273 0.000 0.000 0.000 0.000 {method 'insert' of 'list' objects}
91 0.000 0.000 0.000 0.000 {method 'join' of 'str' objects}
1 0.000 0.000 0.000 0.000 {method 'listen' of '_socket.socket' objects}
182 0.001 0.000 0.001 0.000 {method 'recv' of '_socket.socket' objects}
71 0.001 0.000 0.001 0.000 {method 'send' of '_socket.socket' objects}
182 0.000 0.000 0.000 0.000 {method 'split' of 'str' objects}
2290268 20.197 0.000 29.227 0.000 {select.select}
18 0.000 0.000 0.000 0.000 {setattr}
What's wrong with it?
I’d suggest that select
returns that there is some writeable socket. And well, if there is no readable socket and outstring stays ''
, then you immediately run the loop again and again, causing high cpu load. So its probably better, to only add the wsocks if you actually need to write data. Then the select call will wait until data is available to read.
Concerning your comment, replace:
reads, writes, errs = select.select(rsocks, wsocks, [])
with
reads, writes, errs = select.select(rsocks, [], [])
and add in front of for sock in writes:
add:
reads, writes, errs = select.select([], wsocks, [], 0)
精彩评论