Python - 如何让客户端能够连接多次?

时间:2014-04-14 00:11:33

标签: python linux sockets python-2.7 ubuntu

当我使用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()

2 个答案:

答案 0 :(得分:2)

你的HTTPClient的连接方法是阻塞的,如果你的第二个主机没有连接,你的try / except块在超时后就会激动。你的except块没有关闭套接字,所以acynscore.loop()仍在等待它。

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

答案 1 :(得分:1)

您的代码中可能存在多个问题,例如,在指定目标时删除括号: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)