如何在 TCP Python 聊天服务器上拥有多个客户端?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26445331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:28:44  来源:igfitidea点击:

How can I have multiple clients on a TCP Python Chat Server?

pythontcppython-multithreading

提问by artman41

Any help on how I can get this to accept more than one client, and why it isn't at the moment? Thanks!

关于如何让这个接受多个客户的任何帮助,为什么现在不是?谢谢!

Also, is there anything I'm doing wrong with this code? I've been following mostly Python 2 tutorials because I can't find any for Python 3.4

另外,这段代码有什么问题吗?我一直在关注 Python 2 教程,因为我找不到任何适用于 Python 3.4 的教程

Here is my Server code:

这是我的服务器代码:

import socket
import time
import os
from threading import Thread

folderPath = "Chat Logs"
filePath = folderPath + "/" + str(time.strftime("%H-%M-%S_%d-%m-%Y")) + ".txt"

def clientHandler(c):          
    while True:
        data = c.recv(1024)
        if not data:
            break

    data = data.decode("UTF-8")

    message = str(data[:data.index("§")])
    nick = str(data[data.index("§")+1:])

        print(nick + ": " + message)
        saveChat(nick, message)
        print("   Sending: " + data)
        c.send(bytes(data, "UTF-8"))

    c.close()

def saveChat(nick, message):
    if not os.path.exists(folderPath):
        os.makedirs(folderPath)
    if not os.path.exists(filePath):
        f = open(filePath, "a")
        f.close()

    f = open(filePath, "a")
    f.write(nick + ": " + message + "\n")
    f.close()

def Main():
    host = str(socket.gethostbyname(socket.gethostname()))
    port = 5000

    print(host + ":" + str(port) + "\n")
    Clients = int(input("Clients: "))

    s = socket.socket()
    s.bind((host, port))
    s.listen(Clients)
    for i in range(Clients):
        c, addr = s.accept()
        print("Connection from: " + str(addr))

        Thread(target=clientHandler(c)).start()
    s.close()

if __name__ == "__main__":
    Main()

And here is my Client code:

这是我的客户端代码:

import socket

def Main():
    print("Send 'q' to exit\n")
    address = str(input("ip:port -> "))
    nick = input("nick: ")

    try:
        if address.index(":") != 0:
            host = address[:address.index(":")]
            port = int(address[address.index(":")+1:])
    except ValueError:
        host = address
        port = 5000

    s = socket.socket()
    s.connect((host, port))

    message = input("-> ")

    while message != "q":
        s.send(bytes(message + "??" + nick, "UTF-8"))
        data = s.recv(1024)
        data = data.decode("UTF-8")
        data2 = data

        messageServer = str(data[:data.index("??")])
        nickServer = str(data[data.index("??")+1:])
        if not data == data2:
            print(nickServer + ": " + messageServer)
        message = input("-> ")
    s.close()

if __name__ == "__main__":
    Main()

采纳答案by Totem

First of all, I found these tutorials very helpful: BinaryTides

首先,我发现这些教程非常有用:BinaryTides

Here is an example of a simple tcp server that accepts multiple clients. All this one does receive data from the client and return "OK .. " + the_data. However, you could easily modify it to have a function that broadcasts the data(chat msg) to all clients connected. This example uses threading. You should google for the selectmodule. With regards to your threads, are you sure you are a) using the right module/method for the job and b) that you are calling it in the right way?

这是一个接受多个客户端的简单 tcp 服务器的示例。所有这一切都会从客户端接收数据并返回“OK ..”+ the_data。但是,您可以轻松地将其修改为具有向所有连接的客户端广播数据(聊天消息)的功能。此示例使用线程。你应该谷歌搜索select模块。关于你的线程,你确定你 a) 使用正确的模块/方法来完成工作,b) 你以正确的方式调用它吗?

import socket
import sys
from thread import start_new_thread

HOST = '' # all availabe interfaces
PORT = 9999 # arbitrary non privileged port 

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    print("Could not create socket. Error Code: ", str(msg[0]), "Error: ", msg[1])
    sys.exit(0)

print("[-] Socket Created")

# bind socket
try:
    s.bind((HOST, PORT))
    print("[-] Socket Bound to port " + str(PORT))
except socket.error, msg:
    print("Bind Failed. Error Code: {} Error: {}".format(str(msg[0]), msg[1]))
    sys.exit()

s.listen(10)
print("Listening...")

# The code below is what you're looking for ############

def client_thread(conn):
    conn.send("Welcome to the Server. Type messages and press enter to send.\n")

    while True:
        data = conn.recv(1024)
        if not data:
            break
        reply = "OK . . " + data
        conn.sendall(reply)
    conn.close()

while True:
    # blocking call, waits to accept a connection
    conn, addr = s.accept()
    print("[-] Connected to " + addr[0] + ":" + str(addr[1]))

    start_new_thread(client_thread, (conn,))

s.close()

回答by PSkocik

Check out: http://etutorials.org/Programming/Python+tutorial/Part+IV+Network+and+Web+Programming/Chapter+19.+Sockets+and+Server-Side+Network+Protocol+Modules/19.3+Event-Driven+Socket+Programs/. Example 19-6is (the one with the selectsystem call) like a hello world of chat applications. You might also want to take a look at http://beej.us/guide/bgnet/output/html/multipage/index.htmlfor more lower level (C) insight system networking basics.

查看:http: //etutorials.org/Programming/Python+tutorial/Part+IV+Network+and+Web+Programming/Chapter+19.+Sockets+and+Server-Side+Network+Protocol+Modules/19.3+事件驱动+套接字+程序/。示例19-6(带有select系统调用的那个)就像聊天应用程序的 hello world。您可能还想查看http://beej.us/guide/bgnet/output/html/multipage/index.html以了解更多低级 (C) 洞察系统网络基础知识。