如何判断socket是否还处于连接状态?

1. 心跳包

可不可以在Client设一个定时器,每隔一段时间发一条消息给服务器,看能不能收到服务器的响应。

心跳包就是定时发包,没回应就判断断开。

2.api返回值测试:

	使用getsockopt测试:
	
	int getsockopt(int socket, int level, int option_name,
	              void *restrict option_value, socklen_t *restrict option_len);
	RETURN VALUE
	       Upon successful completion, getsockopt() shall return 0; otherwise, -1 shall be returned and errno set to indicate the error.
	
	ERRORS
	       The getsockopt() function shall fail if:
	
	       EBADF  The socket argument is not a valid file descriptor.
	
	       EINVAL The specified option is invalid at the specified socket level.
	
	       ENOPROTOOPT
	
	              The option is not supported by the protocol.
	
	       ENOTSOCK
	              The socket argument does not refer to a socket.
	
	       The getsockopt() function may fail if:
	
	       EACCES The calling process does not have the appropriate privileges.
	
	       EINVAL The socket has been shut down.
	
	       ENOBUFS
	              Insufficient resources are available in the system to complete the function.
	
	       The following sections are informative.

在getsockopt的错误码中:
EINVAL The socket has been shut down.
有这么一个返回值,可以用于测试连接是否断开

还可以使用异步读写api来进行测试:

		ssize_t recv(int sockfd, void *buf, size_t len, int flags);

       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

       ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ERRORS
       These are some standard errors generated by the socket layer.  Additional errors may be generated and returned from the underlying protocol modules; see their manual pages.

       EAGAIN or EWOULDBLOCK
              The socket is marked nonblocking and the receive operation would block, or a receive  timeout  had  been  set  and  the  timeout  expired  before  data  was  received.
              POSIX.1-2001  allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for
              both possibilities.

       EBADF  The argument sockfd is an invalid descriptor.

       ECONNREFUSED
              A remote host refused to allow the network connection (typically because it is not running the requested service).

       EFAULT The receive buffer pointer(s) point outside the process's address space.

       EINTR  The receive was interrupted by delivery of a signal before any data were available; see signal(7).

       EINVAL Invalid argument passed.

       ENOMEM Could not allocate memory for recvmsg().

       ENOTCONN
              The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).

       ENOTSOCK
              The argument sockfd does not refer to a socket.

不过在使用recv或者recvfrom来进行测试的时候,需要对socket进行设置:
1.强socket设置成非阻塞就行了,很简单

bool dg::SockTool::setblock(int fd, bool flag){

        int fmode = 0;
        //get file access mode.
        if(-1 == (fmode = fcntl(fd, F_GETFL, 0))){
                return false;
        }

        //set mode.
        if(flag)
                fmode &= (~O_NONBLOCK);
        else
                fmode |= O_NONBLOCK;

        //set file access mode.
        if(-1 == fcntl(fd, F_SETFL, fmode))
                return false;
        return true;
}

然后根据recv的返回值和错误码来进行判断:
由于socket是非阻塞的,所以多半是recv调用失败返回-1,然后判断errno的值:
如果errno是EAGAIN or EWOULDBLOCK,那么就说明连接还是活着的(keep-alive).,否则就是连接已经断开,close(fd)清理资源,
但是应该记住这是发生在一个前提过滤掉中断错误EINTR ,如果发生中断则从新测试即可。

其次是可以为阻塞的socket设置阻塞时间,来实现和非阻塞socket类似的测试、
通过setsockopt设置SO_RCVTIMEO可以设置recv的阻塞时间。

你可能感兴趣的:(网络编程)