欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

无阻塞连接 + epoll

最编程 2024-04-15 08:34:41
...

非阻塞connect + epoll

#include <iostream>
#include <string>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
using namespace std;
 
struct so {
    int fd;
    string val;
};

void epollProcess(int sockfd) {
    int epollfd = epoll_create(1);

    struct epoll_event event;
    event.events = (uint32_t) (EPOLLIN | EPOLLOUT | EPOLLET);
    struct so data;
    data.fd = sockfd;
    data.val = "test";
    event.data.ptr = &data;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &event);
    
    struct epoll_event eventArr[128];

    int ret = epoll_wait(epollfd, eventArr, 128, -1);
    if(ret == -1) {
        perror("epoll_wait error");
        exit(EXIT_FAILURE);
    }
    for(int i = 0; i < ret; ++i) {
        int status;
        int err = 0;
        socklen_t len = sizeof(err);

        epoll_event ev = eventArr[i];
        int events = ev.events;
        cout << "events: " << events << endl;
        
        if(events & EPOLLERR) {
            struct so* so_data = (struct so*) ev.data.ptr;
            cout << so_data->val << ", err event fire." << endl;

            status = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &len);
            cout << status << "," << err << endl;
        }
        if (events & EPOLLIN) {
            struct so* so_data = (struct so*) ev.data.ptr;
            cout << so_data->val << ", in event fire." << endl;

            status = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &len);
            cout << status << "," << err << endl;
        }
        if (events & EPOLLOUT) {
            struct so* so_data1 = (struct so*) ev.data.ptr;
            cout << so_data1->val << ", out event fire." << endl;

            status = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &len);
            cout << status << "," << err << endl;
        }
    }
}
 
int main() {
    string ip = "39.97.120.135";
    short port = 9527;


    int sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if(sockfd == -1) {
        perror("sockfd error");
        exit(EXIT_FAILURE);
    }

    int flags = fcntl(sockfd, F_GETFL, 0);
    if(flags == -1) {
        perror("fcntl error");
        exit(EXIT_FAILURE);
    } 
    if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
        perror("fcntl error");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof serverAddr);
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());
    
    int ret = connect(sockfd, (struct sockaddr*)&serverAddr, sizeof serverAddr);
    if(ret < 0) {
        if(errno == EINPROGRESS) {
            epollProcess(sockfd);
        } else {
            perror("connect");
            exit(EXIT_FAILURE);
        }
    }
    else {
        printf("local to local\n");
    }

    return 0;
}
  • connect成功时,epoll可写(EPOLLOUT),如果服务端立刻发送数据,则epoll既可读又可写(EPOLLIN & EPOLLOUT)
  • connect失败时,socket既可读又可写(EPOLLIN & EPOLLOUT & EPOLLERR)
  • 可以通过getsockopt获取错误码,错误码只能使用getsockopt获取一次(获取错误状态并清除)

©著作权归作者所有,转载或内容合作请联系作者

推荐阅读