Найти - Пользователи
Полная версия: Создание сервера с неограниченым числом подключений
Начало » Network » Создание сервера с неограниченым числом подключений
1 2 3 4 5
CryptSpirit
Вот написал пример в котором ждет себе программа когда кто то к сокету конектится. Еслиесть конект то милости просим в отдельный поток. Проблема по сабжу что потоков явно для неорганиченого числа подключений не хватает. Вопрос что делать? Давать на трэд по несколько конектов обслуживать? Заранее спасиб.
Ed
Насчет неограниченного числа подключений вы явно погорячились, но используя треды, а если их будет мало, то gevent, это число можно серьезно увеличить.

Читать здесь:
http://docs.python.org/library/asyncore.html
http://docs.python.org/library/socketserver.html?highlight=tcp%20server
http://www.gevent.org/intro.html
CryptSpirit
Потоки как мне кажется это реальный выход. Но это попахивает идиотизмом создавать такое количество потоков. Будем копать.
Ed
Вот здесь http://pycon.blip.tv/file/3359630/ автор greenlet утверждает, что ему удалось создать около 1000 тредов, после чего ОС сказала ‘Извини, но я больше не буду делать тебе треды’ :)
Кстати, рекомендую посмотреть видео целиком. Очень интересно и как раз в тему.
В частности он упоминает еще одну возможность - неблокирующий ввод/вывод. Если вам так противны треды, то можете попробовать этот подход.
Андрей Светлов
Сначала изучаем неблокирующие сокеты и select.select.
Потом, поэкспериментировав на кроликах и проникшись идеей, выбираем между более оптимальными реализациями.
CryptSpirit
Ed, как не странно но то же самое удалось и у меня. Это где то 1020 тредов. Видео не позволяет посмотреть мой мобильный диал-ап. Я так понял что асинхронизация + нагрузка на один тред определенного числа конектов и можно заполнять анкету в книгу рекордов. Просьба делать ссылки на хотя бы обрывки кода.

ладно оцените мой “почерк”

Сервер

#!/usr/bin/python
import socket,time,threading
HOST = 'localhost'
PORT = 5000
class OnConnect(threading.Thread):
def __init__(self,conn,addr,indexx):
threading.Thread.__init__(self)
self.conn=conn
self.addr=addr
self.indexx=indexx
self.start()
def run(self):
while 1:
try: data = self.conn.recv(1024)
except:
break
else:
if (not data) : break
self.conn.send(data)
time.sleep(0.1)
self.conn.close()
print self.indexx,'-',self.addr[0],':',self.addr[1],'(',time.asctime(time.gmtime(time.time())),')'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
print 'Run in',time.asctime(time.gmtime(time.time()))
print 'Host: ',HOST
print 'port: ',PORT
s.listen(1)
d=0
threading.stack_size(0x100000)
while 1:
conn, addr = s.accept()
d=d+1
print d,'+',addr[0],':',addr[1],'(',time.asctime(time.gmtime(time.time())),')'
OnConnect(conn,addr,d)
time.sleep(0.1)
conn.close()
клиент для краш теста

import socket,threading,time
class TestServ(threading.Thread):
def __init__(self,s):
threading.Thread.__init__(self)
self.s=s
self.start()
def run(self):
for i in range(1000):
self.s.send('x')
data=self.s.recv(1024)
time.sleep(1)
self.s.send('exit')
self.s.close()
port=5000
threading.stack_size(0x100000)
for i in range(10000):
print i
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('localhost',port))
TestServ(s)
time.sleep(0.1)
Не пинать я с апреля на питоне
regall
Посмотрите в код фреймворка/сервера Tornado и почитайте о проблеме 10k - http://www.kegel.com/c10k.html. Также познавательным будет знакомство с сервером YAWS - http://yaws.hyber.org.

Андрей Светлов
Потом, поэкспериментировав на кроликах и проникшись идеей
Давайте все-таки на кошках =)
Ed
CryptSpirit
Ed, как не странно но то же самое удалось и у меня. Это где то 1020 тредов.
Странно. А это точно про треды. потому что 1021 это очень похоже на ограничение по файловым дескрипторам.
У меня, например оно 1024. Минус 3 стандартных (stdin, stdout, stderr) получаем 1021.
Попробуйте увеличить количество открытых файлов для процесса.
Но вообще при невозможности создать тред должен получиться Exception такого вида:
Traceback (most recent call last):
File "./server.py", line 55, in <module>
thread.start()
File "/usr/lib/python2.6/threading.py", line 474, in start
_start_new_thread(self.__bootstrap, ())
thread.error: can't start new thread
У меня это происходит при попытке создания треда номер 380.

ладно оцените мой “почерк”

Не пинать я с апреля на питоне
Как же тогда оценивать :) ?
Ed
CryptSpirit
Просьба делать ссылки на хотя бы обрывки кода.
Вот, что у меня получилось используя eventlet monkey_patch. Это по сути аналог вашего сервера - уберите вызов monkey_patch - получите полный аналог.
import eventlet
eventlet.monkey_patch()

import sys
from threading import Thread
import socket

HOST, PORT = 'localhost', 5000

def handle(index, addr, conn):
while True:
data = conn.recv(1024)
if not data:
break
conn.send(data)
print 'client %i disconnected' % index

if __name__ == '__main__':

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)

print 'Server is waiting for connections on %s:%d' % (HOST, PORT)

index = 0
while True:
index += 1
conn, addr = sock.accept()
print "client connected from %s:%s. Creating thread %d" % (addr[0], addr[1], index)
thread = Thread(target=handle, args=(index, addr, conn))
thread.start()
Сломался клиент на создании треда 2993:
2993
Traceback (most recent call last):
File “./client.py”, line 25, in <module>
TestServ(s)
File “./client.py”, line 11, in __init__
self.start()
File “/usr/lib/python2.6/threading.py”, line 474, in start
_start_new_thread(self.__bootstrap, ())
thread.error: can't start new thread

Если его также пропатчить, то думаю будет гораздо больше.

PS: Да, я сделал еще ulimit -n 10000 предварительно. Иначе отваливалось по ‘too many open files’
o7412369815963
можно попробоват ьиспользовать селект
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB