def main(): global configuration global configuration_file global full_list_of_files global sharing_directory # logging configuration logging.basicConfig(level=logging.DEBUG, format="[%(levelname)s] (%(threadName)s) %(message)s", filename="client.log", filemode="w") console = logging.StreamHandler() if DEBUG: # set the console logging level to debug console.setLevel(logging.DEBUG) else: # set the console logging level to info console.setLevel(logging.INFO) formatter = logging.Formatter( "[%(levelname)s] (%(threadName)s) %(message)s") console.setFormatter(formatter) logging.getLogger("").addHandler(console) configuration_file = "configuration.json" if os.path.isfile(configuration_file): # load the configuration from the json file configuration = json_load(configuration_file) else: # create and initialize the configuration file configuration["server_host"] = "157.253.205.7" configuration["server_port"] = 8080 configuration["listening_ip"] = "localhost" configuration["listening_port"] = 0 configuration["sharing_directory"] = get_sharing_directory() json_save(configuration_file, configuration) logging.debug("configuration: " + str(configuration)) sharing_directory = configuration["sharing_directory"] files_list = [ file_ for file_ in os.listdir(sharing_directory) if os.path.isfile(os.path.join(sharing_directory, file_)) ] logging.debug("files_list: " + str(files_list)) server_address = (configuration["server_host"], configuration["server_port"]) server = connection_init(server_address) # start with an empty incoming message buffer incoming_buffer = "" # send HELLO command ############################################################################ if "username" in configuration: send_message(server, "HELLO " + configuration["username"] + "\n\0") else: send_message(server, "HELLO\n\0") unneeded, incoming_buffer = converse(server, incoming_buffer, "HELLO") # send LISTENING command ############################################################################ listening_ip = configuration["listening_ip"] listening_port = configuration["listening_port"] queue = Queue.Queue() # spawn listening thread listening_thread = Thread(name="ListeningThread", target=listen, args=(listening_ip, listening_port, queue)) # TODO # handle differently, terminate gracefully listening_thread.daemon = True listening_thread.start() listening_ip, listening_port = queue.get() listening_message = "LISTENING {} {}\n\0".format(listening_ip, listening_port) send_message(server, listening_message) converse(server, incoming_buffer, "LISTENING") # send LIST command ############################################################################ list_message = "LIST {}\n".format(len(files_list)) for file_ in files_list: list_message += file_ + "\n" list_message += "\0" send_message(server, list_message) converse(server, incoming_buffer, "LIST") # send SENDLIST command ############################################################################ send_message(server, "SENDLIST " + "\n\0") converse(server, incoming_buffer, "SENDLIST") # options menu/loop ############################################################################ while True: print() print("options:") print("1: SENDLIST : request the list of clients and shared files") print( "2: WHERE : request the IP address and port of the specified client" ) print("4: SHARE : specify the sharing directory") print("5: QUIT : exit the program") option = raw_input() if option in ["1", "sendlist", "SENDLIST"]: send_message(server, "SENDLIST " + "\n\0") converse(server, incoming_buffer, "SENDLIST") elif option in ["2", "where", "WHERE"]: print("Enter the username of the client:") while True: client = raw_input() if client == configuration["username"]: print("{} is you, try again: ".format(client)) continue if client in [pair.split()[0] for pair in full_list_of_files]: break print("{} is an invalid client username, try again: ".format( client)) send_message(server, "WHERE " + client + "\n\0") (peer_ip, peer_port), incoming_buffer = converse(server, incoming_buffer, "WHERE") peer = connection_init((peer_ip, peer_port)) give_me(peer) elif option in ["4", "share", "SHARE"]: configuration["sharing_directory"] = get_sharing_directory() json_save(configuration_file, configuration) elif option in ["5", "quit", "QUIT"]: sys.exit(0) else: print("invalid option, try again")
def converse(server, incoming_buffer, own_previous_command): """ main recursive function used for communication of the client with the server """ global configuration global full_list_of_files global requested_file # parse message if "\0" not in incoming_buffer: incoming_buffer += server.recv(4096) return converse(server, incoming_buffer, own_previous_command) else: index = incoming_buffer.index("\0") message = incoming_buffer[0:index - 1] incoming_buffer = incoming_buffer[index + 1:] logging.info("message received: " + message) lines = message.split("\n") fields = lines[0].split() command = fields[0] # protocol messages and answers if command == "AVAILABLE": username = fields[1] username = get_name(username) send_message(server, "IWANT " + username + "\n\0") return converse(server, incoming_buffer, "IWANT") elif command == "WELCOME": username = fields[1] configuration["username"] = username json_save(configuration_file, configuration) return None, incoming_buffer elif command == "FULLLIST" and own_previous_command == "SENDLIST": number_of_files = int(fields[1]) if number_of_files != (len(lines) - 1): logging.warning("invalid FULLLIST message, wrong number of files") send_message(server, "ERROR\n\0") sys.exit(-1) else: full_list_of_files = lines[1:] # cli_output print() print("full list of clients' files") for line in lines[1:]: print(line) return None, incoming_buffer elif command == "AT" and own_previous_command == "WHERE": peer_ip = fields[1] peer_port = int(fields[2]) return (peer_ip, peer_port), incoming_buffer elif command == "OK" and own_previous_command in ("LIST", "LISTENING"): return None, incoming_buffer elif command == "ERROR": logging.warning("ERROR message received, exiting") sys.exit(-1) else: # TODO # handle invalid commands logging.warning( 'an invalid command was received: "{}"'.format(command)) sys.exit(-1)
def converse(connection, client, incoming_buffer, own_previous_command): """ handle messages, uses recursion if there are more incoming commands """ global configuration_file global configuration global clients_file global clients global connected_clients if "\0" not in incoming_buffer: return "", own_previous_command else: index = incoming_buffer.index("\0") message = incoming_buffer[0:index-1] incoming_buffer = incoming_buffer[index+1:] # info message logging.info("message received: " + str(message)) # split message into lines to handle them easier lines = message.split("\n") fields = lines[0].split() command = fields[0] if command == "HELLO": # check if there is a username after the command if len(fields) == 1: configuration["username_offset"] += 1 json_save(configuration_file, configuration) # create available username for the new client username = "******".format(configuration["username_offset"]) # send answer to client and call converse recursively send_message(connection, "AVAILABLE " + username + "\n\0") return converse(connection, client, incoming_buffer, "AVAILABLE") else: username = fields[1] if username in clients: # tie the client connection tuple with its username connected_clients[client] = username logging.debug("connected_clients: " + str(connected_clients)) # send message WELCOME to client and call converse recursively send_message(connection, "WELCOME " + username + "\n\0") return converse(connection, client, incoming_buffer, "WELCOME") else: # otherwise send ERROR to client, don't need recursion here # because we don't wait for an incoming command from the client send_message(connection, "ERROR\n\0") return incoming_buffer, "ERROR" elif command == "IWANT": username = fields[1] # check if the username is valid if username in clients: configuration["username_offset"] += 1 json_save(configuration_file, configuration) username = "******".format(configuration["username_offset"]) # send answer to client and call converse recursively send_message(connection, "AVAILABLE " + username + "\n\0") return converse(connection, client, incoming_buffer, "AVAILABLE") else: clients[username] = {"files": [], "listening_ip": "", "listening_port": None} json_save(clients_file, clients) logging.debug("clients: " + str(clients)) connected_clients[client] = username logging.debug("connected_clients: " + str(connected_clients)) # send answer to client send_message(connection, "WELCOME " + username + "\n\0") return incoming_buffer, "WELCOME" elif command == "LISTENING": clients[connected_clients[client]]["listening_ip"] = fields[1] clients[connected_clients[client]]["listening_port"] = fields[2] json_save(clients_file, clients) logging.debug("clients: " + str(clients)) # send answer to client send_message(connection, "OK\n\0") return incoming_buffer, "OK" elif command == "LIST": number_of_files = int(fields[1]) if number_of_files != (len(lines) - 1): logging.warning("invalid LIST message, wrong number of files") send_message(connection, "ERROR\n\0") sys.exit(-1) else: clients[connected_clients[client]]["files"] = lines[1:] json_save(clients_file, clients) # send answer to client and call converse recursively send_message(connection, "OK\n\0") return incoming_buffer, "OK" elif command == "SENDLIST": number_of_all_clients_files = 0 for client_ in clients: number_of_all_clients_files += len(clients[client_]["files"]) fulllist_message = "FULLLIST {}\n".format(number_of_all_clients_files) for client_ in clients: for file_ in clients[client_]["files"]: fulllist_message += client_ + " " + file_ + "\n" fulllist_message += "\0" # sends list of clients and their files to the client that requested them send_message(connection, fulllist_message) return converse(connection, client, incoming_buffer, "FULLLIST") elif command == "WHERE": peer = fields[1] # search for the peer in the clients dictionary. # if valid, we sent to client the ip and port of the peer. if peer in clients: # get from dictionary ip and port peer_ip = clients[peer]["listening_ip"] peer_port = clients[peer]["listening_port"] # send message to client with ip and port of the client that # he wants to connect at_message = "AT {} {}\n\0".format(peer_ip, peer_port) send_message(connection, at_message) return incoming_buffer, "WHERE" else: send_message(connection, "UNKNOWN\n\0") return incoming_buffer, "UNKNOWN" elif command == "ERROR": logging.warning("ERROR message received, exiting") sys.exit(-1) else: # TODO # handle invalid commands logging.warning('an invalid command was received: "{}"'.format(command)) sys.exit(-1)
def main(): global configuration_file global configuration global clients_file global clients # logging configuration logging.basicConfig(level=logging.DEBUG, format="[%(levelname)s] (%(threadName)s) %(message)s", filename="server.log", filemode="w") console = logging.StreamHandler() if DEBUG: # set the console logging level to debug console.setLevel(logging.DEBUG) else: # set the console logging level to info console.setLevel(logging.INFO) formatter = logging.Formatter("[%(levelname)s] (%(threadName)s) %(message)s") console.setFormatter(formatter) logging.getLogger("").addHandler(console) configuration_file = "configuration.json" clients_file = "clients.json" if os.path.isfile(configuration_file): # load the configuration from the json file configuration = json_load(configuration_file) else: # create and initialize the configuration file configuration["host"] = "localhost" configuration["port"] = 45000 configuration["username_offset"] = 0 json_save(configuration_file, configuration) logging.debug("configuration: " + str(configuration)) # load the list of known clients from the json file if os.path.isfile(clients_file): clients = json_load(clients_file) else: json_save(clients_file, clients) logging.debug("clients: " + str(clients)) # create socket for connection try: server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error: logging.error("socket.socket error") sys.exit(-1) host = configuration["host"] port = configuration["port"] # bind socket try: server_socket.bind( (host, port) ) except socket.error: # cli_output logging.error("port {} in use, exiting".format(port)) sys.exit(-1) # listen for incoming connections server_socket.listen(5) # cli_output # output message logging.info("server listening on {}:{}".format(host, str(port))) # handle incoming client connections client_counter = 0 while True: connection, address = server_socket.accept() # cli_output # output message logging.info("a client connected from {}:{}".format(address[0], str(address[1]))) # create a thread that runs the client_function client_thread = Thread(name="client {}".format(client_counter), target=client_function, args=(connection, address)) # TODO # handle differently, terminate gracefully client_thread.daemon = True client_thread.start() client_counter += 1
def main(): global configuration global configuration_file global full_list_of_files global sharing_directory # logging configuration logging.basicConfig(level=logging.DEBUG, format="[%(levelname)s] (%(threadName)s) %(message)s", filename="client.log", filemode="w") console = logging.StreamHandler() if DEBUG: # set the console logging level to debug console.setLevel(logging.DEBUG) else: # set the console logging level to info console.setLevel(logging.INFO) formatter = logging.Formatter("[%(levelname)s] (%(threadName)s) %(message)s") console.setFormatter(formatter) logging.getLogger("").addHandler(console) configuration_file = "configuration.json" if os.path.isfile(configuration_file): # load the configuration from the json file configuration = json_load(configuration_file) else: # create and initialize the configuration file configuration["server_host"] = "localhost" configuration["server_port"] = 45000 configuration["listening_ip"] = "localhost" configuration["listening_port"] = 0 configuration["sharing_directory"] = get_sharing_directory() json_save(configuration_file, configuration) logging.debug("configuration: " + str(configuration)) sharing_directory = configuration["sharing_directory"] files_list = [ file_ for file_ in os.listdir(sharing_directory) if os.path.isfile(os.path.join(sharing_directory, file_)) ] logging.debug("files_list: " + str(files_list)) server_address = (configuration["server_host"], configuration["server_port"]) server = connection_init(server_address) # start with an empty incoming message buffer incoming_buffer = "" # send HELLO command ############################################################################ if "username" in configuration: send_message(server, "HELLO " + configuration["username"] + "\n\0") else: send_message(server, "HELLO\n\0") unneeded, incoming_buffer = converse(server, incoming_buffer, "HELLO") # send LISTENING command ############################################################################ listening_ip = configuration["listening_ip"] listening_port = configuration["listening_port"] queue = Queue.Queue() # spawn listening thread listening_thread = Thread(name="ListeningThread", target=listen, args=(listening_ip, listening_port, queue)) # TODO # handle differently, terminate gracefully listening_thread.daemon = True listening_thread.start() listening_ip, listening_port = queue.get() listening_message = "LISTENING {} {}\n\0".format(listening_ip, listening_port) send_message(server, listening_message) converse(server, incoming_buffer, "LISTENING") # send LIST command ############################################################################ list_message = "LIST {}\n".format(len(files_list)) for file_ in files_list: list_message += file_ + "\n" list_message += "\0" send_message(server, list_message) converse(server, incoming_buffer, "LIST") # send SENDLIST command ############################################################################ send_message(server, "SENDLIST " + "\n\0") converse(server, incoming_buffer, "SENDLIST") # options menu/loop ############################################################################ while True: print() print("options:") print("1: SENDLIST : request the list of clients and shared files") print("2: WHERE : request the IP address and port of the specified client") print("4: SHARE : specify the sharing directory") print("5: QUIT : exit the program") option = raw_input() if option in ["1", "sendlist", "SENDLIST"]: send_message(server, "SENDLIST " + "\n\0") converse(server, incoming_buffer, "SENDLIST") elif option in ["2", "where", "WHERE"]: print("Enter the username of the client:") while True: client = raw_input() if client == configuration["username"]: print("{} is you, try again: ".format(client)) continue if client in [pair.split()[0] for pair in full_list_of_files]: break print("{} is an invalid client username, try again: ".format(client)) send_message(server, "WHERE " + client + "\n\0") (peer_ip, peer_port), incoming_buffer = converse(server, incoming_buffer, "WHERE") peer = connection_init( (peer_ip, peer_port) ) give_me(peer) elif option in ["4", "share", "SHARE"]: configuration["sharing_directory"] = get_sharing_directory() json_save(configuration_file, configuration) elif option in ["5", "quit", "QUIT"]: sys.exit(0) else: print("invalid option, try again")
def converse(server, incoming_buffer, own_previous_command): """ main recursive function used for communication of the client with the server """ global configuration global full_list_of_files global requested_file # parse message if "\0" not in incoming_buffer: incoming_buffer += server.recv(4096) return converse(server, incoming_buffer, own_previous_command) else: index = incoming_buffer.index("\0") message = incoming_buffer[0:index-1] incoming_buffer = incoming_buffer[index+1:] logging.info("message received: " + message) lines = message.split("\n") fields = lines[0].split() command = fields[0] # protocol messages and answers if command == "AVAILABLE": username = fields[1] username = get_name(username) send_message(server, "IWANT " + username + "\n\0") return converse(server, incoming_buffer, "IWANT") elif command == "WELCOME": username = fields[1] configuration["username"] = username json_save(configuration_file, configuration) return None, incoming_buffer elif command == "FULLLIST" and own_previous_command == "SENDLIST": number_of_files = int(fields[1]) if number_of_files != (len(lines) - 1): logging.warning("invalid FULLLIST message, wrong number of files") send_message(server, "ERROR\n\0") sys.exit(-1) else: full_list_of_files = lines[1:] # cli_output print() print("full list of clients' files") for line in lines[1:]: print(line) return None, incoming_buffer elif command == "AT" and own_previous_command =="WHERE": peer_ip = fields[1] peer_port = int(fields[2]) return (peer_ip, peer_port), incoming_buffer elif command == "OK" and own_previous_command in ("LIST", "LISTENING"): return None, incoming_buffer elif command == "ERROR": logging.warning("ERROR message received, exiting") sys.exit(-1) else: # TODO # handle invalid commands logging.warning('an invalid command was received: "{}"'.format(command)) sys.exit(-1)
def main(): global configuration_file global configuration global clients_file global clients # basicConfig函数用来配置RootLogger # 支持六个关键字参数,分别为filename,filemode,stream,format,datefmt,level logging.basicConfig(level=logging.DEBUG, format="[%(levelname)s] (%(threadName)s) %(message)s", filename="server.log", filemode="w") # 创建一个handler,用于输出到控制台 console = logging.StreamHandler() if DEBUG: # 指定console被处理的信息级别为DEBUG,低于DEBUG级别的信息将被忽略 console.setLevel(logging.DEBUG) else: # 指定console被处理的信息级别为INFO,低于INFO级别的信息将被忽略 console.setLevel(logging.INFO) # 定义handler的输出格式 formatter = logging.Formatter("[%(levelname)s] (%(threadName)s) %(message)s") console.setFormatter(formatter) # 定义RootLogger,给RootLogger添加handler logging.getLogger("").addHandler(console) configuration_file = "configuration.json" clients_file = "clients.json" if os.path.isfile(configuration_file): # 从json文件中读入配置,并将其解码 configuration = json_load(configuration_file) else: # 创建并初始化配置文件,将字典解码格式化保存到配置文件中 configuration["host"] = "localhost" configuration["port"] = 45000 configuration["username_offset"] = 0 json_save(configuration_file, configuration) logging.debug("configuration: " + str(configuration)) # load the list of known clients from the json file if os.path.isfile(clients_file): clients = json_load(clients_file) else: json_save(clients_file, clients) logging.debug("clients: " + str(clients)) # 创建socket try: server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error: logging.error("socket.socket error") sys.exit(-1) host = configuration["host"] port = configuration["port"] # 绑定socket try: server_socket.bind( (host, port) ) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) except socket.error: # cli_output logging.error("port {} in use, exiting".format(port)) sys.exit(-1) # 开启监听,监听接入连接的主机 server_socket.listen(5) # 控制台输出 # 输出消息 logging.info("server listening on {}:{}".format(host, str(port))) # 对连接到服务器的主机进行下一步的处理 client_counter = 0 while True: connection, address = server_socket.accept() # cli_output # output message logging.info("a client connected from {}:{}".format(address[0], str(address[1]))) # create a thread that runs the client_function # 设置实现的线程函数的名字,格式为client 1,client 2,...default:Thread-1,Thread-2 client_thread = Thread(name="client {}".format(client_counter), target=client_function, args=(connection, address)) # TODO # 设置daemon模式,即使主程序结束,这个子线程依然存在 # handle differently, terminate gracefully client_thread.daemon = True client_thread.start() client_counter += 1