首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在c++中更改监听到非阻塞模式

在c++中更改监听到非阻塞模式
EN

Stack Overflow用户
提问于 2018-03-21 11:29:16
回答 1查看 58关注 0票数 0

我正在尝试实现一个套接字库。一切都很好,直到我达到了接受函数。我检查了堆栈溢出,我说它不会返回,直到客户端通过它连接,但如果它不是在块模式下。那么,我想知道:如何改变收听NONBLOCK模式?

这是我的标题:

代码语言:javascript
运行
复制
#ifndef NET_SOCKET_H
#define NET_SOCKET_H

#ifdef __cplusplus
extern "C" {
#endif

#if defined(WIN32) || defined(WINDOWS_XP)
#include <winsock2.h>
#endif

#include <type-of/include/type.h>
#include <unistd.h>

#define NET_SOCK_ALLOCATED 1

    typedef struct NetSocket NET_SOCK;
    typedef struct sockaddr_in NET_ADDR_IN;
    typedef struct sockaddr NET_ADDR;

    struct NetSocket {

        struct {
            B32 sys; // PF_INET or PF_UNIX
            B32 data; // SOCK_STREAM or SOCK_DGRAM
            B32 mode; // IPPROTO_TCP or IPPROTO_UDP
        } from;
#if defined(WIN32) || defined(WINDOWS_XP)
        SOCKET sock;
#else
        B32 sock;
#endif
        B8 * host;
        NET_ADDR_IN to;
        BIT status;
        STATUS(*open)(NET_SOCK * net);
        STATUS(*tie)(NET_SOCK * server);
        STATUS(*wait)(NET_SOCK * net, B32 max);
        STATUS(*join)(NET_SOCK * server, NET_SOCK * client);
        STATUS(*in)(NET_SOCK * client);
        void (*close)(NET_SOCK * net);
        void (*pop)(NET_SOCK * net);
    };

    NET_SOCK net_sock_std(B8U * host, B32U port);
    NET_SOCK * net_sock_push(B8U * host, B32U port);
    void net_sock_zero(NET_SOCK * net);
    STATUS net_sock_open(NET_SOCK * net);
    STATUS net_sock_tie(NET_SOCK * server);
    STATUS net_sock_wait(NET_SOCK * net, B32 max);
    STATUS net_sock_join(NET_SOCK * server, NET_SOCK * client);
    STATUS net_sock_in(NET_SOCK * client);
    STATUS net_sock_put(NET_SOCK * net);
    void net_sock_close(NET_SOCK * net);
    void net_sock_pop(NET_SOCK * net);

    void winsock_start();
    void winsock_stop();


#ifdef __cplusplus
}
#endif

#endif /* NET_SOCKET_H */

这是我的来源:

代码语言:javascript
运行
复制
#include "net_socket.h"

void net_sock_function(NET_SOCK * net){
    if(net){
        net->open = net_sock_open;
        net->tie = net_sock_tie;
        net->wait = net_sock_wait;
        net->join = net_sock_join;
        net->in = net_sock_in;
        net->close = net_sock_close;
        net->pop = net_sock_pop;
    }
}

NET_SOCK net_sock_std(B8U * host, B32U port){
    NET_SOCK net;
    net_sock_zero(&net);
    if(host)net.host = strdup(host);
    if(port)net.to.sin_port = htons(port);
    bit_off(&net.status,NET_SOCK_ALLOCATED);
    return(net);
}

NET_SOCK * net_sock_push(B8U * host, B32U port){
    NET_SOCK * net = malloc(sizeof(NET_SOCK));
    net_sock_zero(net);
    if(host)net->host = strdup(host);
    if(port)net->to.sin_port = htons(port);
    bit_on(&net->status,NET_SOCK_ALLOCATED);
    return(net);
}

void net_sock_zero(NET_SOCK * net){
    if(net){
        winsock_start();
        net->from.data = SOCK_STREAM;
        net->from.mode = IPPROTO_TCP;
        if(is_win()){
            net->from.sys = AF_INET;
            net->to.sin_family = AF_INET;
        }
        else {
            net->from.sys = AF_UNIX;
            net->to.sin_family = AF_UNIX;
        }
        net->sock = -1;
        net->host = NULL;
        net->to.sin_addr.s_addr = htonl(INADDR_ANY);
        net->to.sin_port = 0;
        net_sock_function(net);
    }
}

STATUS net_sock_open(NET_SOCK * net){
    if(!net)return(Off);
    if( (net->sock = socket(net->from.sys,net->from.data,net->from.mode)) != -1)return(On);
    return(Off);
}

STATUS net_sock_tie(NET_SOCK * server){
    if(!server)return(Off);
    if(bind(server->sock,(NET_ADDR*)&server->to,sizeof(server->to)) != -1)return(On);
    return(Off);
}

STATUS net_sock_wait(NET_SOCK * net, B32 max){
    if(!net)return(Off);
    if(listen(net->sock,max) != -1)return(On);
    return(Off);
}

STATUS net_sock_join(NET_SOCK * server,NET_SOCK * client){
    if(!server || !client)return(Off);
    B32U clientLen = sizeof(client->to);
    while((client->sock = accept(server->sock,(NET_ADDR *)&client->to,&clientLen)) == -1)return(On);
    return(Off);
}

STATUS net_sock_in(NET_SOCK * client){
    if(!client)return(Off);
    if(connect(client->sock,(NET_ADDR *)&client->to,sizeof(client->to)) != -1)return(On);
    return(Off);
}

STATUS net_sock_put(NET_SOCK * net){
    if(!net)return(Off);

    return(Off);
}

void net_sock_close(NET_SOCK * net){
    if(is_win())closesocket(net->sock);
    else close(net->sock);
}

void net_sock_pop(NET_SOCK * net){
    if(net){
        if(net->host){
            free(net->host);
            net->host = NULL;
        }
        if(bit_is_on(net->status,NET_SOCK_ALLOCATED)){
            free(net);
            net = NULL;
        }
    }
}

void winsock_start() {
    if (is_win()) {
        WORD versionWanted = MAKEWORD(1, 1);
        WSADATA wsaData;
        WSAStartup(versionWanted, &wsaData);
        atexit(winsock_stop);
    }
}

void winsock_stop() {
    if (is_win()) {
        WSACleanup();
    }
}

最后是我的主要内容:

代码语言:javascript
运行
复制
#include "net_socket.h"

void command_line(B32 c, B8 ** v, B8U ** host, B32U * port) {
    B32 i = 1;
    while (i < c) {
        switch (i) {
        case 1:
        {
            *port = atoi(v[i]);
        }
            break;
        case 2:
        {
            *host = v[i];
        }
            break;
        }
        i++;
    }
}

int main(int argc, char** argv) {
    B8U * host = NULL;
    B32U port = 50;
    command_line(argc, argv, &host, &port);
    NET_SOCK server = net_sock_std(NULL, port);
    if (server.open(&server)) {
        if (!host) {
            NET_SOCK client = net_sock_std("localhost", port);
            printf("server openned in %hu\n", server.to.sin_port);
            if (client.open(&client)) {
                printf("Server client openned in %hu", client.to.sin_port);
            }

            if (server.tie(&server) && server.wait(&server, 1)){
                printf("\nready\n");
            }

            while (server.join(&server, &client)){ // I can't get in search mode
                printf("searching\n");
            }
            client.pop(&client);

        } else {
            NET_SOCK client = net_sock_std(host, port);
            if (client.open(&client)) {
                printf("client openned in %s %hu\n", host, client.to.sin_port);
                while (!client.in(&client)) {
                    printf("trying to connect\n");
                }
                printf("bye server\n");
            }
        }
        server.close(&server);
    }
    server.pop(&server);
    return (EXIT_SUCCESS);
}

在我朋友Jeremy的帮助下,我发现:(它只是将服务器SOCK设置为关闭)

代码语言:javascript
运行
复制
STATUS net_lock_socket(NET_SOCK * net, STATUS block) {
    if (!net || net->sock < 0) return Off;
#if defined(WIN32)
        unsigned long mode = block ? 0 : 1;
        return (ioctlsocket(net->sock, FIONBIO, &mode) == 0) ? On : Off;
#else
        int flags = fcntl(net->sock, F_GETFL, 0);
        if (flags == -1) return Off;
        flags = block ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
        return (fcntl(net->sock, F_SETFL, flags) == 0) ? On : Off;
#endif
}
EN

回答 1

Stack Overflow用户

发布于 2018-03-21 11:49:08

首先,快速澄清一下--阻塞的不是listen(),而是accept()listen()只是让操作系统知道您希望该套接字能够在将来接受传入的TCP连接;因此没有理由阻止它。

其次,要使accept()成为非阻塞的,首先需要使您在非阻塞上调用的套接字成为accept() --有关如何做到这一点的信息,可以在here中找到。

完成此操作后,如果没有正在等待的TCP连接,则accept()将返回-1并将errno设置为EWOULDBLOCK,而不是在检测到传入的TCP连接之前不返回。因此,为了知道何时在套接字上调用accept()是合适的,您可以在select()调用中将套接字包括在读取fd集中。只要存在传入的TCP连接,accept-socket就会发出可供读取的信号,是时候调用accept()来处理它了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49397664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档