Mixed programming examples of python and C

  • 2020-04-02 13:40:38
  • OfStack

How was recently to test speed, because some business server need to close the icmp, so use ordinary ping will not be able to adapt to my needs, and their simple wrote a program based on the TCP port ping, because c execution efficiency is good, but the development of low efficiency, and python development efficiency is high, but performance is better than c, due to large-scale use, so the core part of the code to implement in c, and the partial implementation into a python module, call c by python module, post code below



#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>


static double mytime(void)
{
    struct timeval tv;
    if (gettimeofday(&tv, NULL) == -1)
        return 0.0;

    return (double)tv.tv_usec + (double)tv.tv_sec * 1000000;
}

static PyObject *                                 
tcpping(PyObject *self, PyObject *args )
{
    struct  sockaddr_in addr;
    struct  hostent *hp;
    double  time;
    char    *host = NULL;
    int     fd;
    int     port, timeout;

    if (!PyArg_ParseTuple(args, "sii", &host, &port, &timeout))  
        return NULL;                              

    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        return Py_BuildValue("d", -1.0);        
    }

    bzero((char *)&addr, sizeof(addr));
    if ((hp = gethostbyname(host)) == NULL) {
        return Py_BuildValue("d", -2.0);        
    }
    bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);

    struct timeval tv;

    tv.tv_sec = 0;
    tv.tv_usec = timeout * 1000;

    double stime = mytime();
    if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        return Py_BuildValue("d", -3.0);        
    }
    fd_set read, 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);
        return Py_BuildValue("d", -4.0);        
    }

    double etime = mytime();
    time = etime - stime;
    if (!FD_ISSET(fd, &read) && !FD_ISSET(fd, &write)) {
        close(fd);
        return Py_BuildValue("d", -4.0);        
    }
    close(fd);
    return Py_BuildValue("d", time/1000);        
}


static struct PyMethodDef portping_methods[] = {
    {"tcpping", tcpping, METH_VARARGS},       
    {NULL, NULL}                   
};


void inittcpportping( )                       
{                                      
    (void) Py_InitModule("tcpportping", portping_methods);   
}

Compile as a python module

gcc tcpportping.c  -I/usr/include/python2.4 -shared -L/usr/bin -fpic -lpython2.4 -o tcpportping.so

Here is the code for python to call the c module:

#!/usr/bin/env python

import tcpportping
import time

i = 0
while i < 5:
    t = tcpportping.tcpping('www.baidu.com', 80, 1000)
    if t < 0:
        print "time out"
    else:
        print t
    time.sleep(0.5)
    i += 1

The result of the port ping is implemented by executing the python code, and from the test results, the program's execution is almost identical to a normal ping.


Related articles: