Anubhav Yadav
2015-05-11 20:07:03 UTC
I am very new to python. I have been a very mediocre programmer, but now I
have decided that I want to level up as a programmer.
I wanted to write a simple TCP client/server (where in the server acts as a
simple TCP Listener). I searched on the forums and I saw that people
advised using frameworks like twisted and sync.io for client server
applications to take advantage of asynchronous model. But since I couldn't
visualize the problems that people faced when they implemented servers as
multithreaded model, so I decided to start by implementing a multithreaded
server, and then improve as I go on facing issues.
So I started with using socket library for both client and server:
Here is my listener.py:
import socket
import threading
from time import sleep
class Serve(threading.Thread):
def __init__(self, client_socket, client_address):
threading.Thread.__init__(self)
self.socket = client_socket
self.address, self.port = client_address
def run(self):
try:
while True:
data = self.socket.recv(300)
if data:
print data
sleep(2)
else:
break
except Exception as e:
print e
finally:
self.socket.close()
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 5555))
sock.listen(1)
servers = []
while True:
connection, client_address = sock.accept()
print "New Connection from {}".format(client_address)
server = Serve(connection, client_address)
servers.append(server)
server.start()
for server in servers:
server.join()
Here is my sender.py. It is supposed to simulate clients connecting to the
server.
import argparse
import socket
import threading
from time import sleep
parser = argparse.ArgumentParser(description="A simple TCP sender")
parser.add_argument('-H', '--host', help='host to connect to',
default='localhost')
parser.add_argument('-p', '--port', help='port of the host', type=int,
default=5555)
parser.add_argument('-w', '--workers', help='number of threads to
create', default=1000, type=int)
args = parser.parse_args()
count = args.workers
def send(id):
lock = threading.Lock()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (args.host, args.port)
try:
sock.connect(server_address)
while True:
sock.sendall('@ABCDEF1234567890FABC#')
sleep(1)
except Exception as e:
print "thread no {} killed".format(id)
print e
lock.acquire()
count-=1
lock.release()
sleep(1)
print "Total threads are {}".format(count)
finally:
sock.close()
threads = []
if __name__ == '__main__':
for i in range(args.workers):
t = threading.Thread(target=send, args=(i,))
threads.append(t)
t.start()
for thread in threads:
thread.join()
When I run the client and server together with 1000 clients, many threads
are killed on a machine with low memory, and only 210-220 clients are
connected with the server. The killed clients gave the following error:
`[Errno 104] Connection reset by peer`
Right now I am not on the low memory machine, but I remember the error also
had "broken pipe" in it.
So I decided to run the same code with 1000 clients on my laptop with 8 GB
memory. This time almost all clients where connected but one or two clients
got killed with the same above error (I could not see broken error in the
messages this time".
Then I ran the same code with 500 clients, and this is where the code broke
with the following errors.
Exception in thread Thread-4999:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
File "/usr/lib/python2.7/threading.py", line 763, in run
File "sender.py", line 17, in send
File "/usr/lib/python2.7/socket.py", line 187, in __init__
error: [Errno 24] Too many open files
Total threads are 4998
These errors came a lot, but the count said that only two threads failed. I
think my logic to calculate the count is wrong.
Then I decided to use SocketServer for the server. Here is the new Server:
import SocketServer
from threading import Thread
from time import sleep
class service(SocketServer.BaseRequestHandler):
def handle(self):
print "Client connected with ", self.client_address
while True:
try:
data = self.request.recv(300)
if data:
print data
sleep(2)
else:
print "Client exited"
self.request.close()
except Exception as e:
print e
class ThreadedTCPServer(SocketServer.ThreadingMixIn,
SocketServer.TCPServer):
pass
t = ThreadedTCPServer(('localhost',5555), service)
t.serve_forever()
I have used the same client. This time there is some durability when there
are 1000 clients, but if I disconnect the sender (send a `kill -KILL pid`
signal) the listener breaks with the following error
`[Errno 9] Bad file descriptor`
Now if I run the sender with 5000 clients, the errors are back.
Exception in thread Thread-4999:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
File "/usr/lib/python2.7/threading.py", line 763, in run
File "sender.py", line 17, in send
File "/usr/lib/python2.7/socket.py", line 187, in __init__
error: [Errno 24] Too many open files
I don't even know if this is the right way of writing the servers, I also
know that possibly there is something wrong with my code, and maybe I am
not doing things as they are meant to be done.
Is it even right to create many thousands clients using threads on the same
machine? Is that what is causing problems? Should I learn some library like
twisted or zmq?
Would love to understand the details of threading and sockets! Please do
leave your comments and criticize me. Sorry for this long post.
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
have decided that I want to level up as a programmer.
I wanted to write a simple TCP client/server (where in the server acts as a
simple TCP Listener). I searched on the forums and I saw that people
advised using frameworks like twisted and sync.io for client server
applications to take advantage of asynchronous model. But since I couldn't
visualize the problems that people faced when they implemented servers as
multithreaded model, so I decided to start by implementing a multithreaded
server, and then improve as I go on facing issues.
So I started with using socket library for both client and server:
Here is my listener.py:
import socket
import threading
from time import sleep
class Serve(threading.Thread):
def __init__(self, client_socket, client_address):
threading.Thread.__init__(self)
self.socket = client_socket
self.address, self.port = client_address
def run(self):
try:
while True:
data = self.socket.recv(300)
if data:
print data
sleep(2)
else:
break
except Exception as e:
print e
finally:
self.socket.close()
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 5555))
sock.listen(1)
servers = []
while True:
connection, client_address = sock.accept()
print "New Connection from {}".format(client_address)
server = Serve(connection, client_address)
servers.append(server)
server.start()
for server in servers:
server.join()
Here is my sender.py. It is supposed to simulate clients connecting to the
server.
import argparse
import socket
import threading
from time import sleep
parser = argparse.ArgumentParser(description="A simple TCP sender")
parser.add_argument('-H', '--host', help='host to connect to',
default='localhost')
parser.add_argument('-p', '--port', help='port of the host', type=int,
default=5555)
parser.add_argument('-w', '--workers', help='number of threads to
create', default=1000, type=int)
args = parser.parse_args()
count = args.workers
def send(id):
lock = threading.Lock()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (args.host, args.port)
try:
sock.connect(server_address)
while True:
sock.sendall('@ABCDEF1234567890FABC#')
sleep(1)
except Exception as e:
print "thread no {} killed".format(id)
print e
lock.acquire()
count-=1
lock.release()
sleep(1)
print "Total threads are {}".format(count)
finally:
sock.close()
threads = []
if __name__ == '__main__':
for i in range(args.workers):
t = threading.Thread(target=send, args=(i,))
threads.append(t)
t.start()
for thread in threads:
thread.join()
When I run the client and server together with 1000 clients, many threads
are killed on a machine with low memory, and only 210-220 clients are
connected with the server. The killed clients gave the following error:
`[Errno 104] Connection reset by peer`
Right now I am not on the low memory machine, but I remember the error also
had "broken pipe" in it.
So I decided to run the same code with 1000 clients on my laptop with 8 GB
memory. This time almost all clients where connected but one or two clients
got killed with the same above error (I could not see broken error in the
messages this time".
Then I ran the same code with 500 clients, and this is where the code broke
with the following errors.
Exception in thread Thread-4999:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
File "/usr/lib/python2.7/threading.py", line 763, in run
File "sender.py", line 17, in send
File "/usr/lib/python2.7/socket.py", line 187, in __init__
error: [Errno 24] Too many open files
Total threads are 4998
These errors came a lot, but the count said that only two threads failed. I
think my logic to calculate the count is wrong.
Then I decided to use SocketServer for the server. Here is the new Server:
import SocketServer
from threading import Thread
from time import sleep
class service(SocketServer.BaseRequestHandler):
def handle(self):
print "Client connected with ", self.client_address
while True:
try:
data = self.request.recv(300)
if data:
print data
sleep(2)
else:
print "Client exited"
self.request.close()
except Exception as e:
print e
class ThreadedTCPServer(SocketServer.ThreadingMixIn,
SocketServer.TCPServer):
pass
t = ThreadedTCPServer(('localhost',5555), service)
t.serve_forever()
I have used the same client. This time there is some durability when there
are 1000 clients, but if I disconnect the sender (send a `kill -KILL pid`
signal) the listener breaks with the following error
`[Errno 9] Bad file descriptor`
Now if I run the sender with 5000 clients, the errors are back.
Exception in thread Thread-4999:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
File "/usr/lib/python2.7/threading.py", line 763, in run
File "sender.py", line 17, in send
File "/usr/lib/python2.7/socket.py", line 187, in __init__
error: [Errno 24] Too many open files
I don't even know if this is the right way of writing the servers, I also
know that possibly there is something wrong with my code, and maybe I am
not doing things as they are meant to be done.
Is it even right to create many thousands clients using threads on the same
machine? Is that what is causing problems? Should I learn some library like
twisted or zmq?
Would love to understand the details of threading and sockets! Please do
leave your comments and criticize me. Sorry for this long post.
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor