Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Python non-blocking socket

Hi I am trying to create a very simple peer-to-peer chatting program in python. The first user can runs the server.py program below to bind to a socket.

import sys
import socket
import select
import threading

# Bind to socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 11111))
s.listen()

def chat(conn, addr):

    # Set blocking to false so that program can send and receive messages at the same time
    conn.setblocking(0)

    # Receive messages using select
    while conn in select.select([conn], [], [], 0)[0]:
        text = conn.recv(4096)
        if text:
            print("{}: {}".format(addr, text))
        else:
            return
    
    # get user input and send message
    while True:
        msg = input(">>>")
        conn.send(msg.encode())
            


if __name__ == '__main__':
    
    ## Accept connections and start new thread
    (conn, addr) = s.accept() 
    threading.Thread(target=chat, args=([conn, addr])).start()

Then another user can use netcat to connect to the server and communicate. However, the program is only able to get the user’s input and send to the other side. The user from the other side is unable to send messages.

One sided communication

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

input() blocks, so you are falling through your chat function and entering the input() loop and never checking for receiving again. Receive on the thread and enter the input loop on the main thread. TCP is full duplex so you can send/recv at the same time on two threads without turning off blocking.

I also needed to add a newline to the send() as my netcat was line-buffering.

import socket
import threading

# Bind to socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 11111))
s.listen()

def chat(conn, addr):
    while True:
        text = conn.recv(4096)
        if not text: break
        print("{}: {}".format(addr, text))


if __name__ == '__main__':
    ## Accept connections and start new thread
    conn, addr = s.accept()
    threading.Thread(target=chat, args=(conn, addr), daemon=True).start()

    # get user input and send message
    while True:
        msg = input(">>>")
        conn.sendall(msg.encode() + b'\n')
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading