Клиент-серверное программирование на python? - PullRequest
10 голосов
/ 28 января 2009

Вот исходный код многопоточного сервера и клиента на python.

В коде клиент и сервер закрывают соединение после завершения задания. Я хочу, чтобы соединения были активными, и отправлять больше данных по тем же соединениям на , чтобы избежать накладных расходов на закрытие и открытие сокетов каждый раз .

Следующий код от: http://www.devshed.com/c/a/Python/Basic-Threading-in-Python/1/

import pickle
import socket
import threading

# We'll pickle a list of numbers:
someList = [ 1, 2, 7, 9, 0 ]
pickledList = pickle.dumps ( someList )

# Our thread class:
class ClientThread ( threading.Thread ):

   # Override Thread's __init__ method to accept the parameters needed:
   def __init__ ( self, channel, details ):

      self.channel = channel
      self.details = details
      threading.Thread.__init__ ( self )

   def run ( self ):

      print 'Received connection:', self.details [ 0 ]
      self.channel.send ( pickledList )
      for x in xrange ( 10 ):
         print self.channel.recv ( 1024 )
      self.channel.close()
      print 'Closed connection:', self.details [ 0 ]

# Set up the server:
server = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
server.bind ( ( '', 2727 ) )
server.listen ( 5 )

# Have the server serve "forever":
while True:
   channel, details = server.accept()
   ClientThread ( channel, details ).start()

import pickle
import socket
import threading

# Here's our thread:
class ConnectionThread ( threading.Thread ):

   def run ( self ):

      # Connect to the server:
      client = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
      client.connect ( ( 'localhost', 2727 ) )

      # Retrieve and unpickle the list object:
      print pickle.loads ( client.recv ( 1024 ) )

      # Send some messages:
      for x in xrange ( 10 ):
         client.send ( 'Hey. ' + str ( x ) + '\n' )

      # Close the connection
      client.close()

# Let's spawn a few threads:
for x in xrange ( 5 ):
   ConnectionThread().start()

Ответы [ 3 ]

20 голосов
/ 28 января 2009

Создание нового потока для каждого соединения - очень плохой выбор дизайна. Что произойдет, если вы столкнетесь с большим количеством соединений?

На самом деле, использование потоков для ожидания сетевого ввода-вывода не стоит. Ваша программа становится действительно сложной, и вы получаете никакой выгоды , поскольку ожидание сети в потоках не заставит вас ждать быстрее . В этом случае вы проигрываете только с помощью потоков.

Следующий текст взят из документации по Python:

Есть только два способа программа на одном процессоре делает «больше чем одна вещь за один раз. " Многопоточное программирование является Самый простой и самый популярный способ сделать это, но есть еще один очень другая техника, которая позволяет вам имеют почти все преимущества многопоточность, без собственно используя несколько потоков. Это правда только практично, если ваша программа во многом связан с вводом / выводом. Если ваша программа связанный с процессором, затем упреждающий запланированные темы, вероятно, что тебе действительно нужно. Сетевые серверы однако редко привязывается к процессору.

И если это привязанный к процессору серверный корпус. Вы всегда можете оставить другой процесс / поток для выполнения части процессора. Продолжение:

Если ваша операционная система поддерживает выберите системный вызов в своей библиотеке ввода-вывода (и почти все делают), то вы можете использовать это жонглировать множественным общением каналы сразу; делать другую работу в то время как ваш ввод / вывод происходит в «Фон». Хотя эта стратегия может показаться странным и сложным, особенно во-первых, это во многих способы легче понять и контролировать чем многопоточное программирование.

Поэтому вместо использования потоков используйте неблокирующий ввод / вывод: соберите сокеты в списке и используйте цикл обработки событий с select.select , чтобы узнать, в каком сокете есть данные для чтения. Сделайте это в один поток.

Для этого вы можете выбрать среду асинхронной сети Python, такую ​​как twisted . Это избавит вас от многих головных болей. Код Twisted совершенствовался годами и охватывает некоторые угловые случаи, которые вы потратите на освоение.

EDIT : любые существующие библиотеки асинхронного ввода-вывода (например, Twisted) представляют собой код Python. Вы могли бы написать это сами, но это уже было написано для вас. Я не понимаю, почему бы вам не использовать одну из этих библиотек и не написать вместо этого свой собственный худший код, поскольку вы новичок. Сетевой ввод-вывод трудно понять правильно.

3 голосов
/ 28 января 2009

Я не уверен, что понимаю вопрос, но не звоните close(), если не хотите закрывать соединение ...

0 голосов
/ 28 января 2009

Например, клиент сохраняет TCP-соединение открытым и использует знакомый протокол, посмотрите на источник модуля telnetlib . (извините, кто-то еще должен будет ответить на ваши вопросы.)

Пример сервера, который держит TCP-соединение открытым, находится в источнике для модуля SocketServer (любой стандартная установка Python включает источник).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...