简体   繁体   English

在线程 c++ 套接字中接受函数循环

[英]accept function loop in thread c++ socket

I have 2 questions:我有两个问题:

first - I try to connect one client to server each time.首先 - 我每次都尝试将一个客户端连接到服务器。 (the accept function is in thread) but the connection fail in accept - return always -1 (instead of zero). (接受函数在线程中)但连接在接受时失败 - 始终返回 -1(而不是零)。

the second question - how I can add timeout for to accepting client?第二个问题 - 我如何为接受客户端添加超时?

server.h服务器.h

class Server{
public:
    void open(int port, object&);
    void startThreadOPeration();
    void stop(){};
    ~Server();
private:
    sockaddr_in address;
    int socketfd;
    Object* obj; 
    void startThread();
    std::thread acceptClient;
};

server.cpp服务器.cpp

void Server::open(int port,Object& obj) {
    this->obj = &obj;
    int socketfd = socket(AF_INET, SOCK_STREAM, 0);
    if (socketfd == -1) {
        throw "Could not create a socket";
    }
    this->socketfd = socketfd;

    sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY; 
    address.sin_port = htons(port);
    this->address = address;

    if (bind(socketfd, (struct sockaddr *) &this->address, sizeof(this->address)) == -1) {
        throw "Could not bind the socket to an IP";
    }


    if (listen(this->socketfd, 5) == -1) { 
        throw "Error during listening command";
    } else {
        std::cout<<"Server is now listening ..."<<std::endl;
    }


    startThread();
}


void Server::startThreadOPeration() {
    while (!side_server::stop) {
        // accepting a client
        int client_socket = accept(this->socketfd, (struct sockaddr *) &this->address,
                                   (socklen_t *) &this->address); // Return -1
        if (client_socket == -1) {
            throw "Error accepting client";
        }
        //do operation
    }



void Server::startThread() {



 acceptClient = std::thread(&Server::startThreadOPeration,this);
}

Server::~Server(){
    close(this->socketfd);
    if(acceptClient.joinable()){
        this->acceptClient.join();
    }
}

thank you for help!谢谢你的帮助!

accept() takes 3 parameters - a socket, a pointer to a socket address structure, and a pointer to a socklen_t containing the maximum length of the given socket address structure. accept()接受 3 个参数 - 一个套接字、一个指向套接字地址结构的指针和一个指向包含给定套接字地址结构的最大长度的socklen_t的指针。 On success, the socklen_t will be updated with the actual length of the socket structure.成功后, socklen_t将使用套接字结构的实际长度进行更新。

Unfortunately, your code calls accept() with the address of the this->address variable in the 3rd parameter rather than the address of a valid socklen_t variable.不幸的是,您的代码使用第三个参数中的this->address变量的地址而不是有效socklen_t变量的地址来调用accept() Odds are good this causes this->address to contain what will appear to be complete nonsense when accept() updates what it thinks is a socklen_t but really isn't.可能性很大,这导致this->address包含当accept()更新它认为是socklen_t但实际上不是。

void Server::startThreadOPeration() {
    while (!side_server::stop) {
        // accepting a client
        socklen_t len = sizeof(this->address); // max size of address structure
        int client_socket = accept(this->socketfd, 
                                   (struct sockaddr *) &this->address, 
                                   &tlen); // supply valid max length
        if (client_socket == -1) {
            throw "Error accepting client";
        }
        //do operation
    }

accept() doesn't do timeouts easily, but select() does: accept()不会轻易超时,但select()会:

void Server::startThreadOPeration() {
    while (!side_server::stop) {
        fd_set readfds;
        struct timeval tv;
        int result;

        FD_ZERO(&readfds);

        tv.tv_sec = timeout_s; // number of seconds to wait here
        tv.tv_usec = timeout_us; // number of additional us to wait here

        FD_SET(this->socketfd, &readfds);
        result = select(this->socketfd + 1, &readfds, NULL, NULL, &tv);
        if (result > 0) 
        {
            // cheating a bit here since the only thing in readfds will be this->socketfd
            // normally you should check what of many file descriptors is set.
            socklen_t len = sizeof(this->address);
            int client_socket = accept(this->socketfd, 
                                       (struct sockaddr *) &this->address, 
                                        &tlen); // supply valid max length
            if (client_socket == -1) {
                throw "Error accepting client";
            }
            //do operation
        }
        else
        {
            // handle any failure except timeout here 
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM