Linux socket编程中隐含一些“坑点”,写代码时需要注意回避。这些坑点有:
一、心跳包应该采用主动式。教科书建议的都是被动式心跳,判断网络是否断开是通过接收心跳包是否超时来判断。主动式心跳是通过心跳包发送是否成功来判断。因为要兼顾网络繁忙造成的延时,被动式心跳需要2-3次心跳周期没有收到心跳包才会确认是网络断开,需要时间长,一般是5-10秒。主动式心跳只要有一次没有发送成功,就可以确认网络断开,需要时间短,一般3秒内。相关代码如下:
void SendHeart(SOCK_QUEUE *lpSockQueue)
{
char *strHeart="heart";
PackSend(lpSockQueue,strHeart,-1,PSRC_SOCKET_SEVER); // 把心跳包放进发送队列
}
void HeartbeatCheck(SOCK_QUEUE *lpSockQueue) //发送心跳包
{
if(lpSockQueue->ready)
{
lpSockQueue->heartbeat += 1;
if(lpSockQueue->heartbeat > 2) // 大约*1秒
{
lpSockQueue->heartbeat = 0;
SendHeart(lpSockQueue); // 每隔3秒发送一次心跳
}
}
}
void *ThreadSend(void *arg) // 网络数据发送线程
{
......
sizeSend=PackGetLen(lpPack);
logd("send<%d>:%s\n",lpSockQueue->port,PackGetData(lpPack));
if(SendSize(lpSockQueue->fdSock,lpPack,sizeSend,1)==-1)
{
loge("ThreadSend() 发送套接字出错\n");
*lpRun = false; //发送出错意味着网络断开
}
......
}
二、默认的发送、接收超时是75秒,断网检测响应慢。
struct timeval timeoutSock = {3,0}; // 超时设置为3秒
//发送超时
setsockopt(fdConnect,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeoutSock,sizeof(timeoutSock));
//接收超时
setsockopt(fdConnect,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeoutSock,sizeof(timeoutSock));
三、默认端口释放后等待2分钟后才能再被使用,服务进程意外崩溃重启,绑定端口会失败。
//设置端口允许复用
optval = 1;
setsockopt(fdSock,SOL_SOCKET,SO_REUSEADDR,(char *)&optval,sizeof(optval));
下载完整的C源代码:https://download.csdn.net/download/u013705518/21398107