TCP-server i Python hakar upp sig

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
JanErik
Inlägg: 3118
Blev medlem: 11 februari 2008, 17:15:58
Ort: Vasa, Finland

TCP-server i Python hakar upp sig

Inlägg av JanErik »

Har gjort en liten server för att ta emot mätvärden från en ESP8266,

Kod: Markera allt

#!/usr/bin/env python
import socket
import struct
import time

TCP_PORT = 5005
BUFFER_SIZE = 50  # Normally 1024, but we want fast response

temperature = 0.5
temperaturetime = 0
temperature2 = 0.0
temperature2time = 0
humidity = 0.7
humiditytime = 0

MEASTIMEOUT = 900

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.bind(('', TCP_PORT))
s.listen(1)

'''
  Measurement packet spec:
  byte 0: 0xB5 "Magic number"
  byte 1: 0xB1 temperature
          0xB2 humidity
          0xB3 temperature2
  byte 2-5: value
    
  Ack packet spec:
  byte 0: 0xA5 "Magic number"
  byte 1: 0xB1 temperature
          0xB2 humidity
          0xB3 temperature2
'''
 
while 1:
    conn, addr = s.accept()
    #print 'Connection address:', addr

    data = bytearray(conn.recv(BUFFER_SIZE))
    #print "received data: "
    #print " ".join(hex(n) for n in data)
    
    if(data[0] == int("0xB5", 16)): #measurement packet
      print "Measurement packet"
      if(data[1] == int("0xB1", 16)):
        temperature = struct.unpack('<f', struct.pack('4B', data[2], data[3], data[4], data[5]))[0]
        print "Received temperature: ", temperature
        temperaturetime = int(time.time())
        data[0] = int("0xA5", 16)
        data[1] = int("0xB1", 16)
        conn.send(data)

      elif (data[1] == int("0xB2", 16)):
        humidity = struct.unpack('<f', struct.pack('4B', data[2], data[3], data[4], data[5]))[0]
        #humidity = struct.unpack_from('<f', data, 2)
        print "Received humidity: ", humidity
        humiditytime = int(time.time())
        data[0] = int("0xA5", 16)
        data[1] = int("0xB2", 16)
        conn.send(data)

      elif (data[1] == int("0xB3", 16)):
        temperature2 = struct.unpack('<f', struct.pack('4B', data[2], data[3], data[4], data[5]))[0]
        print "Received temperature 2: ", temperature2
        temperature2time = int(time.time())
        data[0] = int("0xA5", 16)
        data[1] = int("0xB3", 16)
        conn.send(data)

    elif (data[0] == int("0xD5", 16)): #request packet
      if(data[1] == int("0xB1", 16)):
        print "Request temperature"
        if((int(time.time()) - temperaturetime) < MEASTIMEOUT):
          data[0] = int("0xA5", 16)
          data[1] = int("0xB1", 16)
          struct.pack_into('f', data, 2, temperature)
        conn.send(data)
      elif(data[1] == int("0xB2", 16)):
        print "Request humidity"
        if((int(time.time()) - humiditytime) < MEASTIMEOUT):
          data[0] = int("0xA5", 16)
          data[1] = int("0xB2", 16)
          struct.pack_into('f', data, 2, humidity)
        conn.send(data)
      elif(data[1] == int("0xB3", 16)):
        print "Request temperature 2"
        if((int(time.time()) - temperature2time) < MEASTIMEOUT):
          data[0] = int("0xA5", 16)
          data[1] = int("0xB3", 16)
          struct.pack_into('f', data, 2, temperature2)
        conn.send(data)

    conn.close()
Men den hakar upp sig slumpmässigt, ofta efter några timmar. ESP8266 sänder data var 10:de minut, likadant körs ett annat Pythonskript var 10:de minut från Cron, som lagrar mätningarna i MariaDB.

ESP8266 går i deepsleep efter att ha sänt och kommer således att starta på reset nästa gång.

Oftast verkar den haka upp sig på mätningarna, antingen efter "Received humidity" eller "Received temperature 2". Räcker att starta om serverprocessen, ESP8266 fortsätter nog sända.

Ser ni nåt fundamentalt fel här? SO_REUSEADDR och SO_REUSEPORT har jag satt till i hopp om att det skulle lösa problemet.

Kör ju data = bytearray(conn.recv(BUFFER_SIZE)) för varje inkommande anslutning men Python borde väl städa upp det utan att det blir minnesläckor eller liknande?
danwi
Inlägg: 377
Blev medlem: 16 oktober 2008, 17:00:59
Ort: Linköping

Re: TCP-server i Python hakar upp sig

Inlägg av danwi »

En liten gissning skulle kunna vara att programmet hänger i en "conn.send()" om sändningen inte lyckas. send() och recv() är blockerande om du inte explicit satt non-blocking-läge med conn.setblocking(0). Du kan prova att lägga in conn.settimeout() med något vettigt argument, typ några sekunder eller så, efter s.accept()-raden. Då borde programmet iaf inte hänga sig om det är blockering som är problemet, utan du ska få en timeout exception i stället.
Användarvisningsbild
maDa
Inlägg: 4073
Blev medlem: 11 november 2005, 22:13:16
Ort: Malmö
Kontakt:

Re: TCP-server i Python hakar upp sig

Inlägg av maDa »

Får jag lov att rekommendera att använda ett beprövat protokoll som MQTT istället. Fingerar utmärkt både i Python och på en ESP8622
Skriv svar