打包TCP流

时间:2018-11-23 18:42:23

标签: python tcp udp

在我的程序中,我具有以下架构:

客户端-中间路由器-服务器

客户端和路由器通过TCP连接连接。路由器和服务器具有UDP连接。 我正在这样发送数据:

messagetobesend = "some very long message to be send"
sock = socket(AF_INET,SOCK_STREAM)
# bind my port to the socket
sock.bind((IP,PORT))
sock.connect((routerip, routerport))

# since I'm using TCP, send the data byte by byte
for i in range(len(messagetobesend)):
     sock.send(messagetobesend[i])

# now, I have send all of the message
sock.close()

在路由器中,我有以下内容:

sock = socket(AF_INET,SOCK_STREAM)
sock.bind((ip, port))
sock.listen(1)
# I have accepted the TCP connection
newsocket, addr = sock.accept()

# now create a UDP socket
udpsock = socket(AF_INET,SOCK_DGRAM)
udpsock.bind((myudpip, myudpport))

while True:
    # I want to packetize the data with 128 bytes
    data = newsocket.recv(128)
    if(data):
        data.sendto(udpsock,(serverip,serverport))
    else:
        #received no data, terminate udp connection
        udpsock.close()

newsocket.close()

和服务器:

sock = socket(AF_INET,SOCK_DGRAM)
sock.bind((myip, myport))
while True:

    data, addr = sock.recvfrom(128)
    #print data

我所做的一切似乎都是正确的。但是,服务器通常接收128字节的数据包,有时接收大多数128字节的数据包,有些不接收128字节的数据。

我在这里做错什么了吗?我希望服务器接收所有这些长度为128字节的数据包(所有接收到的数据包长度应相同)

1 个答案:

答案 0 :(得分:1)

您的recv调用返回最多 128个字节。如果您需要精确接收128个字节,则应编写自己的recv_exactly

PACKET_LEN = 128

# ...

def recv_exactly(socket, length):
    buf = bytearray()
    bytes_left = length

    while bytes_left: # equivalent to while bytes_left != 0:  
        data = socket.recv(bytes_left)
        if not data:
            return buf # could theoretically be less than length
        buf += data
        bytes_left -= len(data)

    return buf

while True:
    data = recv_exactly(newsocket, PACKET_LEN)
    if (len(data) == PACKET_LEN): # Data fully received 
        udpsock.sendto(data, (serverip, serverport))
    elif (len(data) > 0): # Data partially received 
        udpsock.sendto(data, (serverip, serverport))
        udpsock.close()
    else: # got no data
        udpsock.close()

P.S .:您可以发送整个messagetobesend,而不必逐字节发送。操作系统内核和网络接口会根据需要缓冲和拆分字节。

通常:TCP是字节流,在套接字关闭时将结束。它以不可预测的块的形式到达,而与每个send调用中发送了多少数据无关。 TCP保证了流的顺序和完整性,但没有数据包边界。

UDP是不可靠的,可以以错误的数据包顺序与错误的数据一起到达,重复或根本不到达。但是UDP是面向数据包的,这意味着接收方可以确定数据包的边界,准确确定数据包的发送方式(如果数据包是通过网络发送的)。