Python socket模拟HTTP请求

0x00 起

最近在做一个对时间要求比较高的扫描器,需要封装一下SOCKET模拟HTTP发包的一些常用函数。简单的说,就是重写一下requests中的get、post方法。

今天在写的时候,遇到一枚很奇怪的问题,对同一个URL,POST请求能正常返回信息,而一旦切到GET,socket time out。

伪代码如下:

get_str = ‘GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36\r\nAccept: */*\r\n\r\n‘
post_str = ‘POST %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36\r\n\r\n%s\r\n\r\n‘

def get(url,port):
    sock = socket.connect(url,port)
    sock.send(get_str % (url, port))    

    response = ‘‘
    temp = sock.recv(4096)
    while temp:
        temp = sock.recv(4096)
        response += temp

    return response 

0x10 结

心烦意乱的调了很久无果,出去吃了个饭,回来查查资料,从头开始顺了一遍,找到了bug点。原因是HTTP 1.1协议中,默认connection: keep-alive。

Connection: keep-alive   当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接

Connection: close  代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。

而python中的sock.recv如果接收不到数据,会等到TCP连接down掉,才会返回NULL。如果在程序中没有设置超时时间,会等到服务器主动断开连接,一般是30s~60s。

这就是造成socket timeout的原因。在http request里添加connection: close即可解决问题。但是为什么只有get受到影响,post却没有问题呢?

做了个简单的测试:

post 很快就返回了结果:

而get用了很久才返回结果,其中connection为keep-alive:

所以,之前所说的HTTP 1.1协议中,所有的请求都默认为Connection: keep-alive是错误的认识。

只有get请求会默认采取Connection: keep-alive

参考资料:

https://www.byvoid.com/blog/http-keep-alive-header

时间: 2024-10-13 06:05:27

Python socket模拟HTTP请求的相关文章

PHP+SOCKET 模拟HTTP请求

HTTP消息结构 客户端请求包括四部份:请求行(状态行).请求头.空行.请求主体(数据),如下图: 服务端响应包括四部份:响应行(状态行).响应头.空行.响应主体(数据),如图: HTTP请求方法: POST .GET  .HEADE.  PUT.  TRACE  .DELETE .OPTIONS .CONNECT  (前三种最实用),有这麽多的请求方法,但web服务器不一定所有的都支持. GET   基本一致,请求指定的页面信息,并返回实体主体. HEAD  基本和GET一致 ,只不过返回的响

使用socket模拟Http请求

这里举一个简单的例子,使用socket来模拟一段http访问百度代码 封装的工具类如下,方法叫XHttp() package com.spider.net; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socke

python用socket模拟post请求

今天用python的socket模拟了下post请求,通过这个实例可以更加了解python中socket的使用,以及http请求和socket的相互关系等知识. #coding=utf-8 import socket if __name__=="__main__": s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("www.xxxxx.com",80)) #pyhon 字符串很长时可以

python socket模拟游戏开服

python socket服务端 #!/usr/bin/python #-*- coding: utf-8 -*- import socket import os,sys host='127.0.0.1' #监听的IP port=60000       #监听的端口 buffer=1024      #接受的字节数 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  #建立socket对象 sock.bind((host,port)) #

python socket 模拟tcp通讯

对于tcp server 端的创建而言, 分为如下步骤: 1,创建socket对象(socket):其中俩个参数分别为 Address Family(如AF_INET为ipv4),AF_INET6为ipv6,AF_UNIX为unix域协议簇). socket类型(如SOCK_STREAM为tcp,SOCK_DGRAM为udp) 2,绑定服务器地址(bind) : 参数为服务器地址二元组 也就是套接字 3,监听(listen): 参数为允许的连接数 4,等待请求(accpet): 建立一个连接,等

java socket模拟http请求

我们模拟SSLSocket连接,请求博客园首页,并打印响应消息.代码引用来自<Java网络编程精解>作者:孙卫琴 写这篇博客为了说明模拟过程中出现的一些问题,模拟时请先在浏览器访问目标路径,F12查看网络,查看原始的网络请求头. 注意: 1.HTTP请求报文包含请求行.请求头部.空行.请求包体4个部分组成. 2.模拟请求头部时Accept-Encoding不要使用压缩,否则响应结果会出现乱码 3.请求头部结束使用回车换行符结束 代码如下: package com.beluga.hello.ht

用socket 模拟http请求

using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; class HttpHelper { #region 模拟客户端socket连接 private static Socket ConnectSocket(string server

Python中模拟http请求时使用代理

在某些情况下我们有必要设置我们请求时的代理服务器,在哪些情况下自己决定,那么如何设置http请求时的代理呢? 与Python自动处理cookie一样,使用urllib2.build_opener来进行构建. 1 import urllib2 2 3 enable_proxy = True 4 proxy_handler = urllib2.ProxyHandler({"http" : 'http://192.168.1.235:8080'}) 5 null_proxy_handler

PHP socket模拟POST请求

<?php if (! function_exists ( 'socket_post' )) { function socket_post($url, $data, $referer = '') { if (! is_array ( $data )) { return; } $data = http_build_query ( $data ); $url = parse_url ( $url ); if (empty ( $url ['scheme'] ) || $url ['scheme']