10

这是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()
4

3 回答 3

20

为每个连接生成一个新线程是一个非常糟糕的设计选择。如果你被很多连接击中会发生什么?

实际上,使用线程等待网络 IO 是不值得的。您的程序变得非常复杂,并且您绝对没有任何好处,因为在线程中等待网络不会让您等待得更快。在这种情况下,您只会因使用线程而失败。

以下文本来自 python 文档:

只有两种方法可以让单个处理器上的程序“一次做不止一件事”。多线程编程是最简单和最流行的方法,但还有另一种非常不同的技术,它让您几乎拥有多线程的所有优点,而无需实际使用多线程。只有当您的程序主要受 I/O 限制时,它才真正实用。如果您的程序受处理器限制,那么抢占式调度线程可能是您真正需要的。然而,网络服务器很少受处理器限制。

如果它是处理器绑定的服务器案例。你总是可以留下另一个进程/线程来做处理器部分。继续:

如果您的操作系统在其 I/O 库中支持 select 系统调用(几乎所有都支持),那么您可以使用它同时处理多个通信通道;当您的 I/O 在“后台”中进行时做其他工作。尽管这种策略可能看起来很奇怪和复杂,尤其是刚开始时,但它在许多方面都比多线程编程更容易理解和控制。

因此,不要使用线程,而是使用非阻塞输入/输出:收集列表中的套接字并使用带有select.select的事件循环来了解哪个套接字有要读取的数据。在单个线程中执行此操作。

你可以选择一个像twisted这样的 python 异步网络框架来为你做这件事。这将为您省去很多麻烦。Twisted 的代码多年来一直在改进,涵盖了一些您需要时间掌握的极端情况。

编辑:任何现有的异步 IO 库(如 Twisted)都是 python 代码。你本可以自己写的,但它已经为你写好了。我不明白为什么您不使用其中一个库并编写自己的最糟糕的代码,因为您是初学者。网络 IO 很难正确处理。

于 2009-01-28T11:19:49.437 回答
3

我不确定我是否理解这个问题,但close()如果您不想关闭连接,请不要打电话...

于 2009-01-28T11:08:09.147 回答
0

有关保持 TCP 连接打开并使用熟悉的协议的客户端示例,请查看telnetlib 模块源代码。(对不起,其他人将不得不回答您的线程问题。)

保持 TCP 连接打开的服务器示例位于SocketServer 模块的源代码中(任何标准 Python 安装都包括源代码)。

于 2009-01-28T11:20:54.427 回答