Problem with writing fast UDP server
Gabriel Genellina
gagsl-py2 at yahoo.com.ar
Thu Nov 20 21:20:49 EST 2008
En Thu, 20 Nov 2008 14:24:20 -0200, Krzysztof Retel
<Krzysztof.Retel at googlemail.com> escribió:
> On Nov 20, 4:00 pm, bieff... at gmail.com wrote:
>> On 20 Nov, 16:03, Krzysztof Retel <Krzysztof.Re... at googlemail.com>
>> wrote:
>>
>> > I am struggling writing fast UDP server. It has to handle around 10000
>> > UDP packets per second. I started building that with non blocking
>> > socket and threads. Unfortunately my approach does not work at all.
>> > I wrote a simple case test: client and server. The client sends 2200
>> > packets within 0.137447118759 secs. The tcpdump received 2189 packets,
>> > which is not bad at all.
>> > But the server only handles 700 -- 870 packets, when it is non-
>> > blocking, and only 670 – 700 received with blocking sockets.
>> > The client and the server are working within the same local network
>> > and tcpdump shows pretty correct amount of packets received.
>
> I wonder if there is a kind of setting for socket to allow no delays?
I've used this script to test sending UDP packets. I've not seen any
delays.
<code>
"""a very simple UDP test
Usage:
%(name)s client <remotehost> <message to send|length of message>
to continuously send messages to <remotehost> until Ctrl-C
%(name)s server
to listen for messages until Ctrl-C
Uses port %(port)d. Once stopped, shows some statistics.
Creates udpstress-client.csv or udpstress-server.csv with
pairs (size,time)
"""
import os, sys
import socket
import time
PORT = 21758
BUFSIZE = 4096
socket.setdefaulttimeout(10.0)
def server(port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('',port))
print "Receiving at port %d" % (port)
history = []
print "Waiting for first packet to arrive...",
sock.recvfrom(BUFSIZE)
print "ok"
t0 = time.clock()
while 1:
try:
try:
data, remoteaddr = sock.recvfrom(BUFSIZE)
except socket.timeout:
print "Timed out"
break
except KeyboardInterrupt: # #1755388 #926423
raise
t1 = time.clock()
if not data:
break
history.append((len(data), t1-t0))
t0 = t1
except KeyboardInterrupt:
print "Stopped"
break
sock.close()
return history
def client(remotehost, port, data):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
history = []
print "Sending %d-bytes packets to %s:%d" % (len(data), remotehost,
port)
t0 = time.clock()
while 1:
try:
nbytes = sock.sendto(data, (remotehost,port))
t1 = time.clock()
if not nbytes:
break
history.append((nbytes, t1-t0))
t0 = t1
except KeyboardInterrupt:
print "Stopped"
break
sock.close()
return history
def show_stats(history, which):
npackets = len(history)
bytes_total = sum([item[0] for item in history])
bytes_avg = float(bytes_total) / npackets
bytes_max = max([item[0] for item in history])
time_total = sum([item[1] for item in history])
time_max = max([item[1] for item in history])
time_min = min([item[1] for item in history])
time_avg = float(time_total) / npackets
speed_max = max([item[0]/item[1] for item in history if item[1]>0])
speed_min = min([item[0]/item[1] for item in history if item[1]>0])
speed_avg = float(bytes_total) / time_total
print "Packet count %8d" % npackets
print "Total bytes %8d bytes" % bytes_total
print "Total time %8.1f secs" % time_total
print "Avg size / packet %8d bytes" % bytes_avg
print "Max size / packet %8d bytes" % bytes_max
print "Max time / packet %8.1f us" % (time_max*1e6)
print "Min time / packet %8.1f us" % (time_min*1e6)
print "Avg time / packet %8.1f us" % (time_avg*1e6)
print "Max speed %8.1f Kbytes/sec" % (speed_max/1024)
print "Min speed %8.1f Kbytes/sec" % (speed_min/1024)
print "Avg speed %8.1f Kbytes/sec" % (speed_avg/1024)
print
open("udpstress-%s.csv" % which,"w").writelines(
["%d,%f\n" % item for item in history])
if len(sys.argv)>1:
if "client".startswith(sys.argv[1].lower()):
remotehost = sys.argv[2]
data = sys.argv[3]
if data.isdigit(): # means length of message
data = "x" * int(data)
history = client(remotehost, PORT, data)
show_stats(history, "client")
sys.exit(0)
elif "server".startswith(sys.argv[1].lower()):
history = server(PORT)
show_stats(history, "server")
sys.exit(0)
print >>sys.stderr, __doc__ % {
"name": os.path.basename(sys.argv[0]),
"port": PORT}
</code>
Start the server before the client.
--
Gabriel Genellina
More information about the Python-list
mailing list