【问题标题】:Python Socket Programming - Messages Getting TruncatedPython Socket 编程 - 消息被截断
【发布时间】:2015-03-18 21:16:43
【问题描述】:

我有一个 GPS 调制解调器 (Sixnet BT-5800),它尝试通过以太网以定时间隔向我的 Linux 客户端广播 GPS NMEA 消息。

在客户端我有一个 python 脚本正在运行。我希望有人能确定我是否在这里做错了什么。

'''
The main program waits on the TCP socket to receive data, parses the data into
GPS NMEA sentences and writes them to the MySQL database
'''
# python library
import configparser
import select
import socket
import sys
from time import sleep

# custom library
#import gpsnmeapacketparser

# open the configuration files
config = configparser.ConfigParser()
files = ['.config.host', '.config', '.config.mysql']
dataset = config.read(files)
if (len(files) != len(dataset)):
    print("Error: Failed to open/find configuration files. Has this package been installed?")
    exit()


def main():
    host_address = config['HOST']['IPAddress']
    host_gps_port = config['HOST']['GPSPort']

    # create a tcp/ip socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    server_address = (host_address, int(host_gps_port, 10))

    print("Binding socket:", server_address)
    sock.bind(server_address)

    # listen for incoming connections
    sock.listen(5)


    while True:
        block = ""

        # wait for a connection
        print('waiting for a connection')
        connection, client_address = sock.accept()

        print('connection from', client_address)

        data = bytearray([])
        buf = bytearray([])

        while True:
            buf = connection.recv(10)

            if buf != b'':
                data += buf
            else:
                break

        if data != b'':
            block = data.decode("utf-8")
            print(block)
            print()

        else:
            connection.close()   

if __name__ == "__main__":
    sys.exit(main())

调制解调器似乎最大输出为 512 字节消息。运行python脚本我会看到如下输出:

waiting for a connection
connection from ('192.168.0.1', 4433)
waiting for a connection
connection from ('192.168.0.1', 4434)
$GPRMC,210458.00,A,4437.35460,N,07545.93616,W,000.0,000.0,180315,13.4,W,A*0F
$GPGGA,210458.00,4437.35460,N,07545.93616,W,1,08,0.91,00121,M,-034,M,,*54
$GPGLL,4437.35460,N,07545.93616,W,210458.00,A,A*79
$GPVTG,000.0,T,013.4,M,000.0,N,000.0,K,A*25
$GPGSV,3,1,09,31,32,089,36,03,19,236,29,16,77,229,36,23,57,292,35*75
$GPGSV,3,2,09,10,07,326,23,29,08,032,17,08,58,067,41,09,29,312,36*73
$GPGSV,3,3,09,27,26,164,37,,,,,,,,,,,,*46
$GPGSA,A,3,31,03,16,23,10,29,09,27,,,,,1.61,0.91,1.33*0C
$GPZDA,210458.00,18,0

waiting for a connection
connection from ('192.168.0.1', 4435)
waiting for a connection
connection from ('192.168.0.1', 4436)
$GPRMC,210528.00,A,4437.35458,N,07545.93617,W,000.0,000.0,180315,13.4,W,A*03
$GPGGA,210528.00,4437.35458,N,07545.93617,W,1,07,1.05,00121,M,-034,M,,*5B
$GPGLL,4437.35458,N,07545.93617,W,210528.00,A,A*75
$GPVTG,000.0,T,013.4,M,000.0,N,000.0,K,A*25
$GPGSV,3,1,09,31,32,089,36,03,19,236,30,16,77,229,36,23,57,292,35*7D
$GPGSV,3,2,09,10,07,326,22,29,08,032,06,08,58,067,42,09,29,312,35*72
$GPGSV,3,3,09,27,26,164,35,,,,,,,,,,,,*44
$GPGSA,A,3,31,03,16,23,10,09,27,,,,,,1.77,1.05,1.42*0A
$GPZDA,210528.00,18,03,

waiting for a connection
connection from ('192.168.0.1', 4437)

在执行期间,connection.recv(10) 运行以收集数据,直到它返回空数组,然后它再次运行并超时。 (这是次要问题,如何确保我已收到所有数据而无需等待此超时?

这是一个 tcpdump 的输出

17:09:27.907495 IP 192.168.0.1.4621 > 192.168.0.5.8763: Flags [F.], seq 1, ack 1, win 2920, options [nop,nop,TS val 5166242 ecr 6220255], length 0
17:09:27.907667 IP 192.168.0.5.8763 > 192.168.0.1.4621: Flags [F.], seq 1, ack 2, win 202, options [nop,nop,TS val 6224000 ecr 5166242], length 0
17:09:27.908091 IP 192.168.0.1.4621 > 192.168.0.5.8763: Flags [.], ack 2, win 2920, options [nop,nop,TS val 5166242 ecr 6224000], length 0
17:09:27.910329 IP 192.168.0.1.4622 > 192.168.0.5.8763: Flags [S], seq 2455146170, win 5840, options [mss 1460,sackOK,TS val 5166244 ecr 0,nop,wscale 1], length 0
17:09:27.910390 IP 192.168.0.5.8763 > 192.168.0.1.4622: Flags [S.], seq 3558179681, ack 2455146171, win 25760, options [mss 1300,sackOK,TS val 6224000 ecr 5166244,nop,wscale 7], length 0
17:09:27.910796 IP 192.168.0.1.4622 > 192.168.0.5.8763: Flags [.], ack 1, win 2920, options [nop,nop,TS val 5166245 ecr 6224000], length 0
17:09:27.914219 IP 192.168.0.1.4622 > 192.168.0.5.8763: Flags [P.], seq 1:513, ack 1, win 2920, options [nop,nop,TS val 5166248 ecr 6224000], length 512
17:09:27.914309 IP 192.168.0.5.8763 > 192.168.0.1.4622: Flags [.], ack 513, win 210, options [nop,nop,TS val 6224001 ecr 5166248], length 0
17:09:42.895197 IP 192.168.0.1.4622 > 192.168.0.5.8763: Flags [F.], seq 513, ack 1, win 2920, options [nop,nop,TS val 5181229 ecr 6224001], length 0
17:09:42.897588 IP 192.168.0.1.4623 > 192.168.0.5.8763: Flags [S], seq 2470830214, win 5840, options [mss 1460,sackOK,TS val 5181231 ecr 0,nop,wscale 1], length 0
17:09:42.897643 IP 192.168.0.5.8763 > 192.168.0.1.4623: Flags [S.], seq 2665688556, ack 2470830215, win 25760, options [mss 1300,sackOK,TS val 6227747 ecr 5181231,nop,wscale 7], length 0
17:09:42.898114 IP 192.168.0.1.4623 > 192.168.0.5.8763: Flags [.], ack 1, win 2920, options [nop,nop,TS val 5181232 ecr 6227747], length 0
17:09:42.898383 IP 192.168.0.5.8763 > 192.168.0.1.4622: Flags [F.], seq 1, ack 514, win 210, options [nop,nop,TS val 6227747 ecr 5181229], length 0
17:09:42.898773 IP 192.168.0.1.4622 > 192.168.0.5.8763: Flags [.], ack 2, win 2920, options [nop,nop,TS val 5181232 ecr 6227747], length 0

看起来调制解调器似乎从来没有得到正确的信号来发送剩余的字符,而那些巨大的序列号可能是错误代码?

我无法确定错误是在我的代码中,还是调制解调器使用了一些非标准 TCP?

【问题讨论】:

    标签: python sockets gps


    【解决方案1】:

    TCP 是一种流式协议,您接收的不是基于消息包的。大幅增加缓冲区大小,并准备好接收可能被破坏并分散在多个接收操作中的消息。

    所以是的,这是一个 TCP 问题,但这是正常的。因为正如我所说,TCP 是一种流协议。

    如果客户端发件人没有任何停顿地这样做:

    • 发送 10 个字节
    • 发送 10 个字节

    接收者很有可能得到这个结果:

    • 接收 20 个字节

    现在如果接收者的缓冲区太小,他会丢失部分信息的机会非常高。当然不是你想要的。 接收者接收数据的方式是不可预测的,你不应该依赖它。从理论上讲,您甚至应该准备好接收每个字节的消息字节。但是因为 TCP 是为了以最智能的方式利用 MTU 来实现的,所以您不太可能会逐字节接收。但问题是您只是不知道哪条消息将被传播到不同的接听电话。

    底线使您的接收缓冲区大小为几 k。

    【讨论】:

    • 不幸的是,它看起来并不那么简单。即使缓冲区设置为 4096(最大消息约为 535),我也看到了相同的结果。调制解调器发送512字节,我们确认,调制解调器发送0长度的seq 513。
    • 当您在套接字上收到 0 字节时,这意味着服务器已经关闭了套接字的末端,将不再发送。问题是为什么?
    • 它开始看起来越来越像问题出在调制解调器方面,这是我希望在这个线程中确定的。感谢您的帮助。
    猜你喜欢
    • 2019-08-23
    • 2017-11-22
    • 2017-02-24
    • 1970-01-01
    • 1970-01-01
    • 2017-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多