首页 > 解决方案 > Select 在来自每个客户端的几条消息后返回空套接字列表

问题描述

我正在尝试使用 python 制作一个基本的基于终端的聊天应用程序。我使用 select() 来更新可读/可写连接。然而,在来自每个客户端的两条消息之后,服务器返回一个空的可读列表(sockets_list)。

我已经尝试从我的套接字列表中删除删除连接的代码。

这是 server.py

import socket
import select
import time

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# host, port
host = 'localhost'
port = 5555

# bind and listen for connections
sock.bind((host, port))
sock.listen(2)

print('Server started on. {} {}'.format(host, port))

# select lists
sockets_list = [sock]
outputs = []

clients = {}


def receive_message(conn):
    try:
        msg = conn.recv(4096)

        if not len(msg):
            return False

        return msg

    except conn.error as e:
        return False


while True:
    print('\n waiting for the next event')

    readable, writable, exceptions = select.select(sockets_list, outputs, [], 10)

    print(readable, writable)

    for s in readable:
        if s == sock:
            connection, address = s.accept()

            user = receive_message(connection)

            if user is False:
                continue

            sockets_list.append(connection)
            clients[connection] = user

            print(f'Accepted new connection from {user.decode()}')
        else:
            arr = s.recv(4096).decode().split(':')
            if len(arr) < 2:
                arr = s.recv(4096).decode().split(':')

            elif len(arr) >= 2:
                message = arr[1]
                # if message is False:
                #     print(f'Connection closed with {s}')
                #
                #     sockets_list.remove(s)
                #     del clients[s]
                #
                #     continue
                user = clients[s]
                print(f'Received message from {user.decode()}: {message}')

                for client in clients:
                    # But don't sent it to sender
                    if client != s:
                        # Send user and message (both with their headers)
                        # client.send(user['header'] + user['data'] + message['header'] + message['data'])
                        client.send(f"{user.decode()}:{message}".encode())
                        print(f'Sending {message} to {clients[client].decode()}')

这是client.py:

import socket
import select
import errno
import sys

IP = "localhost"
PORT = 5555
current_user = input("Username: ")

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

client.connect((IP, PORT))

# client.setblocking(False)

username = current_user.encode()
client.send(username)

while True:
    message = input(f'{current_user} > ')
    if message:
        # Encode message to bytes, prepare header and convert to bytes, like for username above, then send
        client.send(f'{current_user}:{message}'.encode())

    try:
        while True:

            arr = client.recv(4096).decode().split(':')
            username = arr[0]
            if not username:
                print('Connection closed by the server')
                sys.exit()

            message = arr[1]
            # Print message
            print(f'{username} > {message}')
            message = input(f'{current_user} > ')

    except IOError as e:
        print(e)
        sys.exit()

    except Exception as e:
        print(e)

我希望服务器从两个客户端接收/发送消息。这意味着无论客户端 1 发送什么,客户端 2 都会看到。

标签: pythonsocketstcp

解决方案


The issue was that I wasn't sending/receiving the data properly with the client. So I tweaked it a little bit and it works now!

while True:
    message = input(f'{current_user} > ')
    if message:
        client.send(f'{current_user}:{message}'.encode())

    arr = client.recv(4096).decode().split(':')

    if arr:
        username = arr[0]
        message = arr[1]
        # Print message
        print(f'{username} > {message}')

Putting a forever loop in a forever loop didn't make sense so I got rid of it.

I checked if the client received data with if arr: and printed the data. Since arr was in the forever loop, it ALWAYS checked for data.

To send data, it was pretty simple, get input, send it via socket.


推荐阅读