套接字半关闭与关闭

套接字半关闭与关闭 (可参考TCP/IP网络编程)
套接字的半关闭状态: 可以传输但不可接收或可接收但不可传输,即只关闭流的一半.
shutdown()函数的三种断开连接方式: SHUT_RD: 断开输入流 SHUT_WR: 断开输出流 SHUT_RDWR: 同时断开I/O区别: 如果传入SHUT_RD 那么无法接收数据,即使数据到缓冲区了也会抹去并无法调用相关读取函数. 如果传入SHUT_WR 那么无法输出数据了, 但如果输出缓冲中还有未传输的数据会首先传输完毕. [这是与SHUT_RD的区别]. close()才不管缓冲区还有没有内容直接全抹掉. 打算关闭套接字连接时close()shutdown()都会向客户端发送EOF符号表示传输结束. 而调用close()函数会同时关闭I/O流,并且再也无法接收对方的数据了. 使用shutdown()进行半关闭就比较优雅了, 我可以发送完EOF后等待客户端发送的最后一次数据(SHUT_WD). 比如下面的服务端代码: while (1) { read_cnt = fread((void*)buf, 1, BUF_SIZE,fp); if(read_cnt < BUF_SIZE) { break; //我输出完毕之后推出循环 } } shutdown(client_fd,SHUT_WR); //告诉客户端我不再发数据给你了 read(client_fd, buf, BUF_SIZE); //阻塞在这等客户端最后一次发数据过来. printf("msg from client:%s\n", buf); //打印客户端最后一次数据 fclose(fp); close(client_fd); //正式关闭客户端套接字 close(server_fd); closesocketshutdown(使用SHUT_WR当作参数时),会向通信对方发出一个fin包, 而此时套接字的状态会由ESTABLISHED变成FIN_WAIT_1,然后对方发送一个ACK包作为回应, 套接字又变成FIN_WAIT_2,如果对方也关闭了连接则对方会发出FIN我方会回应一个ACK并将套接字置为TIME_WAIT。因此可以看出closesocket,shutdown所进行的TCP行为是一样的, 所不同的是函数部分,shutdown会确保windows建立的数据传输队列中的数据不被丢失, 而closesocket会冒然的抛弃所有的数据,因此如果你愿意closesocket完全可以取代shutdown, 然而在数据交互十分复杂的网络协议程序中,最好还是shutdown稳妥一些! @1. (ESTABLISHED) -- shutdown -> 服务端(FIN_WAIT_1) --fin-> 客户端 --ack-> 服务端(FIN_WAIT_2) @2. 客户端 --fin--> 服务端 --ack--> 客户端(TIME_WAIT); @3. 客户端套接字处于TIME_WAIT 阶段即处于等待回收状态, windows默认4分钟后自动回收, 既然是资源那有稀缺性, 比如nginx默认可操作1024个文件描述符(套接字), 如果这些TIME_WAIT待回收的或CLOSE_WAIT(调用close()产生待回收)的套接字占用太多而无法及时回收的话, 那么nginx剩下可用于建立ESTABLISHED的套接字资源就不足了, 那么就无法继续接受请求, 于是报"Too Many Open Files异常"或卡主(nginx还必须维护这些TIME_WAIT套接字), 再比如mysql配置max-connections=2048, 一旦没有可用的连接(套接字),mysql就会报too many connections, 因此及时的回收或重新利用这些TIME_WAIT 就显得很关键了. HTTP协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接(套接字)传输多个 request/response,一个主要原因就是发现了这个问题. 即告诉套接字别发完一个就像等待被回收了, 继续站岗循环使用吧. 继续看下面的案例怎么通过修改内核配置尽快回收套接字. 
vim /etc/sysctl.conf

编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然后执行 /sbin/sysctl -p 让参数生效。


net.ipv4.tcp_syncookies = 1  表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭; net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将time-wait sockets重新用于新的TCP连接,默认为0,表示关闭; net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。 net.ipv4.tcp_fin_timeout    修改系統默认的 TIMEOUT 时间

 

转载于:https://www.cnblogs.com/zyp221314/p/9228701.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值