《深入浅出TCP之11理解tcp的有序释放操作》

11 理解tcp的有序释放操作

tcp连接的三个阶段:

  • 连接建立阶段
  • 数据传输阶段
  • 连接拆除阶段
    服务器和客户端可以通过关闭各自半边分连接来通知对方,它已完成应答了.效果上看,它们发送的就是一条EOF.
shutdown调用
int shutdown( int s,  int how );

how = 0 : 关闭连接的接收端(也适用于UDP)
how = 1 : 关闭连接的发送端(后继所有试图对套接字进行写操作都会除错.将发送缓冲区中所有的数据都发送出去之后,tcp会向其对等实体发送一个FIN,通知它没数据了)
how = 2 : 两端都关闭(通常不设置此参数,但是某些winsock实现中,如果不先设置2调用shutdown,closesocket无法正常工作.
  1. how = 0, linux会刷新输入队列,以丢弃应用程序还未读取的所以数据,如果有新数据到达,tcp会进行ack,然后悄悄将其丢弃,因为应用程序再也无法接收数据了,windows中,如果数据在队列中,或者有新数据到达,winsock都会重置连接,因此winsock下使用shutdown(s, 0 );是不安全的.
  2. 在winsock中,将how设置为2调用shutdown遇到的问题与设置为0遇到额问题相同----连接可能会重置
  3. 调用shutdown并没有释放套接字及其资源(how被设置为0或2时可能缓冲区释放掉),同时会使的套接字的所有持有者都生效.而调用close或closesocket,不影响套接字的其他持有者
  4. how = 1调用shutdown,不管其他进程是否打开了这个套接字,都可以保证对等实体会收到一个EOF.而调用close或closesocket无法保证这一点,因为在套接字的引用计数减少到0之前,它都不会将FIN发送给对等实体
  5. 当应用程序的对等实体通过close,shutdown或terminate关闭了连接的写入侧时,select会返回一个对套接字的读事件,如果应用程序没有检查EOF状态,它可能要处理一个长度为0的段.这是因为对等实体已经关闭了连接的写入侧,而读事件实际是tcp向应用程序发送了一个来自对等实体的EOF.

注意点:

  • 调用shutdown导致tcp_usrclosed的调用,如果shutdown已经调用过了,连接就处于FIN-WAIT-2状态,tcp_usrclosed会调用soisdisconnected,这个调用会完全关闭套接字,recvfrom返回0,代表EOF。
  • fget在使用CTRL-D的时候,在流上做了标记,因此程序再次走到fget的时候,就不会调用read,fget就直接返回了NULL了
  • 调用FD_CLR把stdin(描述符)排除在select的检查之外
  • 在抓包看不出问题的时候,使用strace或ktrace查看系统调用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值