如何判断一个Http Message的结束——python源码解读


HTTP/1.1 默认的连接方式是长连接,不能通过简单的TCP连接关闭判断HttpMessage的结束。

以下是几种判断HttpMessage结束的方式:

 

1.      HTTP协议约定status code 为1xx,204,304的应答消息不能包含消息体(Message Body), 直接忽略掉消息实体内容。

        [适用于应答消息]

        Http Message =Http Header

2.      如果请求消息的Method为HEAD,则直接忽略其消息体。[适用于请求消息]

         Http Message =Http Header

3.      如果Http消息头部有“Transfer-Encoding:chunked”,则通过chunk size判断长度。

4.      如果Http消息头部有Content-Length且没有Transfer-Encoding(如果同时有Content-Length和Transfer-Encoding,则忽略Content-Length),

         则通过Content-Length判断消息体长度。

5.      如果采用短连接(Http Message头部Connection:close),则直接可以通过服务器关闭连接来确定消息的传输长度。

         [适用于应答消息,Http请求消息不能以这种方式确定长度]

6.      还可以通过接收消息超时判断,但是不可靠。Python Proxy实现的http代理服务器用到了超时机制,源码地址见References[7],仅100多行。


HTTP协议规范RFC 2616的4.4 Message Length中对相关内容有较多的描述(https://tools.ietf.org/html/rfc2616#section-4.4)。

                              

一个实例,Python标准库httplib.py源码解读(http协议客户端的实现)

httplib最简单的使用方法:

import httplib
conn = httplib.HTTPConnection("google.com")
conn.request('GET', '/')
print conn.getresponse().read()
conn.close()

但是一般不直接使用httplib,而是使用更高层的封装urllib,urllib2

conn = httplib.HTTPConnection("google.com")创建HTTPConnection对象,指定要请求的webserver.

conn.request('GET''/')google.com发送http请求,MethodGET

conn.getresponse()创建HTTPResponse对象,接收并读取http应答消息头,read()读取应答消息体。


函数调用关系:

       getresponse()->[创建HTTPResponse对象response]-> response.begin()->response.read()


重点是begin()read()begin()完成了4件事:

       (1)创建HTTPMess

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的Python GUI聊天室的完整源码,基于Tkinter库实现: ```python import tkinter as tk from tkinter import scrolledtext, messagebox import socket import threading class ChatRoomGUI: def __init__(self, master): self.master = master self.master.title("Chat Room") self.master.resizable(0, 0) self.create_widgets() def create_widgets(self): self.label_ip = tk.Label(self.master, text="Server IP:") self.label_ip.grid(row=0, column=0, padx=(10, 0), pady=(10, 5)) self.entry_ip = tk.Entry(self.master) self.entry_ip.insert(tk.END, "127.0.0.1") self.entry_ip.grid(row=0, column=1, padx=(0, 10), pady=(10, 5)) self.label_port = tk.Label(self.master, text="Port:") self.label_port.grid(row=1, column=0, padx=(10, 0), pady=5) self.entry_port = tk.Entry(self.master) self.entry_port.insert(tk.END, "55555") self.entry_port.grid(row=1, column=1, padx=(0, 10), pady=5) self.button_connect = tk.Button(self.master, text="Connect", command=self.connect) self.button_connect.grid(row=0, column=2, rowspan=2, padx=10, pady=5) self.label_username = tk.Label(self.master, text="Username:") self.label_username.grid(row=2, column=0, padx=(10, 0), pady=(10, 5)) self.entry_username = tk.Entry(self.master) self.entry_username.grid(row=2, column=1, columnspan=2, padx=(0, 10), pady=(10, 5)) self.text_chat = scrolledtext.ScrolledText(self.master, state=tk.DISABLED) self.text_chat.grid(row=3, column=0, columnspan=3, padx=10, pady=5) self.entry_message = tk.Entry(self.master) self.entry_message.bind("<Return>", self.send) self.entry_message.grid(row=4, column=0, columnspan=2, padx=(10, 0), pady=(5, 10)) self.button_send = tk.Button(self.master, text="Send", command=self.send) self.button_send.grid(row=4, column=2, padx=(0, 10), pady=(5, 10)) def connect(self): try: self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_socket.connect((self.entry_ip.get(), int(self.entry_port.get()))) self.client_socket.send(self.entry_username.get().encode()) self.master.title("Chat Room - " + self.entry_username.get()) self.text_chat.config(state=tk.NORMAL) self.text_chat.insert(tk.END, "Connected to server.\n") self.text_chat.config(state=tk.DISABLED) self.thread_receive = threading.Thread(target=self.receive) self.thread_receive.start() except ConnectionRefusedError: messagebox.showerror("Error", "Connection refused. Server is not running.") except OSError: messagebox.showerror("Error", "Invalid IP or port.") def send(self, event=None): message = self.entry_message.get() if message: self.client_socket.send(message.encode()) self.entry_message.delete(0, tk.END) def receive(self): while True: try: message = self.client_socket.recv(1024).decode() if message == "USERNAME": self.client_socket.send(self.entry_username.get().encode()) else: self.text_chat.config(state=tk.NORMAL) self.text_chat.insert(tk.END, message + "\n") self.text_chat.config(state=tk.DISABLED) self.text_chat.yview(tk.END) except OSError: break self.client_socket.close() self.master.title("Chat Room - Disconnected") if __name__ == "__main__": root = tk.Tk() app = ChatRoomGUI(root) root.mainloop() ``` 这个聊天室使用了Python的socket和threading模块,以及Tkinter库来创建GUI界面。用户需要输入服务器的IP地址和端口号,以及自己的用户名,然后点击“Connect”按钮连接到服务器。连接成功后,用户可以在文本框中输入消息并按回车或点击“Send”按钮发送消息。接收到消息后,程序会将其显示在聊天室的文本框中。如果服务器未启动或IP地址或端口号无效,程序会显示错误消息框。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值