我编写了以下函数,用于我用于测试的套接字实用程序集合。 (使用Python 2.7.3,如果这很重要。)我将select
库拉入其中的主要原因是我可以实现超时而不是永远等待响应。我发现的问题是,尽管使用64K作为套接字上.recv()
方法的最大大小,但响应却被截断为2048个字符。在我参与select
之前没有发生这种截断。当我将最大尺寸设置得更高时,它会愉快地通过64K甚至更多。
我查看了select
上的一些在线资源,我发现有关此接收数据大小的明显上限的任何信息。即没有它存在的信息,更不用说如何修改它。有人能指出我克服这个2K限制的方法吗?
import socket,select MAXSIZE = 65535 TIMEOUT = 10 def transientConnect(host,port,sendData): error,response = False,'' try: sendSocket = socket.socket() sendSocket.connect((host,port)) sendSocket.send(sendData) gotData = select.select([sendSocket],[],[],TIMEOUT) if (gotData[0]): response = sendSocket.recv(MAXSIZE) else: error = True response = '*** TIMEOUT ***\nNo response from host.' sendSocket.close() except Exception, errText: error,response = True,'*** SOCKET ERROR ***\n'+str(errText) return (error,response)
答案 0 :(得分:3)
TCP套接字为您提供双向字节流,但在较低级别,它通过基于数据包的协议(IP)实现。这意味着您可以在每次读取时接收流的任意块(尽管这些字节都按顺序排列),具体取决于TCP / IP堆栈如何决定拆分流以进行传输。
这里的关键点是你必须在循环中执行recv()
,直到你得到完整的“应用程序消息”。引用Socket Programming HOWTO:
现在我们来到套接字的主要障碍 -send
和recv
对网络缓冲区进行操作。它们不一定处理你所处理的所有字节(或期望它们),因为它们主要关注的是处理网络缓冲区。通常,它们在关联的网络缓冲区已填充(发送)或清空(recv)时返回。然后他们告诉你他们处理了多少字节。 你的责任再次打电话给你,直到你的信息被完全处理完毕。
您在此处看到的是,只要某些数据可用,select
就会提前通知您。
希望这有帮助。
答案 1 :(得分:1)
经过纠正,测试和运作的功能:
MAXSIZE = 65535 TIMEOUT = 10 def transientConnect(host,port,sendData): error,response = False,'' try: sendSocket = socket.socket() sendSocket.connect((host,port)) sendSocket.send(sendData) gotData = select.select([sendSocket],[],[],TIMEOUT) if (gotData[0]): response = sendSocket.recv(MAXSIZE) while True: #Once data starts arriving, use a shorter timeout gotData2 = select.select([sendSocket],[],[],0.5) if (gotData2[0]): moreData = sendSocket.recv(MAXSIZE) response += moreData else:break else: error = True response = '*** TIMEOUT ***\nNo response from host.' sendSocket.close() except Exception, errText: error,response = True,'*** SOCKET ERROR ***\n'+str(errText) return (error,response)