【问题标题】:Python - how can i make the client to be able to connect multiple times?Python - 我怎样才能让客户端能够连接多次?
【发布时间】:2014-05-27 19:39:31
【问题描述】:

只有当我使用 client1 = HTTPClient('192.168.1.2', '3') 时它才有效,但当我同时使用以下两种时: client1 = HTTPClient('192.168.1.2', '3') client2 = HTTPClient('192.168.1.3', '3')

然后整个事情变得非常缓慢,有时其中一个会失败。如何确保client1和client2连接+发送+足够快?

import asyncore, socket

class HTTPClient(asyncore.dispatcher):

  def __init__(self, host, path):
    asyncore.dispatcher.__init__(self)
    self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
    self.settimeout(10)
    try:
      self.connect( (host, 8888) )
    except:
      print 'unable to connect'
      pass
    self.buffer = path

  def handle_connect(self):
    pass

  def handle_close(self):
    self.close()

  def handle_read(self):
    print self.recv(8192)

  def writable(self):
    return (len(self.buffer) > 0)

  def handle_write(self):
    sent = self.send(self.buffer)
    self.buffer = self.buffer[sent:]


client1 = HTTPClient('192.168.1.2', '3')
client2 = HTTPClient('192.168.1.3', '3')
asyncore.loop()

编辑:也尝试了线程,但结果相同

import asyncore, socket
import threading
import os

class HTTPClient(asyncore.dispatcher):

  def __init__(self, host, path):
    asyncore.dispatcher.__init__(self)
    self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
    self.settimeout(10)
    try:
      self.connect( (host, 8888) )
    except:
      print 'unable to connect'
      pass
    self.buffer = path

  def handle_connect(self):
    pass

  def handle_close(self):
    self.close()

  def handle_read(self):
    print self.recv(8192)

  def writable(self):
    return (len(self.buffer) > 0)

  def handle_write(self):
    sent = self.send(self.buffer)
    self.buffer = self.buffer[sent:]

def t1():
  client1 = HTTPClient('192.168.1.161', '3')  

def t2():
  client2 = HTTPClient('192.168.1.163', '3')

t0 = threading.Thread(target=t1())
t0.start()
t0.join() 

t0 = threading.Thread(target=t2())
t0.start()
t0.join() 

asyncore.loop()

【问题讨论】:

  • 您能否更详细地描述“变得非常缓慢,有时其中一个失败”的意思?它以什么方式失败?
  • 当您仅使用 client1 进行连接时,它可以完美运行。但是当您使用客户端 1 和客户端 2 连接时,它需要比正常超时时间更长的时间,因此连接失败并且与单次连接相比,总行程变得异常。
  • 不应该是t0t1,和t0.start()t1.start()然后才加入吗?现在,您一个接一个地启动线程,而不是同时启动。
  • YES - 更改 t0 和 t1 是错字。但仍然存在同样的问题,就像没有线程一样。还有更多想法!
  • 对于连接呢?现在它看起来像“启动线程 1”,等待它停止“,启动线程 2”,“等待它停止”。如果你不等第一个停止再启动第二个,它就没有机会跑得更快。

标签: python linux sockets python-2.7 ubuntu


【解决方案1】:

您的 HTTPClient 的连接方法正在阻塞,如果您的第二个主机不排除连接,则您的 try/except 块在超时后会令人兴奋。您的 except 块没有关闭套接字,因此 acyncore.loop() 仍在等待它。

在下面尝试我的修改,看看他们是否确认了问题。我在 connect 方法周围放置了一些打印语句来说明代码的阻塞部分,并且我已经明确地关闭了异常中的套接字。如果您可以发布服务器代码也会很有帮助,因为我预计问题就在那里。如果服务器代码不在您的控制范围内,您的代码会将您的时间缩短到更小,并打开某种循环的连接,但您应该在每次迭代时退出连接尝试(等待 1 秒,然后 2 秒,然后 4 秒,然后 8 秒,等连接尝试之间)。

import asyncore, socket
import time

class HTTPClient(asyncore.dispatcher):

  def __init__(self, host, path):
    asyncore.dispatcher.__init__(self)
    self.HOST = host
    self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
    self.settimeout(10)
    try:
      t0 = time.time()
      print "connecting to host:", host, '...blocking...'
      self.connect( (host, 80) )
      print "connected to host (%s) in %0.2f seconds:"%(host, time.time()-t0)
    except:
      print 'unable to connect'
      self.close()
    self.buffer = path

  def handle_connect(self):
    pass

  def handle_close(self):
    self.close()

  def handle_read(self):
    print self.recv(8192)

  def writable(self):
    return (len(self.buffer) > 0)

  def handle_write(self):
    sent = self.send(self.buffer)
    self.buffer = self.buffer[sent:]


client1 = HTTPClient('news.google.com', 'GET / HTTP/1.0\r\n\r\n')
client2 = HTTPClient('not_a_valid_server.local', 'GET / HTTP/1.0\r\n\r\n')
client3 = HTTPClient('news.yahoo.com', 'GET / HTTP/1.0\r\n\r\n')
asyncore.loop()

【讨论】:

    【解决方案2】:

    您的代码中可能存在多个问题,例如,在指定目标时删除括号:Thread(target=t1)。如果f 是一个函数,那么f() 会立即调用它。您还将asyncore 与阻塞代码和多线程混合在一起。

    如果你想同时建立几个http连接;您可以改用线程池:

    import urllib2
    from multiprocessing.dummy import Pool # use threads
    
    def fetch(url):
        try:
            return url, urllib2.urlopen(url).read(), None
        except Exception as e:
            return url, None, str(e)
    
    urls = ['http://example.com', ...]
    pool = Pool(20) # use no more than 20 concurrent connections
    for url, result, error in pool.imap_unordered(fetch, urls):
        if error is None:
           print(url + " done")
        else:
           print(url + " error: " + error)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-28
      • 2021-05-29
      • 1970-01-01
      相关资源
      最近更新 更多