linux网络编程 错误,网络编程的异常及处理

网络编程不只是编写网络、主机、进程都正常时能良好工作的进程,更重要的是客户主机崩溃、客户进程崩溃网络异常时怎么处理。

accept被信号中断

accept以及套接字上的I/O可能被信号打断,并返回EINTR作为结果,必须处理该返回值并且适当时候再次调用。

for(;;)

{

if(connfd = accept(listenfd, (struct sockaddr*)addr, sizeof(addr)) < 0)

{

if(connfd == EINTR)

{

continue;

}

else

{

printf("accept error\n");

}

}

}

connect被信号中断

connect被信号打断,返回EINTR作为结果,不能对该socket再次调用connect,需要使用select等待连接完成。

accept返回前连接夭折

47c66034f256df46f75bc4fb0763b2fc.png

149442.htm

estiblished状态的连接在被accept取走之前夭折,对于这种错误,不同的系统有不同的处理,大多数是返回一个错误结果给进程,SVR4返回EPROTO(协议错误),posix指出必须返回ECONNABORTED(软件引起的连接错误),在返回ECONNABORTED错误时,重新调用accept即可。

也有的操作系统会直接清除掉这种夭折的连接,服务器进程根本不会发现夭折的连接。

echo回响程序处理服务器端异常终止

客户端进程阻塞于终端输入时,服务端进程异常终止,三次握手终止连接,客户端把FIN追加到clifd的读取缓冲区末尾。

客户从终端输入字符,通过clifd发送给服务端(由于服务端已关闭,会回复一个RST给客户端)并调用read获取结果。

此时FIN已在读取缓冲区,而RST还在网络传输的过程中,因此read返回0,代表对端已关闭,而不是读取到RST的复位消息。

为了避免这种场景的RST消息,客户端需要使用多路复用同时监听多个输入:套接口和终端输入。这样就能早先一步获取FIN消息,避免连接终止后还向对端发送消息。

SIGPIPE

进程向一个接收到RST的套接字写入消息时,内核会给进程发送一个SIGPIPE信号。

完整的过程是:进程向一个接收到FIN的套接字写入消息,接收到RST应答,此时再次写入,内核会给进程发送一个SIGPIPE信号。

此信号的缺省动作是终止进程,不产生core文件。

不管进程是否捕捉该信号,写操作都会返回EPIPE错误。

SIGPIPE的处理

SIGPIPE缺省是终止进程,并且不产生core文件,这就无从跟踪和发现问题。

对SIGPIPE的处理可以是:

1.设置SIG_IGN,无视该信号,并默认write会处理EPIPE错误。

2.信号处理函数中处理该错误,需要知道的是,信号处理函数无法判断是哪个套接字出了错误,如果确实要知道哪个套接字出了错误,还是需要在write返回后处理EPIPE错误。

服务器主机崩溃

当客户端和服务器之间建立连接后,服务器主机崩溃,此时通过网络发往服务器主机的消息不会得到任何回应。

此时可能返回的错误有两种

1.客户端持续重传数据分节,一直没有得到回应,此时应返回ETIMEOUT错误。

2.如果中间路由器判断服务器主机不可达,并返回一个ICMP错误,则错误是EHOSTUNREACH或ENETUNREACH。

通过write的返回值,可以得知错误原因,但是通常需要等待很长一段时间。

快速检测服务器主机崩溃

给套接字加上一个超时时间

在不主动发送消息的时候检测服务器主机崩溃

心跳消息

服务器主机崩溃后重启

如果服务器主机崩溃后并重启,在崩溃期间客户没有发送消息给服务器,那么客户端是不知道服务器曾经崩溃过的(如果不使用套接字选项SO_KEEPALIVE),客户端给服务器发送消息。

服务器崩溃并重启后丢失了所有的连接信息,对于接收到的消息都以RST响应,导致客户端收到ECONNRESET错误。

如果客户端检测服务器的主机崩溃错误,那应该设置SO_KEEPALIVE。

服务器主机关机

UNIX系统关机时,由INIT进程给所有进程发送SIGTERM信号(我们可以捕捉此信号),然后等待一段时间,然后给所有进程发送SIGKILL信号。进程终止时,所有打开的描述字都将关闭。

对于服务器主机关机,客户最好使用多路复用及时检测到套接字的关闭。

网络数据格式

1.转换所有格式的数据为字符串消息

2.明确指定字节序,在服务器和客户端使用同样的字节序。

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux网络编程中的select函数用于在一组文件描述符上进行多路复用,以便能够同时监视多个文件描述符是否有数据可读、可写或异常等事件发生。 select函数的原型如下: ```c #include <sys/select.h> int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); ``` 其中,参数说明如下: - nfds:需要监视的文件描述符集合中最大描述符加1的值。 - readfds:可读事件的文件描述符集合。 - writefds:可写事件的文件描述符集合。 - exceptfds:异常事件的文件描述符集合。 - timeout:超时时间,如果设置为NULL则表示一直等待,直到有事件发生。 select函数返回值表示有事件发生的文件描述符个数,若返回值为-1则表示发生错误,可通过errno来获取具体错误信息。 使用select函数的基本步骤如下: 1. 创建并初始化文件描述符集合readfds、writefds和exceptfds,并将需要监视的文件描述符添加到相应的集合中。 2. 调用select函数,等待事件发生。 3. 检查select函数的返回值,判断有事件发生的文件描述符个数。 4. 遍历文件描述符集合,检查每个文件描述符对应的就绪事件类型。 5. 处理事件。 select函数在网络编程中常用于实现多客户端并发处理、IO复用等功能。它可以同时监听多个文件描述符,避免了使用多线程或多进程的复杂性和性能开销。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值