python和C语言混合编程实例
最近为了测试网速情况怎么样,由于部分业务服务器需要关闭icmp,这样的话采用普通的ping就无法适应我的需求,于是自己简单的写了一个基于tcp端口的ping的程序,由于c执行效率比较的不错,但是开发效率低下,而python是开发效率高,但是执行效率不如C,由于需要大规模的使用,于是用C实现核心部分的代码,并把这部分实现成一个python的模块,由python调用c的模块,下面就贴代码吧
/*tcpportping.c*/ #include<Python.h> #include<string.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<netdb.h> #include<sys/time.h> /*counttimefunctions*/ staticdoublemytime(void) { structtimevaltv; if(gettimeofday(&tv,NULL)==-1) return0.0; return(double)tv.tv_usec+(double)tv.tv_sec*1000000; } staticPyObject* /*returnsobject*/ tcpping(PyObject*self,PyObject*args) { struct sockaddr_inaddr; struct hostent*hp; double time; char *host=NULL; int fd; int port,timeout; if(!PyArg_ParseTuple(args,"sii",&host,&port,&timeout)) /*convertPython->C*/ returnNULL; /*null=raiseexception*/ if((fd=socket(AF_INET,SOCK_STREAM,0))<0){ returnPy_BuildValue("d",-1.0); /*convertC->Python*/ } bzero((char*)&addr,sizeof(addr)); if((hp=gethostbyname(host))==NULL){ returnPy_BuildValue("d",-2.0); /*convertC->Python*/ } bcopy(hp->h_addr,&addr.sin_addr,hp->h_length); addr.sin_family=AF_INET; addr.sin_port=htons(port); structtimevaltv; tv.tv_sec=0; tv.tv_usec=timeout*1000; doublestime=mytime(); if(connect(fd,(structsockaddr*)&addr,sizeof(addr))<0){ returnPy_BuildValue("d",-3.0); /*convertC->Python*/ } fd_setread,write; FD_ZERO(&read); FD_ZERO(&write); FD_SET(fd,&read); FD_SET(fd,&write); if(select(fd+1,&read,&write,NULL,&tv)==0){ close(fd); returnPy_BuildValue("d",-4.0); /*convertC->Python*/ } doubleetime=mytime(); time=etime-stime; if(!FD_ISSET(fd,&read)&&!FD_ISSET(fd,&write)){ close(fd); returnPy_BuildValue("d",-4.0); /*convertC->Python*/ } close(fd); returnPy_BuildValue("d",time/1000); /*convertC->Python*/ } /*registrationtable */ staticstructPyMethodDefportping_methods[]={ {"tcpping",tcpping,METH_VARARGS}, /*methodname,Cfuncptr,always-tuple*/ {NULL,NULL} /*endoftablemarker*/ }; /*moduleinitializer*/ voidinittcpportping() /*calledonfirstimport*/ { /*namemattersifloadeddynamically*/ (void)Py_InitModule("tcpportping",portping_methods); /*modname,tableptr*/ }
编译成python模块
gcctcpportping.c -I/usr/include/python2.4-shared-L/usr/bin-fpic-lpython2.4-otcpportping.so
下面是python调用c模块的代码:
#!/usr/bin/envpython importtcpportping importtime i=0 whilei<5: t=tcpportping.tcpping('www.baidu.com',80,1000) ift<0: print"timeout" else: printt time.sleep(0.5) i+=1
执行python代码就可以实现端口ping的结果,从测试的情况来看,该程序执行的结果跟普通的ping几乎没有什么差别。