⟅UNIX网络编程⟆⦔accept在返回前终止

说在前面

问题提出

  • ⟅UNIX网络编程⟆⦔处理SIGCHLD信号提及了如何处理被中断的系统调用的一种情况(EINTR非致命错误),另一种情况也可能导致一种非致命错误。
    在这里插入图片描述
    在三路握手完成而建立连接之后,客户TCP却发送了一个RST(复位)。
    在服务端看来,该连接已由TCP排队,等待accept返回(见⟅UNIX网络编程⟆⦔listen函数)时,客户的RST到达(这时,该连接理应终止)。而后,将调用accept函数。

  • 模拟问题
    启动服务器,在其调用accept前让其sleep一小段时间。
    在服务器睡眠时,启动客户,在connect返回后设置SO_LINGER套接字选项让其产生RST,然后终止。(在ubuntu下,当前这种模拟并没有产生错误并设置errno,在后面还会涉及该问题,暂时搁置)

    // client
    	Connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
    
    	struct linger lng;
        socklen_t nSize = sizeof(lng);
        lng.l_onoff = 1;
        lng.l_linger = 0;
    	if( setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &lng, nSize) != 0)
    		err_sys("setsockopt error");
    	Close(sockfd);
    
    // server
    	sleep(20);
    	for ( ; ; ) {
    		clilen = sizeof(cliaddr);
    		
    		if( (connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen)) < 0)
    		{
    			err_sys("accept error");
    		}
    

解决方式

  • 如何处理这种中止的连接依赖于不同的实现。
  • 源自Berkeley的实现完全在内核中处理中止的连接,服务器进程根本看不到。
  • 然而大多数SVR4实现返回一个错误给服务器进程,作为accept的返回结果,不过错误本身取决于实现。这些SVR4实现返回一个EPROTO (“protocolerror",协议错误)errno值
  • POSIX指出返回的errno值必须是ECONNABORTED(“software caused connection abort",软件引起的连接中止)。
    POSIX作出修改的理由在于:流子系统(streams subsystem)中发生某些致命的协议相关事件时,也会返回EPROTO。要是对于由客户引起的一个已建立连接的非致命中止也返回同样的错误,那么服务器就不知道是否应该再次调用accept。换成ECONNABORTED错误,服务器就可以忽略它,再次调用accept就行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值