socket操作中的一些注意事项

TCP 建立连接以后,双方就是对等的。不论是哪一方,只要正常 close(socket_handle),那么 TCP 底层软件都会向对端发送一个 FIN 包。
FIN 包到达对方机器之后,对方机器的 TCP 软件会向应用层程序传递一个 EOF 字符,同时自动进入断开连接流程(要来回协商几次,但这些都是自动的、不可控的)。什么是 EOF 字符?它其实什么也不是,只是一个标记,上层应用程序如果这时读 socket 句柄的话,就会读到 EOF,也就是说,此时 socket 句柄看起来里面有数据,但是读不出来,因此 select 返回可读(非阻塞模式下)read 不会阻塞(阻塞模式下)但是 read 的返回值却是 0。

如果此时不是读操作而是写操作,并且此时 socket 已经断开连接,那么 write 函数会返回 -1 且置 errno 为 EPIPE(如果忽略了 SIGPIPE 信号的话)或者引发 SIGPIPE 信号(如果没忽略的话)



具体的分析可以结合TCP的"四次握手"关闭. TCP是全双工的信道, 可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道, 但本端只是收到FIN包. 按照TCP协议的语义, 表示对端只是关闭了其所负责的那一条单工信道, 仍然可以继续接收数据. 也就是说, 因为TCP协议的限制, 一个端点无法获知对端的socket是调用了close还是shutdown.

对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.

为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它, 给它设置SIG_IGN信号处理函数:

signal(SIGPIPESIG_IGN);



最好显式调用shudown(fd, flag)
close有时候会意外(只有最后一次CLOSE才调用shutdown)
不然的话很容易发生FIN_WAIT1, FIN_WAIT2还有CLOSE_WAIT的

shutdown(fd, SHUT_RDWR);
close(fd);


struct sockaddr_un 是在unix内通迅用的,头文件为<sys/un.h>

struct sockaddr_in 为一般网络通迅用,头文件为<netinet/in.h>


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值