Python socket.sendall 发送看似任意长度的数据

0 投票
1 回答
767 浏览
提问于 2025-05-01 10:26

我正在用Python 3的socket库写一个小脚本,目的是把通话记录发送到服务器。

每条记录的大小正好是109个字节。

当我在发送数据的过程中观察接收端和使用Wireshark工具时,我发现有些数据包的大小明显不对。Wireshark显示,有一个数据包虽然数据是正确的,但它的大小却是170个字节。还有一些数据包的大小超过了1500个字节。

有时候,接收端会拒绝两个数据包,大小分别是59和50个字节(加起来正好是一个完整的数据包的大小)。

有没有办法让这个过程更加可靠呢?

这是我正在使用的方法。

def connect_to_collector(iterator_obj, host, port, rate, count):

if count == None:
  count = len(iterator_obj.mylist)
delay = 3600 / int(rate)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, int(port)))
print ('\n[+] Connected to {} on port {}'.format(host, port))

start = timer()
i = 0
for record in iterator_obj:

  if i < count:
    try:
      if len(record) is not length:
        print ('the length was ', length)
      s.sendall(record)
      time.sleep(delay)
      i += 1 

    except:
      e = sys.exc_info()
      print ('SEND ERROR OCCURRED ', e)
      print ('\n[+] Sent {} to {} on port {} in {:.4f} seconds'.format(i, host, port, timer() - start))
      sys.exit()

    if verbose:
      print ('Sending : |{:' '<150}| record number |{}|'.format(record, i))
  if i >= count:
    break     
# Clean up

print ('\n[+] Sent {} to {} on port {} in {:.4f} seconds'.format(count, host, port, timer() - start))

s.close()

补充说明:在

for record in iterator_obj:

  if i < count:
    try:
      if len(record) is not length:
        print ('the length was ', length)
      s.sendall(record)

迭代器内部的while循环有一个bug,导致sendall()函数有时会被多次调用来发送同一条记录。

我已经把那个循环去掉了。

暂无标签

1 个回答

0

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

有没有办法让这个工作得更可靠一些?

你这里使用的是TCP协议,而TCP是一种流协议,不是数据报(包)协议。这意味着整个连接被视为一个连续的数据流,TCP会根据需要进行优化,比如把一些数据一起发送,或者把其他数据拆开发送。如果你期待每次接收的数据正好对应一次发送,那你就理解错了。

如果你想要使用数据报协议,可以选择UDP。不过这样的话,你就得自己处理丢失的数据包、数据包的顺序问题或者重复数据包的问题。有一些协议,比如SCTP,像UDP一样是数据报协议,但又具备TCP的可靠性。不过这些协议可能不是在所有地方都能使用,使用时可能会遇到防火墙的问题。

撰写回答