简体   繁体   English

有没有办法在多线程 TCP 服务器中向特定客户端发送消息?

[英]Is there a way to send message to a specific client in a multithreaded TCP server?

I have made a tcp multithread server which is always listening to new connections and at the same time handling existing clients.我制作了一个 tcp 多线程服务器,它始终在监听新连接并同时处理现有客户端。 If i have 2 clients, lets say A and B. Is there a way to send a message from the server to a specific client either A or B only?如果我有 2 个客户端,假设 A 和 B。有没有办法将消息从服​​务器发送到特定客户端,仅 A 或 B? Here is my code这是我的代码

import socket
import threading

HEADER = 80
PORT = 9000
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
VITA_POSITIVE = "0000"

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)


def handle_client(conn, addr):
    print(f"[NEW CONNECTION] {addr} connected.")
    connected = True
    while connected:
        conn.send("VITA".encode(FORMAT))
        vita_response_iconet = conn.recv(HEADER).decode(FORMAT)
        print(vita_response_iconet)
        if vita_response_iconet == VITA_POSITIVE:
                print("VITA received from Iconet")
        else:
                print("VITA not received from Iconet")

    conn.close()


def start():
    server.listen()
    print(f"[LISTENING] Server is listening on {SERVER}")
    while True:
        conn, addr = server.accept()
        print(conn)
        print(addr)
        thread = threading.Thread(target=handle_client, args=(conn, addr))
        thread.start()
        print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")


print("[STARTING] server is starting...")
start()

here is the modified code where i have put in the ip address of the clients and trying to run but i am encountering key error issues这是修改后的代码,我在其中输入了客户端的 IP 地址并尝试运行,但我遇到了关键错误问题

import socket, threading
import time



HEADER = 80
PORT = 9000
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
VITA_POSITIVE = "0000"
my_timer = 0




class ClientThread(threading.Thread):

def __init__(self, conn: socket.socket, addr: str):
    threading.Thread.__init__(self)
    
    self.conn = conn
    self.addr = addr

def send(self, msg: str):
    self.conn.sendall(msg.encode())

def run(self):
    print(f"[NEW CONNECTION] {self.addr} connected.")
    connected = True
    while connected:
        clients["10.14.0.1"].send("VITA".encode(FORMAT))
        vita_response_iconet = clients["10.14.0.1"].recv(HEADER).decode(FORMAT) 
        
        print(vita_response_iconet)
        if vita_response_iconet == VITA_POSITIVE:

                print("VITA received from Iconet")
                vita_iconet = 1  
        
        else:
                print("VITA not received from Iconet")
                vita_iconet = 0
        
        clients["10.14.0.1"].send("VITA".encode(FORMAT))
        vita_response_robot = clients["10.14.0.1"].recv(HEADER).decode(FORMAT)

        print(vita_response_robot)
        if vita_response_iconet == VITA_POSITIVE:

                print("VITA received from Robot") 
                vita_robot = 1
        
        else:
                print("VITA not received from Robot")
                vita_robot = 0


    if vita_iconet and vita_robot == 1:
        my_timer = 0
    else:
          my_timer = my_timer
    


    


        

    self.conn.close()
    


def countup():
global my_timer  
for x in range(1, my_timer+1):
time.sleep(1)
countup_thread = threading.Thread(target=countup)
countup_thread.start()


def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
    conn, addr = server.accept()
    print('interesting')
    print(conn)
    print(addr)
    thread = ClientThread(conn, addr)
    print ('be ready')
    thread.start()
    clients[addr] = thread
    print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 2}")





server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
clients = {}

connections = threading.Thread(target=start)
connections.start()

print("[STARTING] server is starting...")
start()

You can do this by creating a class for clients, like this您可以通过为客户创建一个类来做到这一点,就像这样

import socket, threading



HEADER = 80
PORT = 9000
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
VITA_POSITIVE = "0000"



class ClientThread(threading.Thread):

    def __init__(self, conn: socket.socket, addr: str):
        threading.Thread.__init__(self)
        
        self.conn = conn
        self.addr = addr

    def send(self, msg: str):
        self.conn.sendall(msg.encode())

    def run(self):
        print(f"[NEW CONNECTION] {self.addr} connected.")
        connected = True
        while connected:
            self.conn.send("VITA".encode(FORMAT))
            vita_response_iconet = self.conn.recv(HEADER).decode(FORMAT)
            print(vita_response_iconet)
            if vita_response_iconet == VITA_POSITIVE:

                    print("VITA received from Iconet") 
            
            else:
                    print("VITA not received from Iconet")

            

        self.conn.close()



def start():
    server.listen()
    print(f"[LISTENING] Server is listening on {SERVER}")
    while True:
        conn, addr = server.accept()
        print(conn)
        print(addr)
        thread = ClientThread(conn, addr)
        thread.start()
        clients[addr] = thread
        print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")





server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
clients = {}

print("[STARTING] server is starting...")
start()

Now, you can use clients[client_address].send(data_you_want_to_send) to send a message to only this client现在,您可以使用clients[client_address].send(data_you_want_to_send)仅向该客户端发送消息

EDIT This code technically allows you to send a message to a specific client but does not leave too many places to do so.编辑此代码在技术上允许您向特定客户发送消息,但不会留下太多地方这样做。 To solve this problem, you can put the task of accepting connections in a threading.Thread like this为了解决这个问题,你可以把接受连接的任务放在一个threading.Thread中,像这样

import socket, threading, time



HEADER = 80
PORT = 9000
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
VITA_POSITIVE = "0000"



class ClientThread(threading.Thread):

    def __init__(self, conn: socket.socket, addr: str):
        threading.Thread.__init__(self)

        self.conn = conn
        self.addr = addr

    def send(self, msg: str):
        self.conn.sendall(msg.encode())

    def run(self):
        print(f"[NEW CONNECTION] {self.addr} connected.")
        connected = True
        while connected:
            self.conn.send("VITA".encode(FORMAT))
            vita_response_iconet = self.conn.recv(HEADER).decode(FORMAT)
            print(vita_response_iconet)
            if vita_response_iconet == VITA_POSITIVE:

                    print("VITA received from Iconet") 

            else:
                    print("VITA not received from Iconet")



        self.conn.close()



def start():
    server.listen()
    print(f"[LISTENING] Server is listening on {SERVER}")
    while True:
        conn, addr = server.accept()
        print(conn)
        print(addr)
        thread = ClientThread(conn, addr)
        thread.start()
        clients[addr] = thread
        print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")





server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
clients = {}

connections = threading.Thread(target=start)
connections.start()

print("[STARTING] server is starting...")
time.sleep(0.5)

while True:
    client = input("Client you want to send a message : ") # Enter the address of the client you want to send a message
    
    if client not in clients.keys():
        print("This client is not connected")
        continue

    message = input("Message you want to send : ")

    clients[client].send(message)

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

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