Python How to read beyond sockets

Question:

I have the following code:

import click
import time
import socket

@click.group(chain=True)
def cli():
    pass

j = 0

@cli.command()
def main():
    global j
    while j == 0:
        print("Hi")
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: #This is our server
            s.bind((socket.gethostname(), 1234))
            s.listen(5)
            clientsocket, adress = s.accept()
            print(f"Connection from {adress} has been estanblishded !")
            msg  = clientsocket.recv(1024)
            decodedmsg = msg.decode()
            print(decodedmsg)
            j += int(decodedmsg)
            print(str(j))
            time.sleep(1)

@cli.command()
def toggle():
    clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    clientSocket.connect((socket.gethostname(), 1234))
    data = "1" #what we want to send
    clientSocket.send(data.encode())  #telling the client to send the information to the server


if __name__ == "__main__":
    cli()

So far, if I run the file I get Hi, and the the program waits for a connection.

I want, whilst j=0, to have my program print Hi every second. The idea is that the program is printing Hi until python3 pathto/program.py toggle is executed. Does anybody know how I could adjust the code?

Asked By: Maths Wizzard

||

Answers:

s.accept() blocks until there is a connection. To keep it from blocking, use select.select() with a timeout to query if the server socket is ready with a connection. If it times out, continue to print "Hi".

import click
import socket
import select

@click.group(chain=True)
def cli():
    pass

@cli.command()
def main():
    counter = 0
    # Set up the server
    with socket.socket() as s:
        s.bind(('', 1234))
        s.listen()
        with s: # ensure it will be closed when block exits
            while counter == 0:
                print('Hi')
                # readers will be empty on timeout or contain [s]
                # if a connection is ready
                readers, _, _ = select.select([s], [], [], 1.0)
                if s in readers:
                    clientsocket, address = s.accept()
                    with clientsocket: # ensure socket will close
                        print(f"Connection from {address} has been established!")
                        counter += int(clientsocket.recv(1024))
                        print(counter)

@cli.command()
def toggle():
    clientSocket = socket.socket()
    clientSocket.connect((socket.gethostname(), 1234))
    with clientSocket:
        data = "1" #what we want to send
        clientSocket.send(data.encode())  #telling the client to send the information to the server

if __name__ == "__main__":
    cli()

Output after running test main in one command window and test toggle after a few seconds in another command window:

Hi
Hi
Hi
Hi
Connection from ('192.168.1.3', 7530) has been established!
1
Answered By: Mark Tolonen
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.