从硬件(GPRS模块)发送时由对等方重置连接,但从PC发送时可以正常连接

2024-06-08 18:22:05 发布

您现在位置:Python中文网/ 问答频道 /正文

<太长了,读不下去了,博士><强>

  • 从PC和Quectel GPRS模块发送相同的数据
  • 从Quectel发送时,服务器引发异常Connection reset by peer
  • 但是Quectel工作在具有相同EC2微实例和负载均衡器的生产环境中。你知道吗
  • 除了Quectel之外,另一个GPRS模块Neoway M680也适用于这个EC2实例。你知道吗

设置

本地-设置
我有一个QuectelM66,一个GPRS模块,我用它连接到服务器(AWS EC2)并传输一些数据。
我还有一个python script我已经用PC连接并发送相同的数据

import socket
import sys
from io import open
from time import sleep

'''
Python script to send data to remote server
'''
#replace address with the remote server address
HOST, PORT = '127.0.0.1', 3000 

if len(sys.argv) < 2:
    error = "Error:"
    print("{} {}".format(error, "Pass in the file to be send"))
    exit(1)

filename = sys.argv[1]

with open(filename, "r", newline="\r") as f:
    lines = f.readlines()

data = "".join(lines)

# Create a socket (SOCK_STREAM means a TCP socket)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    # Connect to server and send data
    sock.connect((HOST, PORT))
    sock.sendall(bytes(data, "utf-8"))

    # Receive data from the server and shut down
    received = r"{}".format(sock.recv(1024))
    sock.close()

print("Received: {}".format(received))

远程-设置
我正在运行一个EC2-micro实例,这个实例运行一个python脚本,它只监听一个端口并打印它接收到的数据,还发送一个硬编码的响应。这是剧本

#!/usr/bin/env python3

'''
Python code running on EC2-micro
'''

import socket
import errno
from datetime import datetime

print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

HOST = '0.0.0.0'  # Standard loopback interface address (localhost)
PORT = 3000       # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print('Connected by', addr)
        while True:
            try:
                data = r"{}".format(conn.recv(1024))
                print("Received: {}".format(data))
                #respond back with $E0A0
                conn.sendall(bytes("$E0A0:8B\r$E0FF\r", "utf-8"))
                conn.close()
                s.close()
                break
            except socket.error as e:
                if e.errno != errno.ECONNRESET:
                    raise
                if e.errno == errno.ECONNRESET:
                    printf("Connection reset by peer error again")
                    raise #it is failing here
                pass

测试

Quectel GPRS模块

当我尝试使用Quectel模块和AT Commands模块发送数据时,我从硬件(quectel)端看到的是连接已经CLOSED

17:29:05.652 [Tx] AT+QIOPEN="TCP","127.0.0.1",3000\r
17:29:05.672 [Rx] \r\nOK\r\n\r\nCONNECT OK\r\n
17:29:07.699 [Tx] AT+SEND=1\r
17:29:07.718 [Rx] >
17:29:08.603 [Tx] A
17:29:08.647 [Rx] \r\nSEND OK\r\n
17:29:09.446 [Rx] CLOSED

在EC2上运行的代码会崩溃:

Connection reset by peer error again
Traceback (most recent call last):
  File "./server.py", line 22, in <module>
    data = r"{}".format(conn.recv(1024))
ConnectionResetError: [Errno 104] Connection reset by peer

但是当我使用python脚本进行测试时,这种情况不会发生(上面给出的第一个代码)

从PC运行python脚本

$ python client.py data
Received: b'$E0A0:8B\r$E0FF\r'

更多观察:

  • 这个硬件(quectel)正在生产环境中使用,它在那里按预期工作。只有在这个新的独立实例(没有load balancing)中,它才会因Connection reset by peer而失败
  • 我了解到这可能是因为(从here
    • 服务器端资源限制
    • 高流量
  • 但这个新实例没有做任何其他事情。我还检查了CloudWatch,没有发现CPU使用率出现峰值。你知道吗

问题

  1. 你认为这是服务器端的问题吗?
    • 由于Quectel模块用SEND OK响应,从文档中我们可以确定数据已经离开了模块。TCP承诺提供数据
    • 但显然,在数据被接收/读取之前,我们得到了Connection reset by peer
  2. 是性能/基础设施问题吗?
    • 我所能找到的听起来合理的是,服务器可能会减少内存或其他资源

Tags: 模块数据实例importformatdatabywith