非阻塞式socket建立以及如何判断对方断开

  最近写的程序要求的是在控制线程中使用非阻塞的socket,以前没怎么接触过,先贴出代码如下:

#define sockopt_noblock(socket, noblock) do{\
    int val = (noblock);\
    ioctl((socket), FIONBIO, (int)&val);\
} while(0)

int conn_nonb(int sockfd, const struct sockaddr_in *saptr, socklen_t salen, int nsec)
{
    int flags, n, error, code;
    socklen_t len;
    fd_set wset;
    struct timeval tval;

    flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

    sockopt_noblock(sockfd, 1);

    error = 0;
    if ((n == connect(sockfd, (struct sockaddr *)saptr, salen)) == 0) {
        goto done;
    } else if (n < 0 && errno != EINPROGRESS){
        return RS_ERROR;
    }

    /* Do whatever we want while the connect is taking place */

    FD_ZERO(&wset);
    FD_SET(sockfd, &wset);
    tval.tv_sec = nsec;
    tval.tv_usec = 0;

    if ((n = select(sockfd+1, NULL, &wset,
                    NULL, nsec ? &tval : NULL)) == 0) {
        close(sockfd);  /* timeout */
        errno = ETIMEDOUT;
        return RS_ERROR1;
    }

    if (FD_ISSET(sockfd, &wset)) {
        len = sizeof(error);
        code = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);
        /* 如果发生错误,Solaris实现的getsockopt返回-1,
         * 把pending error设置给errno. Berkeley实现的
         * getsockopt返回0, pending error返回给error.
         * 我们需要处理这两种情况 */
        if (code < 0 || error) {
            close(sockfd);
            if (error)
                errno = error;
            return RS_ERROR;
        }
    } else {
        fprintf(stderr, "select error: sockfd not set");
        exit(0);
    }

done:
    //fcntl(sockfd, F_SETFL, flags);  /* restore file status flags ,这里看你自身的情况,可以选择恢复或者不恢复 */
    return RS_OK;        /* return 0 */
}

注:此代码是别人写的,可以拿来直接用,但是在这里连接只能保证你connect的时候是成功的,但是不能保证你后续read、write、send、recv是成功的。因此你需要在每次
read和write前检查连接是否断开。可以通过以下办法来判断(也是网上查找的资料,自己用过,是这样的):

在阻塞模式下,

recv和read 一般返回0,断开。(这个待议,我没试过)

非阻塞模式下,
错误代码是EAGAIN/EWOULDBLOCK时,表示正常,未读写数据。
recv()或read()返回0时,表示断开,返回-1而errno不是EAGAIN/EWOULDBLOCK时,表示有其他错误,一般建议断开。

这里有其他的判断方法,其实和我上面说的一致。

正常断开连接情况下,判断非阻塞模式socket连接是否断开

摘自:http://blog.chinaunix.net/uid-15014334-id-3429627.html

在UNIX/LINUX下,

1,对于主动关闭的SOCKET, recv返回-1,而且errno被置为9(#define EBADF   9 /* Bad file number */)或104 (#define ECONNRESET 104 /* Connection reset by peer */)

2,对于被动关闭的SOCKET,recv返回0,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */)

3,对正常的SOCKET, 如果有接收数据,则返回>0, 否则返回-1,而且errno被置为11(#define EWOULDBLOCK EAGAIN /* Operation would block */)

 

因此对于简单的状态判断(不过多考虑异常情况),
    recv返回>0, 正常
    返回-1,而且errno被置为11  正常
    其它情况    关闭


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值