总结:总结:Linux中中socket常见错误分析常见错误分析
并不是所有的系统调用都可以自动恢复。如msgsnd喝msgrcv就是典型的例子,msgsnd/msgrcv以block方式发
送/接收消息时,会因为进程收到了信号而中断。此时msgsnd/msgrcv将返回-1,errno被设置为EINTR。且即使
在插入信号时设置了SA_RESTART,也无效。
一、连接过程出错分析
(1)如果客户机TCP协议没有接收到对它的SYN数据段的确认,函数以错误返回,错误类型为ETIMEOUT。通常TCP协议在
发送SYN数据段失败之后,会多次发送SYN数据段,在所有的发送都高中失败之后,函数以错误返回。
(2)如果远程TCP协议返回一个RST数据段,函数立即以错误返回,错误类型为ECONNREFUSED。当远程机器在SYN数据
段指定的目的端口号处没有服务进程在等待连接时,远程机器的TCP协议将发送一个RST数据段,向客户机报告这个错误。客
户机的TCP协议在接收到RST数据段后不再继续发送SYN 数据段,函数立即以错误返回。
(3)如果客户机的SYN数据段导致某个路由器产生“目的地不可到达”类型的ICMP消息,函数以错误返回,错误类型为
EHOSTUNREACH或ENETUNREACH。通常TCP协议在接收到这个ICMP消息之后,记录这个消息,然后继续几次发送SYN
数据段,在所有的发送都告失败之后,TCP 协议检查这个ICMP消息,函数以错误返回。
connect函数的出错处理:
(1)ETIMEOUT-connection timed out 目的主机不存在,没有返回任何相应,例如主机关闭
(2)ECONNREFUSED-connection refused(硬错)到达目的主机后,由于各种原因建立不了连接,主机返回RST(复
位)响应,例如主机监听进程未启用,tcp取消连接等
(3)EHOSTTUNREACH-no route to host(软错)路由上引发了一个目的地不可达的ICMP错误
其中(1)(3),客户端会进行定时多次重试,一定次数后才返回错误。另外,当connect连接失败时,sockfd套接口不可
用,必须关闭后重新socket分配才行。
二、慢系统调用
阻塞操作被取消阻塞的操作打断
1)慢系统调用
如果进程在一个慢系统调用中阻塞时,当捕获到某个信号且相应信号处理函数返回时,这个系统调用被中断,调用返回错误,
设置errno为EINTR
处理的方法
◆ 人为重启被中断的系统调用
人为当碰到EINTR错误的时候,有一些可以重启的系统调用要进行重启,而对于有一些系统调用是不能够重启的。
例如:accept、read、write、select、和open之类的函数来说,是可以进行重启的。所以当检测到该错误的时候,可以使用
goto或continue重启动
对于套接字编程中的connect函数我们是不能重启的,原因是,connect的请求已经发送向对方,正在等待对方回应,这时如果
重新调用connect,而对方已经接受了上次的connect请求,这一次的connect就会被拒绝,因此,需要使用select或poll调用来
检查socket的状态,如果socket的状态就绪,则connect已经成功,否则,视错误原因,做对应的处理
另一个例子,就是pthread_cond_wait函数(注意虚假唤醒)
◆ 安装信号时设置 SA_RESTART属性(该方法对有的系统调用无效)
但注意,并不是所有的系统调用都可以自动恢复。如msgsnd喝msgrcv就是典型的例子,msgsnd/msgrcv以block方式发送/接
收消息时,会因为进程收到了信号而中断。此时msgsnd/msgrcv将返回-1,errno被设置为EINTR。且即使在插入信号时设置
了SA_RESTART,也无效。
◆忽略信号(让系统不产生信号中断)
三、
1、accept返回前连接终止
这是一个非致命的错误,只需要再次调用accept
ECONNABORTED
评论0