我使用PyQt、QThreads和couchdb-python与本地局域网上的couchDB实例通信。
为了测试在网络速度慢的情况下多线程是否会工作,我在GUI和沙发之间放置了一个代理。
联网已记录。日志以如下开头
13:52:46.303 (1) send: HEAD /cubic HTTP/1.1CRLFHost: localhost:5981CRLFContent-Length: 0CRLFAccept: application/jsonCRLFUser-Agent: CouchDB-Python/0.8CRLFCRLF
13:52:46.308 (1) recv: HTTP/1.1 200 OKCRLFServer: CouchDB/1.0.1 (Erlang OTP/R13B)CRLFDate: Mon, 21 Feb 2011 13:47:18 GMTCRLFContent-Type: application/jsonCRLFContent-Length: 219CRLFCache-Control: must-revalidateCRLFCRLF
13:53:16.312 (1) recv: link closed
13:53:16.319 (2) send: GET /cubic/_design/Company/_view/by_name HTTP/1.1CRLFHost: localhost:5981CRLFContent-Length: 0CRLFAccept: application/jsonCRLFUser-Agent: CouchDB-Python/0.8CRLFCRLF
13:53:16.330 (2) recv: HTTP/1.1 200 OKCRLFTransfer-Encoding: chunkedCRLFServer: CouchDB/1.0.1 (Erlang OTP/R13B)CRLFEtag: "243QGZGN1ETGA4VN9H1OMB86Z"CRLFDate: Mon, 21 Feb 2011 13:47:48 GMTCRLFContent-Type: application/jsonCRLFCache-Control: must-revalidateCRLFCRLF
13:53:16.331 (2) recv: a0CRLF{"total_rows":9,"offset":0,"rows":[CRLF{"id":"c182c1a2f71c3547ccee45556300770e","key":["A first Company","231","345 East of Eden" ,"Manchester",null],"value":null}CRLF
13:53:16.332 (2) recv: 77CRLF,CRLF{"id":"c182c1a2f71c3547ccee455563001254","key":["C-U-B","1","9-11 March Business Centre","March",null],"value":null}CRLF72CRLF,CRLF{"id":"421261e8a3311c356c4900185800d976","key":"Four","104","4 Fourth street","Four Score",null],"value":null}CRLF74CRLF,CRLF{"id":"c182c1a2f71c3547ccee455563003de8","key":["Fred Smith","431","30 High street","Somehow",null],"value":null}CRLF
13:53:16.334 (2) recv: 83CRLF,CRLF{"id":"7bc7f2014593d108b5b681fe03002ad6","key":["Ian Hobson","1002","31 Sheerwater Dr","Northampton, Nhants",null],"value":null}CRLF76CRLF,CRLF{"id":"c182c1a2f71c3547ccee455563003139","key":["Julie Bloggs","302","30 Back Lane","Somewhere",null],"value":null}CRLF7cCRLF,CRLF{"id":"c182c1a2f71c3547ccee455563002e87","key": "Kingfisher Group","323","33 Westmister Rd","Londonx",null],"value":null}CRLF
13:53:16.335 (2) recv: 7aCRLF,CRLF{"id":"c182c1a2f71c3547ccee455563005894","key":["New Company","212","34 Back Street","Another Town",null],"value":null}CRLF72CRLF,CRLF{"id":"421261e8a3311c356c4900185800d7e2","key":["Three","103","3 High Street","Liverpool 8",null],"value":null}CRLF4CRLFCRLF]}CRLF1CRLFLFCRLF0CRLFCRLF
13:53:46.337 (2) recv: link closed除了在13:52:46.308打开数据库后有30秒的延迟,而recv链接超时之外,这与预期完全一样。直到发生这种情况,代码才能打开发生在13:53:16.319的视图
但是,代理正在使用不同的线程{(2)而不是(1)}。应用程序部分在没有代理的情况下工作得很好,所以我怀疑是代理。
代理代码基于微代理,如下所示
import re, sys, datetime
import socket
import threading
PORT = 5981
class ConnectionThread(threading.Thread):
def __init__(self, (conn,addr),id):
self.conn = conn
self.addr = addr
self.id = id
threading.Thread.__init__(self)
def report(self,data,dir):
txt = data.replace("\n",'LF')
txt = txt.replace("\r",'CR')
now = datetime.datetime.now()
print "%s (%s) %s: %s" % (now.isoformat()[11:23],self.id,dir,txt)
def run(self):
data = self.conn.recv(1024*1024)
request = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
request.connect(('192.168.0.1',5984))
self.report(data,'send')
request.send(data)
while True:
temp = request.recv(1024)
if ('' == temp):
self.report('link closed','recv')
break
self.report(temp,'recv')
self.conn.send(temp)
self.conn.close()
class ProxyThread(threading.Thread):
def __init__(self, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind(('localhost', port))
self.count = 1
threading.Thread.__init__(self)
def run(self):
self.sock.listen(3)
while True:
temp = ConnectionThread(self.sock.accept(),self.count)
temp.start() # each message handled in own thread
self.count += 1
if __name__ == "__main__":
print "Starting a proxy on port", PORT
proxy = ProxyThread(PORT)
proxy.run() 打开数据库的请求和视图的请求都是在同一个(非GUI)线程中发出的。为什么会出现延迟?
我怎样才能改变事情,让它不再发生呢?
发布于 2011-02-22 02:01:07
您的循环仅从被代理的连接的一端读取。因此,当应答从服务器转发到客户端时,当客户端断开连接时,代码不会注意到客户端断开连接,而是一直等待服务器回复或断开连接。
为了解决这个问题,它需要同时从服务器(请求)和客户端(self.conn)套接字读取数据。要做到这一点,最简单的方法是使用非阻塞套接字。
发布于 2011-02-22 01:33:56
HTTP spec声明(第9.4节)
HEAD方法与GET相同,只是服务器不能在响应中返回消息体。
这意味着CRLFCRLF之后没有任何内容,但您的代理正在等待数据,而不是从传入的连接中读取数据。我怀疑couchdb库正在尝试使用保持活动的连接,但是您查看的套接字是错误的。
你的基本问题是,你声称与HTTP1.1对话,但你没有,你应该注意一个CRLFCRLF序列,一个content-size头。如果你发现有一个读取了那么多数据,那么就中断循环,如果没有一个,就立即中断。
https://stackoverflow.com/questions/5067636
复制相似问题