【问题标题】:Send image over http python通过http python发送图像
【发布时间】:2020-03-07 10:25:32
【问题描述】:

我需要在不使用 HTTP 库的情况下构建一个 http 服务器。

我的服务器正在运行并加载了一个 html 页面,但我的 <img src="..."/> 标签没有加载,我收到了调用但无法在页面中预设 png/JPEG。

httpServer.py

​​>
# Define socket host and port
SERVER_HOST = '0.0.0.0'
SERVER_PORT = 8000

# Create socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((SERVER_HOST, SERVER_PORT))
server_socket.listen(1)
print('Listening on port %s ...' % SERVER_PORT)

while True:
    # Wait for client connections
    client_connection, client_address = server_socket.accept()

    # Handle client request
    request = client_connection.recv(1024).decode()
    content = handle_request(request)

    # Send HTTP response
    if content:
        response = 'HTTP/1.1 200 OK\n\n'
        response += content
    else:
        response = 'HTTP/1.1 404 NOT FOUND\n\nFile Not Found'

    client_connection.sendall(response.encode())
    client_connection.close()

# Close socket
server_socket.close()

处理调用的函数

 def handle_request(request):
    http = HttpHandler.HTTPHandler

    # Parse headers
    print(request)
    headers = request.split('\n')
    get_content = headers[0].split()

    accept = headers[6].split()
    type_content = accept[1].split('/')

    try:
        # Filename
        filename = get_content[1]

        if get_content[0] == "GET":
            content = http.get(None, get_content[1], type_content[0])


        return content
    except FileNotFoundError:
        return None

处理http动词的类

class HTTPHandler:

    def get(self, args, type):
        if args == '/':
            args = '/index.html'
            fin = open('htdocs' + args)
        if type != "image":
            fin = open('htdocs/' + args)

        if type == "image":
            fin = open('htdocs/' + args, 'rb')

        # Read file contents
        content = fin.read()
        fin.close()
        return content

意识到我正在尝试制作 HTTP 1.1,如果您发现任何不正常的地方,请提前说声谢谢。

【问题讨论】:

  • 你为什么不能使用http.server。你这样做是为了学习吗?如果是这样,也许您可​​以通过查看 http.server 模块的源代码或 Python 2 BaseHTTPServer 获得一些想法。
  • 也许我会失明,但我看不到该代码将标题行发送到浏览器的位置。
  • @PM2Ring 是的,我这样做是作为一个学习练习,你发送的链接,我可以返回一个字符串,这个代码没有问题,当页面加载时,如果我有<img> 标记浏览器再次调用资源,这就是问题出现的地方,我不知道如何发送图像
  • 为了响应浏览器的请求,您需要发送正确的标头以及二进制图像数据。 This answer 显示标题的样子。

标签: python sockets http tcp get


【解决方案1】:

我不知道您从哪里了解到 HTTP 的工作原理,但我很确定您没有学习 the actual standard,在实现协议时应该这样做。关于您的实施的一些注意事项:

  • 行尾应为\r\n 而不是\n。这对于来自服务器的响应和来自客户端的请求都是如此。
  • 您假设客户端请求永远不会大于 1024 字节,并且可以在单个 recv 中读取。但是,请求可以有任意长度,并且不能保证您在单个 recv 中得到所有请求(TCP 是流协议,而不是消息协议)。
  • 虽然可以在正文之后简单地关闭 TCP 连接,但最好在 Content-length 标头中包含正文的长度或使用分块传输编码。
  • 内容的类型应使用Content-Type 标头给出,即Content-type: text/html 用于HTML,Content-type: image/jpeg 用于JPEG 图像。如果没有这个浏览器可能会正确或错误地猜测类型可能是什么,或者根据上下文也可能坚持正确的内容类型标头。

除此之外,如果您调试此类问题,了解客户端和服务器之间实际交换的内容会很有帮助。可能是您自己检查了这一点,但您没有将此类信息包含在您的问题中。您唯一的错误描述是“...我收到了电话,但无法在页面中预设 png/JPEG”,然后转储您的代码。

【讨论】:

  • 感谢标准方面的帮助,问题是我将字节作为字符串(在连接中)而不是字节发送。
【解决方案2】:

httpServer.py

​​>

结果如下:

while True:
# Wait for client connections
client_connection, client_address = server_socket.accept()

# Handle client request
request = client_connection.recv(10240).decode()
content = handle_request(request)

# Send HTTP response
if content:
    if str(content).find("html") > 0:
        client_connection.send('HTTP/1.1 200 OK\n\n'.encode())
        client_connection.send(content.encode())
    else:
        client_connection.send('HTTP/1.1 200 OK\r\n'.encode())
        client_connection.send("Content-Type: image/jpeg\r\n".encode())
        client_connection.send("Accept-Ranges: bytes\r\n\r\n".encode())
        client_connection.send(content)
else:
    response = 'HTTP/1.1 404 NOT FOUND\r\nFile Not Found'

client_connection.close()

Get 方法如下:

class HTTPHandler:

def get(self, args, type):
    if args == '/':
        args = '/index.html'
        fin = open('htdocs' + args)
    if type != "image":
        fin = open('htdocs/' + args)

    if type.find("html") == -1:
        image_data = open('htdocs/' + args, 'rb')
        bytes = image_data.read()

        # Content-Type: image/jpeg, image/png \n\n
        content = bytes
        fin.close()
        return content

    # Read file contents
    content = fin.read()
    fin.close()
    return content

【讨论】:

  • IPS - CD 它说什么了吗?来自未来的感谢!
猜你喜欢
  • 2011-05-08
  • 1970-01-01
  • 2012-07-27
  • 2012-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-18
  • 1970-01-01
相关资源
最近更新 更多