Обнаружить (неблокирующее) нажатие клавиши при принятии клиентских подключений - PullRequest
1 голос
/ 09 марта 2019

Я довольно новичок в программировании на python.Я пытаюсь кодировать какую-то форму симуляции, используя сокеты.Я могу успешно подключить несколько клиентов к серверу.Однако я хотел бы, чтобы сервер принимал клиентские соединения, ожидая некоторого ввода (скажем, клавиши ввода или ввода строки из консоли / терминала).Если пользователь нажимает клавишу ввода или вводит эту строку, то сервер должен прекратить принимать клиентские соединения и отправить список подключенных клиентов всем клиентам.Я знаю, как кодировать оставшуюся часть, но я не знаю, где обнаружить нажатие этой клавиши при принятии соединений.Это то, что я до сих пор.Я пытался найти похожие подходы, но не нашел того, что соответствует моим потребностям.

Файл сервера:

import socket, sys, traceback, json, pygame, curses, time
from threading import Thread
clientList = {}

def initialize():
    serverConnect()

def serverConnect():
    local_hostname = socket.gethostname()
    host = socket.gethostbyname(local_hostname)
    port = 6666
    sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sockfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        sockfd.bind((host, port))
    except:
        print("Bind failed. Error : " + str(sys.exc_info()))
        sys.exit()
    sockfd.listen(3)
    cid = 0
    # infinite loop - do not reset for every requests
    while True:
        print("Awaiting client connection...")
        clientSocket, address = sockfd.accept()
        cid += 1
        add_client_to_list(cid, address)
        ip = str(address[0])
        port = str(address[1])
        print("Connected with " + ip + ":" + port)
        try:
            Thread(target=client_thread, args=(clientSocket, ip, port, cid, address)).start()
        except:
            print("Thread did not start.")
            traceback.print_exc() 
    sockfd.close()

def client_thread(clientSocket, ip, port, cid, address, BUFSIZE = 5120):
    clientAddress = address
    clientID = cid
    print("Sending client ID " + str(clientID) + " to " + ip + ":" + port)
    clientSocket.sendall(str(clientID).encode("utf-8"))
    threadActive = True
    while threadActive:
        recdData = receive_input(clientSocket, BUFSIZE)
        if "--QUIT--" in recdData:
            print("Client is requesting to quit")
            clientSocket.close()
            print("Connection " + ip + ":" + port + " closed")
            threadActive = False
        else:
            print("\nReceived: {}".format(recdData) + " from %d" %clientID)
            clientSocket.sendall("-".encode("utf8"))

def receive_input(clientSocket, BUFSIZE):
    recdData = clientSocket.recv(BUFSIZE)
    recdDataSize = sys.getsizeof(recdData)
    if recdDataSize > BUFSIZE:
        print("The input size is greater than expected {}".format(recdDataSize))
    decodedData = recdData.decode("utf8").rstrip()  # decode and strip end of line
    result = process_input(decodedData)
    return result

def process_input(input_str):
    return str(input_str).upper()

def add_client_to_list(client_ID, client_address):
    clientList[client_ID] = client_address
    print(clientList)

def send_client_list(clientSocket, clientList):
    jsonList = json.dumps(clientList)
    clientSocket.sendall(str(jsonList).encode("utf-8"))

def keyPress(stdscr):
    """checking for keypress"""
    stdscr.nodelay(True)  # do not wait for input when calling getch
    return stdscr.getch()

if __name__ == "__main__":
    initialize()

Файл клиента:

import socket
import sys
import json

def initialize():
    sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = socket.gethostname()
    port = 6666    
    try:
        sockfd.connect((host, port))
    except:
        print("Connection error")
        sys.exit()        

    # Receiving server assigned client ID
    try:
        myID = sockfd.recv(1024).decode("utf-8")
        print("Received ID: " + myID + " from server.")
    except:
        print("Could not receive my ID from server")
        sys.exit()    

    print("Enter 'quit' to exit and 'list' to receive client List")
    message = input(" -> ")
    while True:
        if message == "list":
            print("Receiving clientList from server...")
            try:
                jsonList = sockfd.recv(8192).decode("utf-8")
                clientList = json.loads(jsonList)
                print("Received list: %s" % clientList)
            except:
                print("Could not receive list from server")
                sys.exit()
        elif message != 'quit':
            sockfd.sendall(message.encode("utf8"))
            if sockfd.recv(5120).decode("utf8") == "-":
                pass

            message = input(" -> ")
        else:
            sockfd.send(b'--quit--')
            break;

if __name__ == "__main__":
    initialize()

Это то, что я нашел.Это небольшой скрипт, который определяет, вводит ли пользователь {a} в консоль.И если он делает, то сообщение печатается.В противном случае он продолжает прослушивать нажатия клавиш.

import curses, time
def keyPress(stdscr):
    # checking for keypress
    stdscr.nodelay(True)  # do not wait for input when calling getch
    return stdscr.getch()
while True:
    if curses.wrapper(keyPress) == 97:    
        print("You pressed 'a'")
    else:
        pass
    time.sleep(0.1)

Было бы здорово, если бы вы могли подсказать мне, как я могу использовать эту концепцию для обнаружения нажатия клавиш на стороне сервера и прекращения приема клиентских подключений и вызова функции дляотправить список клиентов всем клиентам.Или если у вас есть другие подходы или предложения.

...