1

I need some help. I'm working on a legacy software that uses python 2.5.4 running on Windows7 and I need to enable keepalives in my socket connection.

I've seen in the thread below that you can enable keepalives in python using

object.setsockopt( socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)

However this setup uses the default windows keep alive timer of 2 hours.

I've also seen that we can set the timer using the following API, however it is only available for Python 2.6 onwards.

sock.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 10000, 3000))

Is there anyway I can set this SIO_KEEPALIVE_VALS using python 2.5.4 ? The legacy code I have also has the module pywin32-214. I really can't upgrade the python version.

I also wonder how python2.6 and newer calls the windows api

int WSAIoctl(
  (socket) s,              // descriptor identifying a socket
  SIO_KEEPALIVE_VALS,                  // dwIoControlCode
  (LPVOID) lpvInBuffer,    // pointer to tcp_keepalive struct 
  (DWORD) cbInBuffer,      // length of input buffer 
  NULL,         // output buffer
  0,       // size of output buffer
  (LPDWORD) lpcbBytesReturned,    // number of bytes returned
  (LPWSAOVERLAPPED) lpOverlapped,   // OVERLAPPED structure
  (LPWSAOVERLAPPED_COMPLETION_ROUTINE) lpCompletionRoutine,  // completion routine
);

Thanks for your help.

References: How to change tcp keepalive timer using python script?

https://msdn.microsoft.com/en-us/library/dd877220%28v=vs.85%29.aspx

Community
  • 1
  • 1
paulp
  • 23
  • 4
  • You could backport the [sock_ioctl](https://hg.python.org/cpython/file/2.6/Modules/socketmodule.c#l2848) function from Python 2.6 or use Ctypes to call the [WSAIoctl](https://github.com/twisted/twisted/blob/e38cc25a67747899c6984d6ebaa8d3d134799415/src/twisted/internet/test/_win32ifaces.py#L26) function. – cgohlke Nov 24 '16 at 07:41
  • Hi @cgohlke, thanks for your suggestion. However, I haven't really tried mixing C/C++ with Python before. I will start looking into it. If you have any suggestion on a good reference, it would be much appreciated. Many Thanks. – paulp Nov 25 '16 at 00:59

1 Answers1

1

Here is how you do it in c

static PyObject*
sock_ioctl(PyObject *argO , PyObject *arg)
{
PyObject *s;
DWORD recv;
struct tcp_keepalive ka;
if (!PyArg_ParseTuple(arg, "O(kkk):keepalive",&s,
    &ka.onoff, &ka.keepalivetime, &ka.keepaliveinterval))
    return NULL;

if (WSAIoctl(PyObject_AsFileDescriptor(s), SIO_KEEPALIVE_VALS, &ka,  sizeof(ka),
    NULL, 0, &recv, NULL, NULL) == SOCKET_ERROR) {
    return set_error();
}
return PyLong_FromUnsignedLong(recv);
}

I made a small python extension in github https://github.com/rawinput/ioctl compiled for python 2.5

rawinput
  • 132
  • 1
  • 7
  • Thank you very much @rawinput for this. Really appreciate it. I tried it and the API works like a charm (returns with no errors). I'm knowledgeable in C/C++ and Python, however, I haven't really tried mixing them together. Hence, the C code you gave me is a bit of a mystery but I will try to learn it. A question though, does the function ioctl.keepalive() throw an exception in case it fails? – paulp Nov 25 '16 at 00:55
  • Yes with an OSError as defined in your link https://msdn.microsoft.com/en-us/library/dd877220%28v=vs.85%29.aspx – rawinput Nov 25 '16 at 05:53
  • Thanks again mate! – paulp Nov 28 '16 at 05:24
  • Hi @rawinput, I spent some time looking at linking C into python. Can you help me out a bit on how the format "O(kkk):keepalive" is interpreted by PyArg_ParseTuple()? Thanks. – paulp Nov 30 '16 at 05:41
  • hello read this https://docs.python.org/2/c-api/arg.html you can see that O is python object to c Pyobject and k is python integer or long integer to c usigned long and () means tuple . – rawinput Nov 30 '16 at 11:33
  • Thanks again @rawinput. Sorry to be asking too much, but one last question about compiling. I created a setup.py, added ioctl as an extension. When I try to build using `C:\Python25\python.exe setup.py build -c mingw32`, I'm getting an error saying unknown type 'int64_t'. If I don't add mingw32, its looking for VS2003. `from distutils.core import setup, Extension module1 = Extension('ioctl', sources = ['ioctl.c']) setup (name = 'TestPackage', version = '1.0', description = 'Test compilation', ext_modules = [module1])` – paulp Dec 01 '16 at 02:59
  • hello i removed the unnecessary int64_t declaration and uploaded the setup.py in github you will notice that in the setup.py file you have to give the path of winsock2 library in my computer it is "C:/MinGW/lib/libws2_32.a" hope this help – rawinput Dec 01 '16 at 09:59