如何在基于多客户端套接字的聊天室中实现多个渠道?

时间:2019-12-01 16:28:13

标签: python python-3.x sockets server chat

我一直在遵循有关如何使用python 3使用套接字进行多客户端聊天的教程。到目前为止,我已经开始使用它了。这是我的代码:

server.py

import socket
import select

Header_Length = 10

IP = "127.0.0.1"
PORT = 1234

class Channels(object):

    name = ""
    members = ""

    # Class constructor
    def __init__(self, name):
        self.name = name
        self.members = set()


    def AddUserToChannel(self, client):
        if client not in members:
            self.members.add(client)
        else:
            print('Member already exists in this channel.')

    def RemoveUserFromChannel(self, client):
        self.members.discard(client)

    def make_channel():
        channel = Channel(name, members)
        return channel


# Creating socket with IPv4 and TCP
Server_Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Setting server socket option
Server_Socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# Server will use IP and PORT to connect
Server_Socket.bind((IP, PORT))

# Start listening
Server_Socket.listen()

# List of sockets
Sockets_List = [Server_Socket]

# Using dictonary to create client list
Clients = {}

print(f'Listening for connections on {IP}:{PORT}')

# Receive message
def receive_message(Client_Socket):

    try:
    # Checking message length
        Message_Header = Client_Socket.recv(Header_Length)

        if not len(Message_Header):
            return False

        Message_Length = int(Message_Header.decode('utf-8'))

        # Return header and data
        return {'header': Message_Header, 'data': Client_Socket.recv(Message_Length)}

    except:
        return False



while True:
    Read_Sockets, _, Exception_Sockets = select.select(Sockets_List, [], Sockets_List)

# Checking all sockets
    for Connected_Socket in Read_Sockets:

    # Checking new connection
        if Connected_Socket == Server_Socket:
            Client_Socket, Client_Address = Server_Socket.accept() # Accepting new connection

            # Get username provided by the client
            User = receive_message(Client_Socket)

            # Client disconnect
            if User is False:
                continue

            # If client did not disconnect, appending the connected list
            Sockets_List.append(Client_Socket)
            Clients[Client_Socket] = User

            print('Accepted new connection from {}:{}, username:{}'.format(*Client_Address, User['data'].decode('utf-8')))

        # Old connection
        else:
            # New message
            Message = receive_message(Connected_Socket)

            # Remove client from the list if disconnect
            if Message is False:
                print('Closed connection from:{}'.format(Clients[Connected_Socket]['data'].decode('utf-8')))
                Sockets_List.remove(Connected_Socket)
                del Clients[Connected_Socket]
                continue

            # Checking who sent the message
            User =  Clients[Connected_Socket]

            print(f'Received message from {User["data"].decode("utf-8")}: {Message["data"].decode("utf-8")}')

            # Broadcasting message
            for Client_Socket in Clients:
                # Filtering so that sender do not receive the message
                if Client_Socket != Connected_Socket:
                    Client_Socket.send(User['header'] + User['data'] + Message['header'] + Message['data'])

# Exception handling
    for Connected_Socket in Exception_Sockets:
        Sockets_List.remove(Connected_Socket)
        del Clients[Connected_Socket]

client.py

Client_Username = input("Username: ")


# Creating socket for client
Client_Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Client_Socket.connect((IP, PORT))
Client_Socket.setblocking(False)

# Sending username and header
Username = Client_Username.encode('utf-8')
Username_Header = f"{len(Username):^{Header_Length}}".encode('utf-8')
Client_Socket.send(Username_Header + Username)

while True:
    # Waiting for message input
    Message = input(f'{Client_Username} >>> ')
    #Message = ""

    # Sending message
    if Message:
        Message = Message.encode('utf-8')
        Message_Header = f"{len(Message):^{Header_Length}}".encode('utf-8')
        Client_Socket.send(Message_Header + Message)

    # Checking for received messages from other users
    try:

        while True:
            Username_Header = Client_Socket.recv(Header_Length)

            # Closing connection
            if not len(Username_Header):
                print('Server Disconnected')
                sys.exit()

            # Decoding username and message
            Username_Length = int(Username_Header.decode('utf-8'))
            Username = Client_Socket.recv(Username_Length).decode('utf-8')
            Message_Header = Client_Socket.recv(Header_Length)
            Message_Length = int(Message_Header.decode('utf-8'))
            Message = Client_Socket.recv(Message_Length).decode('utf-8')

            print(f'{Username} >>> {Message}')

    # Error handling
    except IOError as ex:
        if ex.errno != errno.EAGAIN and ex.errno != errno.EWOULDBLOCK:
            print('IO Error: {}'.format(str(ex)))
            sys.exit()
        continue
    # Error handling
    except Exception as ex:
        print('Error: '.format(str(e)))
        sys.exit()

现在我要实现的是客户端聊天可以具有多个渠道,并且用户会说诸如!join channel_name这样的内容是对主要渠道的补充。我认为可以采用多种方法,但是我不确定100%。 我可能要做的一件事是添加一个if语句,这样,如果用户以!join开头一个短语,它将把该用户移至另一个频道。 我坚持的另一件事是首先要具有多个渠道。我是否需要在不同的端口上使用多个服务,还是有另一种使用套接字实现此服务的方法?

0 个答案:

没有答案