繁体   English   中英

Python 控制台用socket聊天

[英]Python console chat with socket

我正在与服务器和客户端编写一个简单的控制台聊天。 当接收到来自第一个客户端的消息时,服务器应该将其发送给第二个客户端,反之亦然。 但是当第一个客户端向服务器发送消息时,它会返回并且不会到达第二个客户端。 可能receive receiving() function有问题。

这是我的client.py

import socket
from _thread import *


def recieving(clientSocket):
    while True:
        encodedMsg = clientSocket.recv(1024)
        decodedMsg = encodedMsg.decode('utf-8')

        print(decodedMsg)


def chat(clientSocket, name):
    msg = input()
    encoded_msg = f'[{name}] {msg}'.encode('utf-8')

    clientSocket.send(encoded_msg)


def main():
    serverAddress = (socket.gethostname(), 4444)

    clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    clientSocket.connect(serverAddress)

    name = input('Enter your name: ')
    start_new_thread(recieving, (clientSocket,))
    while True:
        chat(clientSocket, name)
    

if __name__ == "__main__":
    main()

server.py

import time
import socket
from _thread import *


def listen(clientSocket, addr):
    while True:
        encodedMsg = clientSocket.recv(1024)
        decodedMsg = encodedMsg.decode('utf-8')
        currTime = time.strftime("%Y-%m-%d-%H.%M.%S", time.localtime())
    
        for client in clients:
            if addr != client:
                clientSocket.sendto(encodedMsg, client)

    print(f'[{currTime}] {decodedMsg}')


def main():
    serverAddress = (socket.gethostname(), 4444)
    global clients
    clients = []

    serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    serverSocket.bind(serverAddress)
    serverSocket.listen(2)

    while True:
        clientSocket, addr = serverSocket.accept()

        if addr not in clients:
            clients.append(addr)
            print(f'{addr} joined chat')

        start_new_thread(listen, (clientSocket, addr))


if __name__ == '__main__':
    main()

如果其套接字已连接,则sendto不会按预期工作。 它只是发送到连接的套接字,而不是指定的地址。

因此, listen需要能够访问每个客户端的打开套接字才能写入。

当前clients是地址列表,但您可以将其更改为地址字典到套接字映射:

def main():
    global clients
    clients = {}

然后当你得到一个新的客户端连接时,保存地址和套接字:

        clientSocket, addr = serverSocket.accept()

        if addr not in clients:
            clients[addr] = clientSocket
            print(f'{addr} joined chat')

        start_new_thread(listen, (clientSocket, addr))

最后,在侦听中,写入彼此客户端的套接字,而不是该listen线程的已连接clientSocket

        for client in clients:
            if addr != client:
                print(f"sending message from {addr} to {client}")
                clients[client].send(encodedMsg)

您的代码还有许多其他问题。

Sockets 不是线程安全的。 因此,如果 2 个客户端碰巧同时写相同的东西,就会出现竞争条件; 可以对写入进行插值,并且可以对消息进行处理。

如果客户端断开连接,则服务器无法很好地处理断开连接。 如果服务器断开连接,客户端 go 也会进入无限循环。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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