Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

socket chat room - python 3.7

This is a python chat room that I've been working on and it enables to you to chat to other people on the same network through python

Host:

import socket
import sys
import time

s = socket.socket()
host = socket.gethostname()
port = 8080
s.bind((host,port))
print("")
print("Sever adress is", host)
print("")
name = input(str("Please enter your username : "))
s.listen(1)
print("")
print("Waiting for any incoming connections ... ")
print("")
conn, addr = s.accept()
print("Recieved connection")

#connection done ###

s_name = conn.recv(1024)
s_name = s_name.decode()
print("")
print(s_name, "has connected to the chat room")
print("")
conn.send(name.encode())

## messaging loop ##

while 1:
    message = input(str("Please enter enter your message : "))
    print("")
    conn.send(message.encode())
    message = conn.recv(1024)
    message = message.decode()
    print("")
    print(name,": ",message)
    print("")

Client:

import socket
import sys
import time

print("Welcome to python chat ")
print("")
print("Initiallsing....")
time.sleep(1)

s = socket.socket()
print("")
host = input(str("Please enter server adress : "))
print("")
name = input(str("Please enter your name : "))
port = 8080
print("")
time.sleep(1)
s.connect((host,port))
print("Connected...")

## Conection done ##

s.send(name.encode())
s_name = s.recv(1024)
s_name = s_name.decode()
print("")
print( s_name, "has joined the chat room ")

while 1:
    message = s.recv(1024)
    message = message.decode()
    print("")
    print(name,": ",message)
    print("")
    message = input(str("Please enter your enter message : "))
    print("")
    s.send(message.encode())

I have 2 problems, the first problem is that it only allows one person to speak at a time, what I mean by this say that if you send a message first you won't be allowed to send another message until the other person has responded. The second problem is that this code only works for 2 users, I want it so it works for multiple users

Edit:

Also could some one acutually give a proper solution instead of telling me to start all over again please because it took me so long to figure out how to make this system in the place.

Thank you

like image 749
system123456 Avatar asked Oct 16 '22 07:10

system123456


1 Answers

You need to create two separate threads for sending and receiving. The way you have written the loop will not work for both way communication simultaneously. Because after sending a message the loop is waiting to receive something. [If you want to run the code over internet, replace localhost with the desired IP address in the line HOST = 'localhost'] Let me share a solution (this is a sample solution I have done while TAing an undergraduate class on networking):

I have tested the code on a Linux machine (Ubuntu 18.04). I have got students who have successfully ran this on their Mac. I am not sure if it runs on a windows machine. Even if it does not work on a Windows machine, a few minor modifications should do the trick.

Server sider code (you need to run this first): chatServerDuplex.py

# Import socket module
from socket import *
import threading
import sys # In order to terminate the program

FLAG = False  # this is a flag variable for checking quit

# function for receiving message from client
def recv_from_client(conn):
    global FLAG
    try:
        # Receives the request message from the client
        while True:
            if FLAG == True:
                break
            message = conn.recv(1024).decode()
            # if 'q' is received from the client the server quits
            if message == 'q':
                conn.send('q'.encode())
                print('Closing connection')
                conn.close()
                FLAG = True
                break
            print('Client: ' + message)
    except:
        conn.close()


# function for receiving message from client
def send_to_client(conn):
    global FLAG
    try:
        while True:
            if FLAG == True:
                break
            send_msg = input('')
            # the server can provide 'q' as an input if it wish to quit
            if send_msg == 'q':
                conn.send('q'.encode())
                print('Closing connection')
                conn.close()
                FLAG = True
                break
            conn.send(send_msg.encode())
    except:
        conn.close()


# this is main function
def main():
    threads = []
    global FLAG

    # TODO (1) - define HOST name, this would be an IP address or 'localhost' (1 line)
    HOST = 'localhost'
    # TODO (2) - define PORT number (1 line) (Google, what should be a valid port number)
    # make sure the ports are not used for any other application
    serverPort = 6789

    # Create a TCP server socket
    #(AF_INET is used for IPv4 protocols)
    #(SOCK_STREAM is used for TCP)
    # TODO (3) - CREATE a socket for IPv4 TCP connection (1 line)
    serverSocket = socket(AF_INET, SOCK_STREAM)

    # Bind the socket to server address and server port
    # TODO (4) - bind the socket for HOSR and serverPort (1 line)
    serverSocket.bind((HOST, serverPort))

    # Listen to at most 1 connection at a time
    # TODO (5) - listen and wait for request from client (1 line)
    serverSocket.listen(1)

    # Server should be up and running and listening to the incoming connections
    print('The chat server is ready to connect to a chat client')
    # TODO (6) - accept any connection request from a client (1 line)
    connectionSocket, addr = serverSocket.accept()
    print('Sever is connected with a chat client\n')

    t_rcv = threading.Thread(target=recv_from_client, args=(connectionSocket,))
    t_send = threading.Thread(target=send_to_client, args=(connectionSocket,))
    # call the function to receive message server
    #recv_from_server(clientSocket)
    threads.append(t_rcv)
    threads.append(t_send)
    t_rcv.start()
    t_send.start()

    t_rcv.join()
    t_send.join()


    # closing serverScoket before exiting
    print('EXITING')
    serverSocket.close()
    #Terminate the program after sending the corresponding data
    sys.exit()


# This is where the program starts
if __name__ == '__main__':
    main()

Client side code: chatClientDuplex.py

from socket import *
import threading
import sys


FLAG = False  # this is a flag variable for checking quit

# function for receiving message from client
def send_to_server(clsock):
    global FLAG
    while True:
        if FLAG == True:
            break
        send_msg = input('')
        clsock.sendall(send_msg.encode())

# function for receiving message from server
def recv_from_server(clsock):
    global FLAG
    while True:
        data = clsock.recv(1024).decode()
        if data == 'q':
            print('Closing connection')
            FLAG = True
            break
        print('Server: ' + data)

# this is main function
def main():
    threads = []
    # TODO (1) - define HOST name, this would be an IP address or 'localhost' (1 line)
    HOST = 'localhost'  # The server's hostname or IP address
    # TODO (2) - define PORT number (1 line) (Google, what should be a valid port number)
    PORT = 6789        # The port used by the server

    # Create a TCP client socket
    #(AF_INET is used for IPv4 protocols)
    #(SOCK_STREAM is used for TCP)
    # TODO (3) - CREATE a socket for IPv4 TCP connection (1 line)
    clientSocket = socket(AF_INET, SOCK_STREAM)

    # request to connect sent to server defined by HOST and PORT
    # TODO (4) - request a connection to the server (1 line)
    clientSocket.connect((HOST, PORT))
    print('Client is connected to a chat sever!\n')



    # call the function to send message to server
    #send_to_server(clientSocket)
    t_send = threading.Thread(target=send_to_server, args=(clientSocket,))
    # call the function to receive message server
    #recv_from_server(clientSocket)
    t_rcv = threading.Thread(target=recv_from_server, args=(clientSocket,))
    threads.append(t_send)
    threads.append(t_rcv)
    t_send.start()
    t_rcv.start()

    t_send.join()
    t_rcv.join()

    print('EXITING')
    sys.exit()

# This is where the program starts
if __name__ == '__main__':
    main()
like image 57
shariful Avatar answered Nov 15 '22 10:11

shariful