我有一个GPS调制解调器(Sixnet BT-5800)尝试通过以太网将GPS NMEA消息以定时间隔广播到我的Linux客户端。
在客户端上我运行了一个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?
答案 0 :(得分:2)
TCP是一种流媒体协议,您没有收到基于消息的数据包。大幅增加缓冲区大小并准备好接收可能被破坏并分散在多个接收操作上的消息。
所以是的,这是一个TCP问题,但这是正常的。因为我说TCP是一种流媒体协议。
如果客户端发件人在没有任何暂停的情况下执行此操作:
接收者很可能得到这个结果:
现在如果接收器的缓冲区太小,很可能会丢失部分信息。当然不是你想要的。 接收方接收数据的方式是不可预测的,您不应该依赖它。从理论上讲,您应该准备好每字节接收消息字节。但是因为实现TCP是为了以最智能的方式使用MTU,所以每个字节不太可能接收到字节。但问题是你不知道哪些消息将分散在不同的接听电话上。
底线使您的接收缓冲区的大小达到几个k。