Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
467 views
in Technique[技术] by (71.8m points)

python - 如何在基于多客户端套接字的聊天室中实现多个渠道?(How would I implement multiple channels in a multi-client socket based chat room?)

I've been following a tutorial on how to make multi-client chat using socket with python 3. So far I've got it working.

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

Here's my code:

(这是我的代码:)

server.py

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

Now what I'm trying to implement is the client chat can have multiple channels, and a user would say something such as !join channel_name this is in addition to a main channel.

(现在我要实现的是客户端聊天可以具有多个渠道,并且用户会说诸如!join channel_name东西,这是对主要渠道的补充。)

There is multiple approaches I think would be possible, but I'm not 100% sure.

(我认为可以采用多种方法,但是我不确定100%。)

One thing I might have to do is add an if statement, so that if the user begins a phrase with !join it would move said user to the different channel.

(我可能要做的一件事是添加一个if语句,这样,如果用户使用!join开头一个短语,它将把该用户移至另一个通道。)

Another thing I'm stuck on is making having multiple-channels in the first place.

(我坚持的另一件事是首先要具有多个渠道。)

Would I need to have multiple serves with different ports, or would there be another way to implement this using sockets?

(我是否需要在不同的端口上使用多个服务,还是有另一种使用套接字实现此服务的方法?)

  ask by GuardGoose translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...