简体   繁体   中英

socket chat room - python

I'm running windows 10, python 2.7 using pycharm I'm doing as an exercise a socket chat room, and I've stumbled on a certain problem:

While running the client and server socket from multiple cmd windows, When I exit one cmd window abruptly, the server is supposed to forward a message to the remaining client - informing them that a client left (including the client's nick)

For some reason it proves to be a problem, the server seems to retain that client in the client list, raising an error as if I sent him that message (which obviously is problematic, because he is no longer there).

When I tried to fix that - changing the loop to not send the message to that specific client (by saving his socket object) -it doesn't send any message. As if it doesn't recognize the other clients.

My code:

Server:

import socket
import select
import datetime
server_socket=socket.socket()

server_socket.bind(('127.0.0.1',23))

server_socket.listen(5)
open_client_sockets = []
messages_to_send = []
chat_clients={}
def send_waiting_messages(wlist):

    for message in messages_to_send:
       (sender,msg)=message
       if(msg=='\r'):
           continue
       elif(msg=='quit'):
           pass
       else:
           nick_len=int(msg[:2])
           nick=msg[2:2+nick_len]
           chat=msg[2+nick_len:]
           chat_clients[sender]=nick
       for client in wlist:
           if(msg=='quit'):
                   client.send(('{:02d}:{:02d} {} has left the chat!'.format(datetime.datetime.now().hour,datetime.datetime.now().minute,sender)))
           else:
               if(client is sender):
                   client.send('NL')
               else:
                   client.send('{:02d}:{:02d} {}: {}'.format(datetime.datetime.now().hour,datetime.datetime.now().minute,nick,chat))
       messages_to_send.remove(message)
while True:
    rlist,wlist,xlist=select.select([server_socket] + open_client_sockets,open_client_sockets,[])
    for current_socket in rlist:
        print wlist
        if(current_socket is server_socket):
            (new_socket,address)=server_socket.accept()
            open_client_sockets.append(new_socket)
            chat_clients[new_socket]=''
        else:
            try:
                msg=current_socket.recv(1024)
            except socket.error as e:
                if e.errno==10054:
                    msg=''
                else:
                    raise
            if(msg=='' or msg=='quit'):
                if(msg=='quit'):
                    messages_to_send.append((chat_clients[current_socket], 'quit'))
                    current_socket.send('quit')
                    open_client_sockets.remove(current_socket)
                    del chat_clients[current_socket]

                else:
                    print '{:02d}:{:02d} {} has left the chat!'.format(datetime.datetime.now().hour,
                                                                 datetime.datetime.now().minute, chat_clients[current_socket])
                    messages_to_send.append((current_socket, 'quit'))

            else:
                print msg
                messages_to_send.append((current_socket,msg))
    send_waiting_messages(wlist)

Client:

import socket
import select
import datetime
server_socket=socket.socket()

server_socket.bind(('127.0.0.1',23))

server_socket.listen(5)
open_client_sockets = []
messages_to_send = []
chat_clients={}
def send_waiting_messages(wlist):

    for message in messages_to_send:
       (sender,msg)=message
       if(msg=='\r'):
           continue
       elif(msg=='quit'):
           pass
       else:
           nick_len=int(msg[:2])
           nick=msg[2:2+nick_len]
           chat=msg[2+nick_len:]
           chat_clients[sender]=nick
       for client in wlist:
           if(msg=='quit'):
                   client.send(('{:02d}:{:02d} {} has left the chat!'.format(datetime.datetime.now().hour,datetime.datetime.now().minute,sender)))
           else:
               if(client is sender):
                   client.send('NL')
               else:
                   client.send('{:02d}:{:02d} {}: {}'.format(datetime.datetime.now().hour,datetime.datetime.now().minute,nick,chat))
       messages_to_send.remove(message)
while True:
    rlist,wlist,xlist=select.select([server_socket] + open_client_sockets,open_client_sockets,[])
    for current_socket in rlist:
        print wlist
        if(current_socket is server_socket):
            (new_socket,address)=server_socket.accept()
            open_client_sockets.append(new_socket)
            chat_clients[new_socket]=''
        else:
            try:
                msg=current_socket.recv(1024)
            except socket.error as e:
                if e.errno==10054:
                    msg=''
                else:
                    raise
            if(msg=='' or msg=='quit'):
                if(msg=='quit'):
                    messages_to_send.append((chat_clients[current_socket], 'quit'))
                    current_socket.send('quit')
                    open_client_sockets.remove(current_socket)
                    del chat_clients[current_socket]

                else:
                    print '{:02d}:{:02d} {} has left the chat!'.format(datetime.datetime.now().hour,
                                                                 datetime.datetime.now().minute, chat_clients[current_socket])
                    messages_to_send.append((current_socket, 'quit'))

            else:
                print msg
                messages_to_send.append((current_socket,msg))
    send_waiting_messages(wlist)

Help would be much appreciated!

I have also been trying trying to make a chat room and I have been successful. You might want to look at my code to find the solution.

Server

import threading
from queue import Queue 
import socket
host = ''
port = 5000
client_list = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1000)

def conn():
    while True:
        (host, port) = s.accept()
        f = len(client_list)
        client_list.append(host)
        print(client_list)
        p1 = threading.Thread(target=clientam, args=str(f))
        p2 = threading.Thread(target=threader)

        p2.start()
        p1.start()

        p1.join()
        p2.join()

def clientam(client):
    size = 3000
    client = int(client)
    c = client_list[client]
    print(c)
    c.send("Welcome to the chatroom".encode())    
    while True:
        try:
            data = c.recv(size).decode()

            if data == "exit":
                for l in client_list:
                    if l == c:
                        pass
                    else:
                        l.send("The other person has left the chatroom".encode())                     
                client_list[client] = ''
                print(client_list)
                c.close()
                break

            else:
                for l in client_list:
                    if l == c:
                        pass
                    else:
                        l.send(data.encode())

        except Exception:
            for l in client_list:
                if l == c:
                    continue
                else:
                    try:
                        l.send("The other person has left the chatroom".encode())
                    except Exception:
                        pass
                    break
            try:
                c.close()
            except Exception:
                break

def threader():
    t = threading.Thread(target=conn)
    t.start()
    t.join()



threader()

client

import socket
import threading
import time
import pickle

host = '127.0.0.1'
port = 5000

s = socket.socket()
d = 0

print_lock = threading.Lock()

def conn():
    global d
    global s
    try:
        if d == 1:
            s = socket.socket()
            s.connect((host, port))
            d = 0
        elif d == 0: 
            s.connect((host, port))
    except Exception:
        conn()

def reciever():
    global d
    global g

    g = False
    li = [128, 3, 88, 0, 113, 46]
    size = 3000
    while True:
        try:
            data = s.recv(size).decode()
            data = str(data)
            with open('Data.txt', 'a') as f:
                f.write(data)

            if str(data) == 'The other person has left the chatroom':
                with print_lock:
                    print(data)
            elif str(data) == "Welcome to the chatroom":
                g = True
                with print_lock:
                    print(str(data))
            else:
                try:
                    int(data)
                    continue
                except Exception:
                    with print_lock:
                        print("Other Person:> " + str(data))
        except Exception as e:
            with print_lock:
                print("You have been disconnected")
            d = 1
            s.close()
            with print_lock:
                print('Trying to connect to server')
            conn()

def sender():
    global d
    global g

    while True:
        if g == True:
            while True:
                with print_lock:
                    i = input('You:> ')
                if i == 'exit':
                    try:
                        s.send(i.encode())
                        with print_lock:
                            print("You have been disconnected")
                        d = 1
                    except Exception:
                        with print_lock:
                            print('You have been disconnected')
                        d = 1
                elif i == "connect":
                    if d == 0:
                        with print_lock:
                            print("Server already connected")
                    elif d == 1:
                        with print_lock:
                            print('Server connecting')
                        conn()
                else:
                    try:
                        if d == 0:
                            s.send(i.encode())
                        elif d == 1:
                            with print_lock:
                                print('Server is disconnected')
                    except Exception:
                        with print_lock:
                            print('Server is disconnected')

def threader():
    p1 = threading.Thread(target = reciever)
    p1.start()

    p2 = threading.Thread(target = sender)
    p2.start()

    p1.join()
    p2.join()

conn()
threader()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM