• 网络编程的异常及处理


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

    accept被信号中断
    accept以及套接字上的I/O可能被信号打断,并返回EINTR作为结果,必须处理该返回值并且适当时候再次调用。
    for(;;)
    {
        if(connfd = accept(listenfd, (struct sockaddr*)addr, sizeof(addr)) < 0)
        {
            if(connfd == EINTR)
            {
                continue;
            }
            else
            {
                printf("accept error ");
            }
        }
    }
    connect被信号中断
    connect被信号打断,返回EINTR作为结果,不能对该socket再次调用connect,需要使用select等待连接完成。
    accept返回前连接夭折

     

    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.明确指定字节序,在服务器和客户端使用同样的字节序。
  • 相关阅读:
    10. 分离链接散列表
    9. avltree
    8.二叉查找树
    socket listen参数中的backlog 的意义!
    TCP 三次握手和四次挥手中的ACK 为什么总是SYN + 1 或者 FIN +1 而不是+ 其他数值?
    eclipse 快捷键
    内部类
    rabbitmq AmqpClient 使用Topic 交换机同一个channel 同时多个队列 ,多个交换机,C++代码示例
    rabbitMQ 问题
    rabbitmq AmqpClient 使用Topic 交换机投递与接收消息,C++代码示例
  • 原文地址:https://www.cnblogs.com/learn-my-life/p/5653820.html
Copyright © 2020-2023  润新知