如何在基于HTTP服务器的python上获取客户端的IP地址?

问题描述 投票:-1回答:1

我构建了一个简单的基于HTTP服务器的python,我想在控制台上打印每个客户端的IP(在这一行 - 打印(“客户端的IP地址”+ IP))。你能帮帮我吗?

我附上了服务器的完整代码,谢谢!服务器是基于HTTP服务器的Python,我使用select和socket。需要客户端IP地址的原因是创建用户IP的字典。谢谢!

import select, socket, queue, os
DEFAULT_URL = r'/signup.html'
ERROR_404_URL = r'/errors/404.html'
ROOT_PATH = r'/web'
REDIRECTION_LIST = [r"/index.html", r"/index.htm", r"index.html"]
IP = "0.0.0.0"
PORT = 12345
IMAGE_TYPES = ["png", "jpg", "bmp", "gif", "jpeg"]
SERVER_STATUS = {"OK": 200, "Redirect": 302, "Not Found": 404}
BUFFER_LENGTH = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# server.setblocking(0)
server.bind((IP, PORT))
server.listen(5)
inputs = [server]
outputs = [] #requests
message_queues = {}
users ={}

def get_file_data(file_path):
    """ Get and return data from file in :param file_path"""
    try:
        file_handler = open(file_path, 'rb')
        # read file content
        response_content = file_handler.read()

        file_handler.close()
        return response_content

    except Exception:
        print ("Warning, file not found. Serving response code 404\n")
        print("file path    "+file_path)
        print("Done")

    return None


def get_file_info(client_request):
    """ Get  absolute response file path and response file type by parsing :param client_request"""
    str_array = client_request.split(" ")
    file_path_parameters = str_array[1]
    strings = file_path_parameters.split("?")

    if '?' in file_path_parameters:
        get_req = strings[1]
        get_request = get_req.split("=")
        print("get_request   "+get_request[0])
        print("ip of the client "+IP) # HERE it should print the 
        #client IP



   # print("string "+ strings[1])
    file_path =strings[0]
    print("file path " + file_path)
    if file_path == r"/":
        file_path = DEFAULT_URL

    print("file path "+ file_path)
    file_type = file_path.split(".")[1]

    abs_file_path = ROOT_PATH + file_path  # "/test.html"
    print(abs_file_path)
    return abs_file_path, file_type


def header(url, file_type):
    ######################################
    # headers
    ######################################
    headers = ""
    http_version = "HTTP/1.1 200 OK"
    content_length = str(os.path.getsize(url))
    content_type = file_type
    if content_type == "html":
        headers = 'HTTP/1.1 200 OK' + '\nContent-Type: text/html; charset=utf-8 \nContent-Length: ' + str(content_length) + '\n\n'
    elif content_type == "css":
        headers = 'HTTP/1.1 200 OK\nContent-Type: text/css \nContent-Length: ' + str(content_length) + '\n\n'

    elif content_type == "js":
        headers = 'HTTP/1.1 200 OK' +'\nContent-Type: text/javascript; charset=utf-8 \nContent-Length: ' + str(content_length) + '\n\n'
    elif file_type in IMAGE_TYPES:
        headers = 'HTTP/1.1 200 OK\nContent-Type: image/xyz \nContent-Length: ' + content_length + '\n\n'
    else:
        headers = 'HTTP/1.1 200 OK\nContent-Type: ' + content_type + '\nContent-Length: ' + str(content_length) + '\n\n'
    return headers.encode()



    # further headers
    # current_date = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
    # response_header += 'Date: ' + current_date + '\n'
    # Important: "\n" twice  - because html page body
    # starts with first empty line
    # response_header += 'Server: Allam-HTTP-Server\n\n'
    # signal that the connection will be closed
    # after completing the request
    response_header += 'Connection: close\n\n'

    print("response_header = ", response_header)

    return response_header.encode() + file_data


def main():
    """ Main loop for connect, read and write to/from sockets"""
    while inputs:
        readable, writable, exceptional = select.select(
            inputs, outputs, inputs+outputs, 1)
        for s in readable:
            if s is server: #אם זה של הסרבר
                new_client_socket, client_address = s.accept()
                print("accepted")
                # new_client_socket.setblocking(0)
                inputs.append(new_client_socket)
                message_queues[new_client_socket] = queue.Queue()
            else:
                data = s.recv(1024)
                if data: #המחרוזת לא ריקה
                    message_queues[s].put(data)
                    if s not in outputs:
                        outputs.append(s)
                else: # אם זה ריק כלומר להתנתק צריך להשמיד
                    if s in outputs:
                        outputs.remove(s)
                    inputs.remove(s)
                    s.close()
                    del message_queues[s]

        for s in writable:
            try:
                next_msg = message_queues[s].get_nowait()
            except queue.Empty:
                outputs.remove(s)
            else:
                file_path, file_type = get_file_info(next_msg.decode())
                file_data = get_file_data(file_path)
#                file_size = len(file_data)  # another way: num_of_bytes = os.stat(file_path).st_size
                http_response = header(file_path, file_type)+file_data
                s.send(http_response)

        for s in exceptional:
            inputs.remove(s)
            if s in outputs:
                outputs.remove(s)
            s.close()
            del message_queues[s]


if __name__ == '__main__':

    main()
python python-3.7 httpserver
1个回答
0
投票

您从s.accept()获得客户端地址 - 它是IP地址(str)和端口(int)的元组。您的代码根本不使用此变量,只关心套接字。

new_client_socket, client_address = s.accept()

您只将客户端请求字符串传递给get_file_info,因此它不知道它当前正在服务的客户端。保存客户端地址,也许在dict映射套接字到这样的元组?

更多信息:https://docs.python.org/3/library/socket.html#socket.socket.accept

© www.soinside.com 2019 - 2024. All rights reserved.