Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python套接字接收大量数据_Python_Sockets - Fatal编程技术网

Python套接字接收大量数据

Python套接字接收大量数据,python,sockets,Python,Sockets,当我尝试接收大量数据时,它会被切断,我必须按enter键才能获取其余数据。起初,我可以增加一点,但它仍然不会收到所有的。正如您所看到的,我增加了conn.recv()上的缓冲区,但它仍然无法获取所有数据。它会在某一点切断它。我必须在原始输入上按enter键才能接收其余数据。我是否可以一次获取所有数据?这是密码 port = 7777 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('0.0.0.0', por

当我尝试接收大量数据时,它会被切断,我必须按enter键才能获取其余数据。起初,我可以增加一点,但它仍然不会收到所有的。正如您所看到的,我增加了conn.recv()上的缓冲区,但它仍然无法获取所有数据。它会在某一点切断它。我必须在原始输入上按enter键才能接收其余数据。我是否可以一次获取所有数据?这是密码

port = 7777
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('0.0.0.0', port))
sock.listen(1)
print ("Listening on port: "+str(port))
while 1:
    conn, sock_addr = sock.accept()
    print "accepted connection from", sock_addr
    while 1:
        command = raw_input('shell> ')
        conn.send(command)
        data = conn.recv(8000)
        if not data: break
        print data,
    conn.close()

您可能需要多次调用conn.recv()以接收所有数据。由于TCP流不维护帧边界(即,它们仅作为原始字节流工作,而不是结构化消息流),因此单次调用它不能保证将发送的所有数据都带入

有关此问题的其他说明,请参阅

请注意,这意味着您需要知道何时收到所有数据。如果发送方总是准确地发送8000个字节,那么您可以计算到目前为止收到的字节数,然后从8000个字节中减去该字节数,以了解还有多少字节需要接收;如果数据大小可变,则可以使用多种其他方法,例如在发送消息之前让发送方发送多个字节的标题,或者如果发送的是ASCII文本,则可以查找换行符或NUL字符。

TCP/IP是基于流的协议,而不是基于消息的协议。无法保证一个对等方的每次
send()
调用都会导致另一个对等方的一次
recv()
调用,而另一个对等方接收到发送的确切数据时,可能会收到数据单,由于数据包碎片,会在多个
recv()
调用中分割

您需要在TCP之上定义自己的基于消息的协议,以便区分消息边界。然后,要读取消息,您可以继续调用
recv()
,直到您读取了整个消息或发生错误

发送消息的一种简单方法是在每条消息前面加上长度前缀。然后,要阅读一条消息,首先要读取长度,然后读取那么多字节。以下是您可以如何做到这一点:

def send_msg(sock, msg):
    # Prefix each message with a 4-byte length (network byte order)
    msg = struct.pack('>I', len(msg)) + msg
    sock.sendall(msg)

def recv_msg(sock):
    # Read message length and unpack it into an integer
    raw_msglen = recvall(sock, 4)
    if not raw_msglen:
        return None
    msglen = struct.unpack('>I', raw_msglen)[0]
    # Read the message data
    return recvall(sock, msglen)

def recvall(sock, n):
    # Helper function to recv n bytes or return None if EOF is hit
    data = bytearray()
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
            return None
        data.extend(packet)
    return data
def send_msg(sock,msg):
#以4字节长度(网络字节顺序)作为每条消息的前缀
msg=struct.pack('>I',len(msg))+msg
sock.sendall(msg)
def recv_msg(袜子):
#读取消息长度并将其解压为整数
原始格伦=recvall(短袜,4)
如果不是原始格伦:
一无所获
msglen=struct.unpack('>I',raw\msglen)[0]
#读取消息数据
返回记录(索克、格伦)
def recvall(短袜,n):
#Helper函数接收n个字节,如果命中EOF,则返回None
数据=字节数组()
而len(数据)

然后,您可以使用
send_msg
recv_msg
功能发送和接收整个消息,并且在网络级别拆分或合并数据包时不会出现任何问题。

您可以将其用作:
data=recvall(sock)

def recvall(sock):
BUFF_尺寸=4096#4千磅
数据=b''
尽管如此:
零件=袜子尺寸(抛光尺寸)
数据+=零件
如果透镜(零件)
修改Adam Rosenfield的代码:

import sys


def send_msg(sock, msg):
    size_of_package = sys.getsizeof(msg)
    package = str(size_of_package)+":"+ msg #Create our package size,":",message
    sock.sendall(package)

def recv_msg(sock):
    try:
        header = sock.recv(2)#Magic, small number to begin with.
        while ":" not in header:
            header += sock.recv(2) #Keep looping, picking up two bytes each time

        size_of_package, separator, message_fragment = header.partition(":")
        message = sock.recv(int(size_of_package))
        full_message = message_fragment + message
        return full_message

    except OverflowError:
        return "OverflowError."
    except:
        print "Unexpected error:", sys.exc_info()[0]
        raise

然而,我强烈鼓励使用原始方法。

< P>使用生成器函数的变化(我认为更多的Python):

def recvall(sock,buffer_size=4096):
buf=sock.recv(缓冲区大小)
而buf:
产量单位
如果len(buf)<缓冲区大小:中断
buf=sock.recv(缓冲区大小)
# ...
使用套接字。创建_连接((主机、端口))作为套接字:
sock.sendall(命令)
响应=b“”。加入(recvall(sock))

接受的答案很好,但对于大文件来说速度会非常慢-string是一个不可变的类这意味着每次使用
+
符号时都会创建更多的对象,使用
列表作为堆栈结构将更有效

这应该更有效

while True: 
    chunk = s.recv(10000)
    if not chunk: 
        break
    fragments.append(chunk)

print "".join(fragments)

您可以使用序列化来完成它

from socket import *
from json import dumps, loads

def recvall(conn):
    data = ""
    while True:
    try:
        data = conn.recv(1024)
        return json.loads(data)
    except ValueError:
        continue

def sendall(conn):
    conn.sendall(json.dumps(data))

注意:如果要使用上面的代码共享文件,则需要将其编码/解码为base64

大多数答案描述了某种
recvall()
方法。如果接收数据时的瓶颈是在
for
循环中创建字节数组,那么我在
recvall()
方法中测试了三种分配接收数据的方法:

arr = bytearray(msg_len)
pos = 0
while pos < msg_len:
    arr[pos:pos+max_msg_size] = sock.recv(max_msg_size)
    pos += max_msg_size
字节字符串方法:

arr = b''
while len(arr) < msg_len:
    arr += sock.recv(max_msg_size)
预分配
bytearray
方法:

arr = bytearray(msg_len)
pos = 0
while pos < msg_len:
    arr[pos:pos+max_msg_size] = sock.recv(max_msg_size)
    pos += max_msg_size
arr=bytearray(msg_len)
pos=0
当pos
结果:


适用于在您之前不知道数据包长度的情况下寻找答案的任何其他人。 这里有一个简单的解决方案,一次读取4096字节,当接收到的字节少于4096字节时停止。但是,如果接收到的数据包的总长度正好是4096字节,它将无法工作,然后它将再次调用
recv()
,并挂起

def recvall(sock):
    data = b''
    bufsize = 4096
    while True:
        packet = sock.recv(bufsize)
        data += packet
        if len(packet) < bufsize:
            break
    return data
def recvall(sock):
数据=b''
bufsize=4096
尽管如此:
packet=sock.recv(bufsize)
数据+=数据包
如果len(数据包)
我认为这个问题已经得到了很好的回答,但我只想添加一个使用Python 3.8和新赋值表达式(walrus运算符)的方法,因为它在风格上很简单

import socket

host = "127.0.0.1"
port = 31337
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen()
con, addr = s.accept()
msg_list = []

while (walrus_msg := con.recv(3)) != b'\r\n':
    msg_list.append(walrus_msg)

print(msg_list)
在这种情况下,从套接字接收3个字节,并立即分配给
walrus\u msg
。一旦套接字接收到
b'\r\n'
,它就会中断循环<代码>海象味精
被添加到
味精列表
中,并在循环中断后打印。这个脚本是基本的
def recvall(sock):
    data = b''
    bufsize = 4096
    while True:
        packet = sock.recv(bufsize)
        data += packet
        if len(packet) < bufsize:
            break
    return data
import socket

host = "127.0.0.1"
port = 31337
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen()
con, addr = s.accept()
msg_list = []

while (walrus_msg := con.recv(3)) != b'\r\n':
    msg_list.append(walrus_msg)

print(msg_list)
def recvall(sock):
    BUFF_SIZE = 4096
    data = bytearray()
    while True:
        packet = sock.recv(BUFF_SIZE)
        if not packet:  # Important!!
            break
        data.extend(packet)
    return data
jsonString = bytearray()

for _ in range(32):

    packet = clisocket.recv(1024)
    if not packet:
       break
    jsonString.extend(packet)