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的阻塞时间。
本文探讨了如何判断socket连接状态,包括利用心跳包维持连接和通过API如getsockopt的错误码测试连接是否断开。同时介绍了设置socket为非阻塞或设置接收超时(SO_RCVTIMEO)来检测连接的有效性。
3848

被折叠的 条评论
为什么被折叠?



