Socket communication that lock

Hello
I got a Micropython card that awake each minute, connect to Wifi, open a socket and push a caracter string.
on the other side a raspberry with a python script that open a socket and try to read.

It works between somes minutes to some hour but stuck always…
If I stop and start the raspberry script it works again…

I try to run on raspberry side the script :

  • on a loop “while True”
  • with a crontab that execute the script without while loop

=> same behaviour

It llok like the socket become “full” after a certain time?
Or stuck during sending/receiving process and can’t manage a new one?

When in this state the process seem’s to still open in the port

netstat -tupln grep 112zz 
tcp 3 0 192.168.xx.yy:112zz 0.0.0.0:* LISTEN -

Below the script running on the raspberry side

#!/usr/bin/env 
python3 import socket 
mySocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, fileno=None) 
mySocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
hostname = '192.168.xx.yy' 
portno = 112zz 
mySocket.bind((hostname, portno)) 
mySocket.listen(2) 

if __name__ == "__main__": 
  #while True: 
  client, client_addr = mySocket.accept() 
  print('Connection established with client at address {}'.format(client_addr)) 
  message = client.recv(1024).decode() 
  print(message) 
  client.close()

any idee of how to debug? or to improve my script quality?

Thanks

You’re only accepting a single connection at a time, and waiting for the other end to talk to you. That means, if anything connects and holds it open, your server will stall out. You may want to consider supporting multiple connections at once, to avoid this.

This listen(2) does not mean I accept 2 connection ?

My need is of course only one “wanted” client, but indeed is there is a non wanted connection try and if that bloc my script I need more than one…

Is it possible to say "I only accept connection from this IP ?

Close. It means that you can have a backlog of two connections - there can be up to two connections waiting for you to accept them. Any more than that, and the system will start telling new clients that you aren’t available.

You can reject any connection from any other IP, but you’ll still need to process the sockets. But even if you lock it to a single IP, you could get stuck in this way, since it’s entirely possible for the other end to stall out.

Ok, understand, thanks

So this kind of code should accept multiple connection ?

import socket
from _thread import *

host = '127.0.0.1'
port = 1233
ThreadCount = 0

def client_handler(connection):
    connection.send(str.encode('You are now connected to the replay server... Type BYE to stop'))
    while True:
        data = connection.recv(2048)
        message = data.decode('utf-8')
        if message == 'BYE':
            break
        reply = f'Server: {message}'
        connection.sendall(str.encode(reply))
    connection.close()

def accept_connections(ServerSocket):
    Client, address = ServerSocket.accept()
    print('Connected to: ' + address[0] + ':' + str(address[1]))
    start_new_thread(client_handler, (Client, ))

def start_server(host, port):
    ServerSocket = socket.socket()
    try:
        ServerSocket.bind((host, port))
    except socket.error as e:
        print(str(e))
    print(f'Server is listing on the port {port}...')
    ServerSocket.listen()

    while True:
        accept_connections(ServerSocket)
start_server(host, port)

I don’t know why you’d be doing from _thread import * rather than using the higher-level threading module, but broadly speaking this is one option. However, be aware that the code you have here - which, I am guessing, was written by ChatGPT, as it has multiple rather bizarre constructs in it - is designed for a quite different protocol from your original.

You may want to go back to your original version, and JUST add threading to it. Or alternatively, use asyncio instead, which scales quite efficiently. Either way will work.

Thanks, I found this code on a tuto on a web site but maybe indeed he came from ChatGPT :wink:

I like this structure of the code because a would like to avoid non allowed IP to connect and I add a test in the accept_connections() depending on the adress[0] value.

Not sure to understand your comment on from _thread import * ?
you mean it is beter to do like this :
from _thread import start_new_thread
as I only use this function?

Ah. I would posit that it might be rather ancient, but it ALSO uses several more modern features, like f-strings, so whatever it is, it’s a bit of a mess and I wouldn’t recommend using it :slight_smile:

Python has a very low level module called _thread, but for the most part, it is WAY better to use the higher level module threading. But yes, if you’re going to use _thread, I would very STRONGLY advise against using a star import. Just import the module itself (import _thread) or import specific names (from _thread import start_new_thread), rather than leave open the possibility of literally any unrecognized name coming from that module. Mainly, though, go with threading instead.

Or go with asyncio since your code isn’t going to run into the problems that demand threading. Either will work.

Thanks for advice
change to

from threading import Thread
thread = Thread(target = client_handler, args = (args))
thread.start()

Will have a look to asyncio when more time :wink: