选择socket.send的收件人 - Python套接字模块

时间:2014-03-20 18:52:53

标签: python sockets chat

我正在尝试制作群聊项目,其中无限量的客户端可以使用相同的脚本加入服务器,它将由接收客户端消息的服务器工作并将其发送到所有连接的客户端,包括发送者。我只是设法使发送者只收回他自己的消息,而不是另一个客户发送的消息。

我在考虑将所有连接的客户端IP存储在一个列表中,然后将其发送到每个IP,但我不知道如何更改socket.send的rectient

服务器代码:

from threading import *
import socket

s = socket.socket()         
host = socket.gethostbyname(socket.gethostname())
port = 1337
s.bind((host, port))
s.listen(5)
print("Server host is", host)


def getMainThread():
    for thread in enumerate(): 
        if thread.name == 'MainThread':
            return thread
    return None


class client(Thread):
    def __init__(self, socket, address):
        Thread.__init__(self)
        self.socket = socket
        self.address = address
        self.start()


    def run(self):
        main = getMainThread()
        while main and main.isAlive():
            print(self.address, "has connected!")
            message = self.socket.recv(8192).decode('utf-8')
            self.socket.send(bytes(message, 'UTF-8'))

        self.socket.close()

while True:
    c, addr = s.accept()
    client(c, addr)
    clients = [] #list for all client IP's
    clients.append(addr)

此外,是否有一种方法可以让客户端与服务器建立连接,以便它不会一直弹出客户端每次发送消息时连接的server.py?

客户代码:

import socket
import os
import sys
host = '25.154.84.23'
print("""
=======================================================
=Welcome to Coder77's local internet messaging service=
=======================================================
The current soon to be encrypted server is {0}

You can enter the command /help for a list of commands available
""".format(host))
#username = input("Enter username: ")
username = 'Smile'
print("Now connecting to {0}....".format(host))


def printhelp():
    print("""
The following commands are in the current version of this program:
/clear to clear the screen
/username to change your username
/exit to exit
/help for a list of commands
""")


def main():
    global username
    global host
    sock = socket.socket()
    try:
        sock.connect((host, 1337))
        while True:
            message2 = input("{0}: ".format(username))
            message = ('{0}: {1}'.format(username,message2))

            if '/quit' in message:
                sys.exit()
            if '/clear' in message:
                os.system('cls')
            if '/help' in message:
                printhelp()
            if '/username' in message:
                username = input("What would you like as your new username? ")

            sock.send(bytes(message, 'UTF-8'))
            received = sock.recv(8192).decode('utf-8')
            print(received)
    except socket.error:
        print("Host is unreachable")

if __name__ == '__main__':
    main() 

已更正服务器代码:

import sys
print(sys.version)
from threading import *
import socket

s = socket.socket()         
host = socket.gethostbyname(socket.gethostname())
port = 1337
s.bind((host, port))
s.listen(5)
print("Server host is", host)


def getMainThread():
    for thread in enumerate():  # Imported from threading
        if thread.name == 'MainThread':
            return thread
    return None


class Client(Thread):
    def __init__(self, socket, address):
        Thread.__init__(self)
        self.socket = socket
        self.address = address
        self.start()

    def run(self):
            main = getMainThread()
            print(self.address, "has connected!")
            while main and main.isAlive():
                message = self.socket.recv(8192).decode('utf-8')
                print(message)
                self.socket.send(bytes(message, 'UTF-8'))
                for each_client in clients:
                    each_client.socket.send(bytes(message, 'UTF-8'))

while True:
    c, addr = s.accept()
    this_client = Client(c, addr)
    clients = []
    clients.append(this_client)

由gravetii改编的新代码导致了很多格式错误。现在发生的事情是,用户收回他发送的内容,他没有收回其他用户发送的内容,并且用户收回了他之前的消息,这非常令人困惑。请运行代码,你会发现它很难解释。

实施例 enter image description here

1 个答案:

答案 0 :(得分:1)

在您的服务器代码中,您只执行self.socket.send(bytes(message, 'UTF-8'))。那么你如何期望服务器将消息发送给所有客户端?为此,您需要遍历客户端列表并在每个套接字上调用send()方法。

while True:
    c, addr = s.accept()
    client(c, addr)
    clients = [] #list for all client IP's
    clients.append(addr)

在此代码中,您正在创建一个客户端对象,但从未将其添加到列表中,那么创建一个客户端对象的目的是什么? 我想你想要的是:

while True:
    c, addr = s.accept()
    this_client = client(c, addr)
    clients = [] #list for all client IP's
    clients.append(this_client)

然后,您可以通过修改服务器代码的相关部分将消息发送给所有客户端:

def run(self):
        main = getMainThread()
        while main and main.isAlive():
            print(self.address, "has connected!")
            message = self.socket.recv(8192).decode('utf-8')
            self.socket.send(bytes(message, 'UTF-8'))
            for each_client in clients:
                each_client.socket.send(bytes(message, 'UTF-8'))

另外,为什么在发送一条消息后关闭连接?我相信您的意图是向服务器发送多条消息,在这种情况下,您不需要关闭连接。

此外,创建一个名称以大写字母开头的类更好。因此,您可能希望使用Client代替client作为类名。

现在每当客户端在server.py中说出某些内容时,就会出现弹出消息的问题,请查看client线程的run()方法:

def run(self):
        main = getMainThread()
        while main and main.isAlive():
            print(self.address, "has connected!")
            message = self.socket.recv(8192).decode('utf-8')
            self.socket.send(bytes(message, 'UTF-8'))

一旦创建client对象,线程就会开始执行,因此第一次连接到服务器时,它就会显示该消息。但是将print(self.address, "has connected!")置于while循环中是不正确的。因此,每当客户端说出某些内容时,服务器会将其发送回客户端,然后循环再次运行,从而再次显示消息。您需要像这样修改它:

def run(self):
        print(self.address, "has connected!")
        main = getMainThread()
        while main and main.isAlive():
            message = self.socket.recv(8192).decode('utf-8')
            self.socket.send(bytes(message, 'UTF-8'))

希望这有帮助!

相关问题