参考文章:
http://lenky.info/2013/02/24/socket%E9%80%89%E9%A1%B9%E7%B3%BB%E5%88%97%E4%B9%8Bso_linger/
SO_LINGER选项只对close()起作用,改变在套接口上执行close()函数的默认行为。关于SO_LINGER套接口选项的设置及作用在很多地方都有介绍,如(unix 网络编程 卷1 p172)。
先说一下我在服务器这里遇到的问题,接收完客服端发送完的数据,需要给客户端返回一条信息,虽然不一定保证客服端必须收到,但要尽力而为。(我用的是阻塞的socket)
开始我只是通过对l_onoff和l_linger都设置为非0,然后调用close()。这样无疑是有问题的,至少在。考重启服务器时可能会说端口已被占用。
一种方法使用应用级确认,服务器向客户发送数据后调用read来读取对端应用层发送来的数据。这样无疑保证对端一定能收到(当然不出现网络问题的情况下),然后再close()。但这样又会增加服务器的负担,需要维持一段时间的链接。另一种方法,先调用shutdown,等一段时间在close。这里等一段时间怎样确定呢?sleep()绝对不是好的办法。
最后解决方法(可能不是最好的,希望大牛指点啊):通过结合选项SO_LINGER、函数close()、函数shutdown()、函数read()配合设计。
1) 设置SO_LINGER选项参数l_onof非0而l_linger为0;
2) 调用函数shutdown(sock_fd, SHUT_WR);
3) 设置超时定时器,假定为t秒;
4) 调用函数read(sock_fd)阻塞等待,直到读到EOF或被定时器超时中断。
5) 执行函数close(sock_fd)或者调用exit(0)进程退出。
2) 调用函数shutdown(sock_fd, SHUT_WR);
3) 设置超时定时器,假定为t秒;
4) 调用函数read(sock_fd)阻塞等待,直到读到EOF或被定时器超时中断。
5) 执行函数close(sock_fd)或者调用exit(0)进程退出。
linger InternalLinger;
InternalLinger.l_onoff=1;
InternalLinger.l_linger=0;
InternalLinger.l_onoff=1;
InternalLinger.l_linger=0;
setsockopt(sfd, SOL_SOCKET, SO_LINGER, (const char*)&InternalLinger, sizeof(linger));//设置SO_LINGER选项(防范LOSE_WAIT挂住所有套接字)
#denfine TIMEOUT 5;
struct tiemval tv_timeout;