Python套接字服务器脚本
在运行最新Raspbian构建的RasPi(第1代)上设置一个连续运行的python编写的套接字服务器时,我遇到了一个问题。我想做的是将RasPi设置为远程temp的数据服务器。使用ESP32和WiFi进行通信的传感器。 我遇到的问题是我的服务器冻结,这是在不规则的基础上发生的。服务器所做的(或至少应该做的)是,它接受一个远程连接,获取数据,将其分块并将数据保存到一个文件中。脚本一开始运行得很好,一切都按预期运行,但随着时间的推移,它冻结了,为了编码神的爱,我不知道为什么。也许这里有人能帮我 服务器代码如下:Python套接字服务器脚本,python,server,raspberry-pi,raspbian,serversocket,Python,Server,Raspberry Pi,Raspbian,Serversocket,在运行最新Raspbian构建的RasPi(第1代)上设置一个连续运行的python编写的套接字服务器时,我遇到了一个问题。我想做的是将RasPi设置为远程temp的数据服务器。使用ESP32和WiFi进行通信的传感器。 我遇到的问题是我的服务器冻结,这是在不规则的基础上发生的。服务器所做的(或至少应该做的)是,它接受一个远程连接,获取数据,将其分块并将数据保存到一个文件中。脚本一开始运行得很好,一切都按预期运行,但随着时间的推移,它冻结了,为了编码神的爱,我不知道为什么。也许这里有人能帮我 服
import socket
import datetime
PARAMS=['T','P','A','H','B','C']
sensors={'id':0}
for param in PARAMS:
sensors[param]={'value':0.0,'index_start':0,'index_end':0}
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.0.10', 7543 ))
s.listen(1)
while True:
print("****Waiting for connection")
conn, addr = s.accept()
#create index for data slicing
contents=[]
with conn:
print('***Incoming connection from: ', addr)
while conn: # change here!
print("****What do you have for me? ")
content = conn.recv(1024)
print("***Received: ")
print(content)
contents.append(content)
print("****Data put into the pool")
if not content:
print("****No more data")
break
#conn.sendall(data)
print("***Data passed for processing: ")
print(contents)
now=datetime.datetime.now()
timestamp=now.strftime("%Y-%m-%d %H:%M:%S")
temp_list=[]
for c in contents:
clean_c=str(c).lstrip('b\'').rstrip('\'')
temp_list.append(clean_c)
text=''.join(temp_list)
print(text)
for i,param in enumerate(PARAMS):
sensors[param]['index_start']=text.index(param)+2
if param != 'T':
prev_param=PARAMS[i-1]
sensors[prev_param]['index_end']=text.index(param)
if param == 'C':
sensors[param]['index_end']=len(text)-1
sensors['id']=text[:sensors['T']['index_start']-2]
for param in PARAMS:
sensors[param]['value']=text[sensors[param]['index_start']:sensors[param]['index_end']]
if param == 'C':
sensors[param]['value']=text[sensors[param]['index_start']:]
value_tuple=(timestamp,sensors['id'],)
for param in PARAMS:
value_tuple+=(sensors[param]['value'].replace('.',','),)
text='\t'.join(value_tuple)
with open('/home/pi/Desktop/sensors.csv','a+') as file:
file.write(text+'\n')
print("****Closing connection")
print(timestamp)
#conn.close()
冰冻总是发生在地面上
content = conn.recv(1024)
我知道这个函数会锁定我的程序,但我不知道如果没有数据为什么它会出现在那里?怎么做才能做到。。。。好。。不是吗?我在客户端关闭连接,据我所知,with
函数应该响应socet关闭,对吗
任何帮助都将不胜感激
编辑1:
所以我被问及堆栈错误,但没有。在I Ctr+C之后,我得到了一个标准的响应,只有content=conn.recv(1024)
reference:
Traceback (most recent call last):
File "/home/pi/My_Python/Server2.py", line 27, in <module>
conn, addr = s.accept()
File "/usr/lib/python3.7/socket.py", line 212, in accept
fd, addr = self._accept()
KeyboardInterrupt: Execution interrupted
这可能是stop()函数的EOF吗?如果是这样的话,我的服务器有时是否有可能没有收到此消息?这会使它冻结。但是如果是这样的话,我需要有一种方法来查看插座是否打开。如果我的客户端关闭了一个连接,这意味着套接字已经完成,服务器应该检测到它。我可以这样做。但如何做到这一点呢?我本来想从我的剧本中起诉“康恩”,但由于我刚刚开始使用这种语言,这对我来说仍然是压倒性的。那么“conn”是一个对象吗?变量?当我打印它时,我从中得到了大量的数据。那么,它是一根绳子吗?我在这里不知所措
编辑3:
这些帖子的编辑让人觉得很可笑,但我想这就是规则
首先,我要说一声“谢谢你!”感谢到目前为止一直在帮助我的每一个人。你们太棒了D
我花了一段时间才回答,因为我一直在排除故障。我想这是我并不特别喜欢Python的事情之一。没有包含完整功能描述的存储库。例如,我所看到的每个地方都有这样一句话:“socket.recv()是一个阻塞函数”。(引用亚历克·鲍德温(Alec Baldwin)在广告中的话)是的,它是一个阻塞函数,但不,它不是。您可以做的是
conn.recv(59,socket.MSG_DONTWAIT)
它所做的是获取传入缓冲区,就是这样。没有等待。我想这应该与conn.recv()
相同,我很高兴尝试它,它一直运行正常,直到我得到暂时不可用的[Errno 11]资源
,基本上说没有什么可读的。我认为这可能是获取EOF信号的问题——从何时抛出异常判断——即使我发送/读取了一定数量的字节。这意味着这个问题与我到目前为止的经历是一致的。冷tl;医生:
conn
上设置超时,以避免客户端可能出现的问题content=conn.recv(1024)
周围的所有异常,记录它们并关闭套接字contents.append(content)
发生在检查conn close之前,因此在输入结束时总是以[…,b'']结束s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 7543 ))
s.listen(1)
while True:
print("****Waiting for connection")
conn, addr = s.accept()
#create index for data slicing
contents=[]
with conn:
print('***Incoming connection from: ', addr)
while conn: # change here!
print("****What do you have for me? ")
content = conn.recv(1024)
print("***Received: ")
print(content)
contents.append(content)
print("****Data put into the pool")
if not content:
print("****No more data")
break
#conn.sendall(data)
print("***Data passed for processing: ")
print(contents)
意见1:
通过对netcat和telnet的多次测试,服务器继续按预期工作。使用netcat I Ctrl+C,在我的系统上,它使连接在等待时间上,但服务器继续工作(如预期的那样)。杀死任一客户端(使用kill
)也不会对服务器产生影响
我可能对服务器造成一些伤害的一种情况是,我使用以下命令强制终止客户端TCP连接:
$ sudo ss -K dst 127.0.0.1 dport = 7543
在这种情况下,服务器会因以下原因中断:
Traceback (most recent call last):
File "./tests.py", line 24, in <module>
content = conn.recv(1024)
ConnectionResetError: [Errno 104] Connection reset by peer
上述行为是标准的。实际上,您并没有像问题中那样得到2条流,而是在同一个流中得到2条“消息”(在TCP中,我认为正确的术语是段)。第一个是客户端发送的数据,第二个(EOF)是在套接字终止时发送到应用程序(FIN,ACK+FIN,ACK)。我相信这里的EOF不是由客户端发送的,而是由本地TCP/IP堆栈(内核)发送到您的应用程序,以指示终止序列发生在TCP套接字中,因此您不能“错过它”(对此不是100%确定)。如果你错过了什么,那就是鳍序列
观察3:recv上的插座超时和阻塞()
您在问什么是conn
:它是特定于特定客户机的套接字对象。这就是回报
如果您怀疑客户端已连接,但很长一段时间没有发送任何内容(是的,这会阻塞recv(),从而阻塞您的服务器),我建议您尝试。我这样说是因为从我收集的数据来看,客户机在每个循环中连接、发送、关闭。如果由于某种原因没有发生这种情况,而客户端只是连接并等待,那么它会使服务器循环保持忙碌,因为它刚刚接受客户端并等待conn
套接字上的数据
这是我认为服务器会阻塞recv()
的唯一情况,很可能是由于客户端没有发送。。。在任何情况下,您的服务器都不应该真的“易受攻击”,因此我会尝试conn.settimeout(5)
给客户端5秒的时间进行传输。您需要处理超时异常,该异常在时间过去且客户端未发送任何内容时引发
我试图用下面的话来谴责这个案子
$ sudo ss -K dst 127.0.0.1 dport = 7543
Traceback (most recent call last):
File "./tests.py", line 24, in <module>
content = conn.recv(1024)
ConnectionResetError: [Errno 104] Connection reset by peer
***Incoming connection from: ('127.0.0.1', 49272)
****What do you have for me?
***Received:
b'asdasd\r\n'
****Data put into the pool
****What do you have for me?
***Received:
b'asdasd\r\n'
****Data put into the pool
****What do you have for me?
***Received:
b'sadasd\r\n'
****Data put into the pool
****What do you have for me?
***Received:
b'asdsda\r\n'
****Data put into the pool
****What do you have for me?
***Received:
b'' # <<<<<< HERE you receive the "close"
****Data put into the pool
****No more data
***Data passed for processing:
[b'asdasd\r\n', b'asdasd\r\n', b'sadasd\r\n', b'asdsda\r\n', b''] # <<<<<< Here you see you added it in contents
***Incoming connection from: ('127.0.0.1', 51194)
****What do you have for me?
***Received:
b'asdasd\n'
****Data put into the pool
****What do you have for me?
***Received:
b'asdasd\n'
****Data put into the pool
****What do you have for me?
^CTraceback (most recent call last):
File "./tests.py", line 24, in <module>
content = conn.recv(1024)
KeyboardInterrupt
****Waiting for connection
***Incoming connection from: ('127.0.0.1', 51858)
****What do you have for me?
***Received:
b'asd\r\n'
****Data put into the pool
****What do you have for me?
!!! ERROR while receiving: timed out
***Data passed for processing:
[b'asd\r\n']
****Waiting for connection
$ telnet localhost 7543
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
asd # << This was received before timeout
Connection closed by foreign host. ## << This is the server hanging up
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 7543 ))
s.listen(1)
while True:
print("****Waiting for connection")
conn, addr = s.accept()
#create index for data slicing
contents=[]
with conn:
conn.settimeout(5) # << NEW!
try: # << NEW!
print('***Incoming connection from: ', addr)
while conn: # change here!
print("****What do you have for me? ")
content = conn.recv(1024)
print("***Received: ")
print(content)
contents.append(content)
print("****Data put into the pool")
if not content:
print("****No more data")
break
#conn.sendall(data)
except Exception as e:
print("!!! ERROR while receiving:", str(e))
print("***Data passed for processing: ")
print(contents)