0

I am working on this simple chat program with a student studying Python.

https://www.geeksforgeeks.org/simple-chat-room-using-python/

I set up the server on my macbook, with

python server.py 0.0.0.0 6677

where server.py is the script:

# Python program to implement server side of chat room.
import socket
import select
import sys
from thread import *
 
"""The first argument AF_INET is the address domain of the
socket. This is used when we have an Internet Domain with
any two hosts The second argument is the type of socket.
SOCK_STREAM means that data or characters are read in
a continuous flow."""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 
# checks whether sufficient arguments have been provided
if len(sys.argv) != 3:
    print ("Correct usage: script, IP address, port number")
    exit()
 
# takes the first argument from command prompt as IP address
IP_address = str(sys.argv[1])
 
# takes second argument from command prompt as port number
Port = int(sys.argv[2])
 
"""
binds the server to an entered IP address and at the
specified port number.
The client must be aware of these parameters
"""
server.bind((IP_address, Port))
 
"""
listens for 100 active connections. This number can be
increased as per convenience.
"""
server.listen(100)
 
list_of_clients = []
 
def clientthread(conn, addr):
 
    # sends a message to the client whose user object is conn
    conn.send("Welcome to this chatroom!")
 
    while True:
            try:
                message = conn.recv(2048)
                if message:
 
                    """prints the message and address of the
                    user who just sent the message on the server
                    terminal"""
                    print ("<" + addr[0] + "> " + message)
 
                    # Calls broadcast function to send message to all
                    message_to_send = "<" + addr[0] + "> " + message
                    broadcast(message_to_send, conn)
 
                else:
                    """message may have no content if the connection
                    is broken, in this case we remove the connection"""
                    remove(conn)
 
            except:
                continue
 
"""Using the below function, we broadcast the message to all
clients who's object is not the same as the one sending
the message """
def broadcast(message, connection):
    for clients in list_of_clients:
        if clients!=connection:
            try:
                clients.send(message)
            except:
                clients.close()
 
                # if the link is broken, we remove the client
                remove(clients)
 
"""The following function simply removes the object
from the list that was created at the beginning of
the program"""
def remove(connection):
    if connection in list_of_clients:
        list_of_clients.remove(connection)
 
while True:
 
    """Accepts a connection request and stores two parameters,
    conn which is a socket object for that user, and addr
    which contains the IP address of the client that just
    connected"""
    conn, addr = server.accept()
 
    """Maintains a list of clients for ease of broadcasting
    a message to all available people in the chatroom"""
    list_of_clients.append(conn)
 
    # prints the address of the user that just connected
    print (addr[0] + " connected")
 
    # creates and individual thread for every user
    # that connects
    start_new_thread(clientthread,(conn,addr))    
 
conn.close()
server.close()

Then, on the same macbook, to add a user,

python client.py 0.0.0.0 6677

where client.py is the script

# Python program to implement client side of chat room.
import socket
import select
import sys
 
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv) != 3:
    print ("Correct usage: script, IP address, port number")
    exit()
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.connect((IP_address, Port))
 
while True:
 
    # maintains a list of possible input streams
    sockets_list = [sys.stdin, server]
 
    """ There are two possible input situations. Either the
    user wants to give manual input to send to other people,
    or the server is sending a message to be printed on the
    screen. Select returns from sockets_list, the stream that
    is reader for input. So for example, if the server wants
    to send a message, then the if condition will hold true
    below.If the user wants to send a message, the else
    condition will evaluate as true"""
    read_sockets,write_socket, error_socket = select.select(sockets_list,[],[])
 
    for socks in read_sockets:
        if socks == server:
            message = socks.recv(2048)
            print (message)
        else:
            message = sys.stdin.readline()
            server.send(message)
            sys.stdout.write("<You>")
            sys.stdout.write(message)
            sys.stdout.flush()
server.close()

and then, on a Windows 10 computer, I run

python client.py 192.168.0.41 6677 (my server's broadcast address, read off ifconfig)

The client then connects successfully to the server, as can be seen on the server. But, the Windows computer does not join the chat, rather reading the error "[WinError 10038] an operation was attempted on something that is not a socket".

I was able to get it to work on macbook to linux. Is this something to do with a Windows firewall?

apg
  • 101
  • 5
  • 1
    On an unrelated note, the value you pass to `listen` isn't the number of active connections you can have. It's the number of connections queued waiting to be accepted. It should usually be rather low, `5` is a common value. – Some programmer dude Nov 22 '21 at 14:13
  • As for the error you get, please copy-paste the *full* and *complete* error output into the question ([edit] it), and also add a comment on the line in the code where you get it. – Some programmer dude Nov 22 '21 at 14:15
  • Unfortunately I don't have access to the student's Windows computer, but I will later. The error has also been (with a different IP address) "connection refused". I will add the full error later when I can. – apg Nov 22 '21 at 14:24
  • 1
    Does this answer your question? [Using sys.stdin in select.select on Windows](https://stackoverflow.com/questions/12499523/using-sys-stdin-in-select-select-on-windows) – Some programmer dude Nov 22 '21 at 14:31
  • Potentially. So this suggests the code itself won't work on windows, as the select.select idea won't work? – apg Nov 22 '21 at 14:35
  • 1
    That's correct, you need to figure out some other way to poll `sys.stdin` on Windows. Preferably something that could be portable for other systems as well (so you don't have two programs depending on system) :) – Some programmer dude Nov 22 '21 at 14:36
  • Would this fix it? https://stackoverflow.com/a/10842772/5267913, so basically just remove the `sys.stdin` at the line in client.py `sockets_list = [sys.stdin, server]` – apg Nov 22 '21 at 14:44

0 Answers0