微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么getsockopt optlen为零?

如何解决为什么getsockopt optlen为零?

我使用非阻塞套接字和事件库。我只是注意到,当我打电话随机快速连接到本地ip的端口时,getsockopt(fd,SOL_SOCKET,SO_ERROR,&val,&optlen);的optlen变为0。

我试图制作较小的代码显示问题。我在此代码中使用了epoll,但其他事件库中也发生了同样的问题。

#define nconnect_d 500
#define ebuffer_d 64

#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>

struct sockaddr_in initaddr(uint32_t ip,uint16_t port){
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(ip);
    memset(addr.sin_zero,sizeof(addr.sin_zero));
    return addr;
}

int getconnectfd(uint32_t sip,uint16_t sport,uint32_t dip,uint16_t dport){
    int fd;
    if((fd = socket(AF_INET,SOCK_STREAM,0)) == -1)
        return -1;
    if(setsockopt(fd,SO_REUSEPORT,(int[]){1},sizeof(int)) == -1)
        return -1;
    if(fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK) == -1)
        return -1;
    struct sockaddr_in saddr = initaddr(sip,sport);
    if(bind(fd,(const struct sockaddr *)&saddr,(socklen_t)sizeof(struct sockaddr_in)) == -1)
        return -1;
    struct sockaddr_in daddr = initaddr(dip,dport);
    if(connect(fd,(const struct sockaddr*)&daddr,(socklen_t)sizeof(struct sockaddr_in)) == -1 && errno != EINPROGRESS)
        return -1;
    return fd;
}

int epolltouch(int efd,int sfd,uint32_t flag){
    struct epoll_event event;
    event.data.fd = sfd;
    event.events = flag;
    if(epoll_ctl(efd,EPOLL_CTL_ADD,sfd,&event) == -1)
        return -1;
    return 0;
}

int epollrm(int efd,int sfd){
    if(epoll_ctl(efd,EPOLL_CTL_DEL,NULL) == -1)
        return -1;
    return 0;
}

int main(){
    int efd = epoll_create1(0);
    assert(efd != -1);
    for(uint32_t i = 0; i < nconnect_d; i++){
        int sfd = getconnectfd(INADDR_ANY,12420,0x7f000001,2048 + i);
        assert(sfd != -1);
        epolltouch(efd,EPOLLOUT | EPOLLET);
    }
    struct epoll_event events[ebuffer_d];
    uint32_t iconnect = nconnect_d;
    while(iconnect){
        int n = epoll_wait(efd,events,ebuffer_d,-1);
        assert(n != -1);
        for(uint32_t i = 0; i < n; i++){
            int evfd = events[i].data.fd;
            int opt,optlen;
            assert(getsockopt(evfd,&opt,&optlen) != -1);
            assert(optlen == sizeof(int));
            switch(opt){
                case 0:{
                    /* connection has been established */
                    break;
                }
                case ECONNREFUSED:
                case ehostunreach:
                case ENETUNREACH:
                /* can be more valid case isn't it? */
                {
                    /* connection has Failed */
                    break;
                }
                default:{
                    assert(0);
                }
            }
            iconnect--;
            epollrm(efd,evfd);
            close(evfd);
        }
    }
    return 0;
}

我跑步时;

$ ./a.out
a.out: temp.c:72: main: Assertion `optlen == sizeof(int)' Failed.
Aborted (core dumped)

optlen 0是否表示套接字由于某种原因被关闭了?之后需要关闭插座吗?

解决方法

使用getsockopt()时,最后一个参数必须是 已初始化 socklen_t。 通话之前,您应该使用存储空间大小对其进行初始化 以获得结果值(此处为{sizeof(opt))。 它通过地址传递,因为如果此存储空间太大 对于实际结果,然后系统调用将其调整为 确切大小。

,

调用getsockopt()要求您为系统提供缓冲区,这意味着您必须在调用前设置optlen

int opt;
socklen_t optlen = sizeof opt;

... getsockopt(evfd,SOL_SOCKET,SO_ERROR,&opt,&optlen);

通过这种方式,getsockopt()知道允许写入“缓冲​​区”的数量,在这种情况下,缓冲区仅是一个整数,并且使用实际写入的字节数来更新optlen

手册页中指出optlen是一个值/结果,这意味着您将其设置为传入并期望重新获得另一个值,但是opt仅是结果,因此不在乎价值是什么。

EDIT 将optlen的类型固定为socklen_t,将h / t固定为prog-fh

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?