接受客户端连接时检测(无阻塞)按键

时间:2019-03-09 04:47:47

标签: python-3.x sockets ipc keypress nonblocking

我在python编程方面还很陌生。我正在尝试使用套接字编写某种形式的模拟代码。我能够将多个客户端成功连接到服务器。但是我希望服务器在等待某些输入(例如,从控制台/终端输入Enter键或字符串输入)时接受客户端连接。如果用户按下Enter键或输入该字符串,则服务器应停止接受客户端连接,并将连接的客户端列表发送给所有客户端。我知道如何对其余部分进行编码,但是我不知道在接受连接时在哪里可以检测到此按键。到目前为止,这就是我所拥有的。我曾尝试寻找类似的方法,但没有找到符合我需要的东西。

服务器文件:

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)

如果您能指导我如何使用此概念来检测服务器端的按键按下并停止接受客户端连接并调用该函数以将客户端列表发送给所有客户端,那将是很好的。或者,如果您有任何其他方法或建议。

0 个答案:

没有答案