Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1800666
  • 博文数量: 306
  • 博客积分: 3133
  • 博客等级: 中校
  • 技术积分: 3932
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-19 16:50
文章分类

全部博文(306)

文章存档

2018年(7)

2017年(18)

2016年(39)

2015年(35)

2014年(52)

2013年(39)

2012年(22)

2011年(29)

2010年(53)

2009年(12)

分类: LINUX

2010-09-06 10:51:02

当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:
close(sockfd);


  你也可以调用shutdown()函数来关闭该socket。该函数允许你只停止在某个方向上的数据传输,而一个方向上的数据传输继续进行。如你可以关闭某socket的写操作而允许继续在该socket上接受数据,直至读入所有数据。
  int shutdown(int sockfd,int how);
  Sockfd是需要关闭的socket的描述符。参数 how允许为shutdown操作选择以下几种方式:
    SHUT_RD:关闭连接的读端。也就是该套接字不再接受数据,任何当前在套接字接受缓冲区的数据将被丢弃。进程将不能对该套接字发出任何读操作。对TCP套接字该调用之后接受到的任何数据将被确认然后无声的丢弃掉。
    SHUT_WR:关闭连接的写端,进程不能在对此套接字发出写操作
    SHUT_RDWR:相当于调用shutdown两次:首先是以SHUT_RD,然后以SHUT_WR


使用close中止一个连接,但它只是减少描述符的参考数,并不直接关闭连接,只有当描述符的参考数为0时才关闭连接。
shutdown可直接关闭描述符,不考虑描述符的参考数,可选择中止一个方向的连接。

tcp关闭状态机:
主动方: close(socketfd);发送fin   ---->被动方
主动方<-----------被动方的ipv4协议栈自动回复一个ack,主动方接收后处于fin_wait_2;
主动方<-----------被动方recv出错,然后close(sockfd)发送fin给主动方,发送后被动方处于last_ack;
主动方------------>ack

先调用close()的一方会进入TIME_WAIT状态;   

问题:
可能程序员代码质量不高,导致不检查recv出错信息,而没有close(sockfd),从而导致主动方永远接受不到fin包,从而导致close_wait,即fin_wait_2;

解决方法:
1.对recv,send进行出错检查,及时close,shutdown;
2.对socketfd进行SO_REUSEADDR,从而避免连接失败后重连时使用其他端口,一般client尤其需要。
3.将SO_LINGER设为0,强制关闭。l_onoff=1,l_linger=0;(seconds)


注意:
    1>. 如果有多个进程共享一个套接字,close每被调用一次,计数减1,直到计数为0时,也就是所用进程都调用了close,套接字将被释放。
    2>. 在多进程中如果一个进程中shutdown(sfd, SHUT_RDWR)后其它的进程将无法进行通信. 如果一个进程close(sfd)将不会影响到其它进程. 得自己理解引用计数的用法了. 有Kernel编程知识的更好理解了.
阅读(1502) | 评论(0) | 转发(0) |
0

上一篇:串口通信

下一篇:Socket EAGAIN

给主人留下些什么吧!~~