socket聊天室 - python

时间:2017-10-10 16:59:10

标签: python sockets chat

我使用pycharm运行windows 10,python 2.7 我做一个插座聊天室的练习,我偶然发现了一个问题:

从多个cmd窗口运行客户端和服务器套接字时, 当我突然退出一个cmd窗口时,服务器应该将消息转发给剩余的客户端 - 通知他们客户端离开(包括客户端的缺口)

由于某种原因,它被证明是一个问题,服务器似乎在客户端列表中保留该客户端,引发错误,好像我向他发送了该消息(这显然是有问题的,因为他不再存在)。 / p>

当我尝试修复它时 - 将循环更改为不将消息发送到该特定客户端(通过保存其套接字对象) - 它不会发送任何消息。 好像它没有认出其他客户。

我的代码:

服务器:

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)

客户端:

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)

非常感谢帮助!

1 个答案:

答案 0 :(得分:-1)

我也一直试图建立一个聊天室,并且成功了。您可能要看一下我的代码以找到解决方案。

服务器

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()

客户端

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()