繁体   English   中英

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

[英]How to get the IP address of a client on HTTP server based python?

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

我附上了服务器的完整代码,谢谢! 服务器是一个基于 Python 的 HTTP 服务器,我使用了 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()

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

new_client_socket, client_address = s.accept()

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

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

暂无
暂无

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

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