Python Http发送模块实现
来源:互联网 发布:手机fps软件 编辑:程序博客网 时间:2024/06/05 06:49
最近开源项目需要一个用C语言实现的Http模块,用于网络数据的发送和接受
然后呢就看了很多网上的教程,使用了一个C语言中的curl方法
源代码如下
#include <stdio.h>#include <curl/curl.h>#include <stdlib.h>#include <string.h>#include <openssl/md5.h>#include <python2.7/Python.h>size_t memory_callback(void *data, size_t size, size_t nmemb, void *content){ size_t realsize = size *nmemb; char *p = *(char **)content; size_t len = p ? strlen(p) : 0; *(char **)content = realloc(p, len + realsize + 1); p = *(char **)content; memcpy(p + len, data, realsize); p[len + realsize] = '\0'; return realsize;}size_t get_content(char *appid, char *secret_key, char *q, char *from ,char *to, char **content){ CURL *curl; CURLcode res; curl = curl_easy_init(); if(curl) { char myurl[1000] = "http://api.fanyi.baidu.com/api/trans/vip/translate?"; char salt[60]; int a = rand(); sprintf(salt,"%d",a); char sign[120] = ""; strcat(sign,appid); strcat(sign,q); strcat(sign,salt); strcat(sign,secret_key); //printf("%s\n",sign); unsigned char md[16]; int i; char tmp[3]={'\0'},buf[33]={'\0'}; MD5((const unsigned char *)sign, strlen((const char *)sign), md); for (i = 0; i < 16; i++) { sprintf(tmp,"%2.2x",md[i]); strcat(buf,tmp); } //printf("%s\n",buf); strcat(myurl,"appid="); strcat(myurl,appid); strcat(myurl,"&q="); strcat(myurl,q); strcat(myurl,"&from="); strcat(myurl,from); strcat(myurl,"&to="); strcat(myurl,to); strcat(myurl,"&salt="); strcat(myurl,salt); strcat(myurl,"&sign="); strcat(myurl,buf); printf("%s\n",myurl); /* always cleanup */ curl_easy_setopt(curl, CURLOPT_URL, myurl); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memory_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)content); res = curl_easy_perform(curl); /* Check for errors */ if(res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); } return 0;}static PyObject *xhttp(PyObject *self, PyObject *args){ char *content = NULL; char *appid; char *secret_key; char *q; char *from; char *to; if(!PyArg_ParseTuple(args, "s|ssss", &appid, &secret_key, &q, &from, &to)) { return NULL; } get_content(appid, secret_key, q, from, to, &content); return Py_BuildValue("s", content); if(content) free(content);}static PyMethodDef httpMethods[] ={ {"xhttp", (PyCFunction)xhttp, METH_VARARGS}, {NULL, NULL, 0, NULL}};PyMODINIT_FUNC initxhttp(void){ Py_InitModule("xhttp", httpMethods);}
我们从头来研究一下这个代码吧
首先是三个函数库,比较特殊
#include <curl/curl.h>#include <openssl/md5.h>#include <python2.7/Python.h>
curl是利用URL语法在命令行方式下工作的开源文件传输工具。它被广泛应用在Unix、多种Linux发行版中,并且有DOS和Win32、Win64下的移植版本
但是我们这里使用的是libcurl
并不是linux的某个命令,而是一个函数库
#include <openssl/md5.h>
是加密函数,用于计算md5值的
#include <python2.7/Python.h>
这里也可以写作
#include "Python.h"
但是我们现在直接指定到特定的头文件,可以减少很多编译时候的麻烦
然后便是这个包装过的C函数
size_t memory_callback(void *data, size_t size, size_t nmemb, void *content){ size_t realsize = size *nmemb; char *p = *(char **)content; size_t len = p ? strlen(p) : 0; *(char **)content = realloc(p, len + realsize + 1); p = *(char **)content; memcpy(p + len, data, realsize); p[len + realsize] = '\0'; return realsize;}
这个函数是我们在调用
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memory_callback);
时候,调用的处理函数
通过CURLOPT_WRITEFUNCTION
指定curl_easy_setopt
的处理方式,在接受到返回的http包时候,自动调用memory_callback
函数来处理
而memory_callback
函数的结构所在cURL
的API说明中定义的
我们可以去cURL
的官网去查看说明,这里我摘查了一下
#include <curl/curl.h>size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEFUNCTION, write_callback);
现在我们来解释一下其中的几个参数的意义
首先ptr
是指向交付的数据的指针
size
和nmemb
相乘的结果则是代表返回数据的大小
而size
代表的是每个块的大小,nmemb
代表的是块的数目
而userdata
并不是在我们这里函数中定义的
userdata
是定义在这里
#include <curl/curl.h>CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer)
注意:
我们这里定义时使用的名为是pointer
的指针,但是结合我们前面那个定义,pointer
代表的就是要传进write_callback
的第四个参数userdata
上面那个定义就是我们对userdata
的定义
如果你没有定义回写函数(wirte_callback
),那么,pointer
就必须初始化为一个FILE
类型的的文件句柄
然后通过这个文件句柄将送回的http包的内容写入文件中
char *p = *(char **)content;
这句话的意思是将返回的http包内容content
的地址赋给*p
然后将p指向的内存的大小计算出来,放入变量len
中
size_t len = p ? strlen(p) : 0;
最后,使用realloc
重新分配content
所指向的内存大小为返回的数据的大小
*(char **)content = realloc(p, len + realsize + 1);
最后把指针p
指向新的content
p = *(char **)content;
指针p
也只是一个中间变量,主要是未来防止丢失包的地址,先将其保存在p
指针中
然后改变完content
后,再用p
指向新的content
最后将数据data
存入新扩展的内存中
然后,我们进入主函数中
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memory_callback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)content);
主函数中的
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memory_callback);
将传回的数据通过回调函数处理,存入适当的空间中,然后执行下一个函数
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)content);
将content指针指向数据存储的位置
然后检查curl的工作情况
res = curl_easy_perform(curl);
最后判断一下res
的值,是否为正常的值
最后我们就可以使用python来包装我们的C代码了
if(!PyArg_ParseTuple(args, "s|ssss", &appid, &secret_key, &q, &from, &to)) { return NULL; }
从python中传入的五个参数,都是为string
类型的
然后我们调用C语言的函数
get_content(appid, secret_key, q, from, to, &content);
将返回的值写入content中,最后将C语言中的值转换成python的值然后返回python中
return Py_BuildValue("s", content);
最后的最后,那就是编译了
将要链接的库函数接在程序的后面
gcc -shared -I/usr/include/python2.7 -fPIC xhttp.c -lcurl -lssl -pthread -o xhttp.so
编译成so文件,就可以在这个目录下导入这个我们用C写的模块了
- Python Http发送模块实现
- python发送http请求之requests模块
- python发送http请求之requests模块
- python发送http请求之requests模块
- requests模块--python发送http请求
- Python发送邮件模块
- python发送HTTP请求
- python发送HTTP请求
- python发送HTTP请求
- python发送http请求
- python 发送http请求
- python 发送http post
- python发送HTTP请求
- JAVA实现Python requests模块(JAVA实现Http请求)
- python http client模块
- python之HTTP模块
- Python模块学习 ---- httplib HTTP协议客户端实现
- Python模块学习 ---- httplib HTTP协议客户端实现
- logiscope 应用度量元 翻译和解释
- spark alone模式参数中英文对照
- spring声明式事务 同一类内方法调用事务失效
- 自定义View系列教程06--详解View的Touch事件处理
- android async-http使用
- Python Http发送模块实现
- python环境搭建
- Python(3)
- WEBP
- 关于android IPC(AIDL、Binder、Messenger)通信
- 精通iOS开发-第15章 Grand Central Dispatch和后台处理
- 检验完全平方数
- swift2.0 学习笔记Twenty
- Android多媒体学习四:实现图像的编辑和合成