setsockopt/getsockopt用于设置/获取套接层相关选项的值,在Windows VC和Linux GCC/G++中均提供了这两个函数,但在使用时会有微小差异。
今天将一个Windows VS10环境下开发的socket程序移植到CentOS7中,利用G++进行编译调试时,遇到了一个小问题,先上代码:
int TimeOut = 1000;
if(setsockopt(fd,SOL_SOCKET,SO_SNDTIMEO,(unsigned char*)&TimeOut, sizeof(TimeOut))==SOCKET_ERROR){
return 0;
}
//设置发送超时1秒
if(setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,(unsigned char*)&TimeOut, sizeof(TimeOut))==SOCKET_ERROR){
return 0;
}
代码很简单,通过setsockopt设置socket的发送、接收超时时间,在VS10编译运行均正常。但在G++编译正常,运行时出错,setsockopt返回值为-1(#define SOCKET_ERROR -1),仔细查看报错信息为EINVAL(在调用setsockopt()时,optlen无效),检查fd、TimeOut、各个参数选项均正常,一时无措。。。囧。。。
抱着尝试的心态,将时间类型改为了struct timeval,代码如下:
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
if(setsockopt(fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(struct timeval))==SOCKET_ERROR){
return 0;
}
//设置发送超时1秒
<pre name="code" class="cpp">tv.tv_sec = 1;
tv.tv_usec = 0;
if(setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(struct timeval))==SOCKET_ERROR){ return 0;}
再次编译、运行,setsockopt返回0,运行正常了,顿时喜出望外也很无语。。。
PS: struct timeval tv这个变量最好在每次使用前进行设置,有的函数在调用过之后会进行修改,如:select,导致再次调用时值发生变化。
一直认为setsockopt/getsockopt在Linux与Windows中的实现基本相同,没有注意细节,导致在参数类型上出了问题。看来在函数的实现、功能、参数方面Linux和Windows还是有很多不同的,今天工作紧张没有深入分析两个系统的实现细节,找个时间再研究吧。