Marc Romero
Marc Romero

Reputation: 115

Socket in thread accept all port connections? c++

I have 3 sockets listening different ports from the same IP (10080, 20081, 30082). I've created the sockets in different treads (pthreads, actually) and I've binded it, etc. When I do the Accept(), the 3 sockets wait for the client call, but when I do the call for any port, always answer the socket that makes the last Accept().

That's my process (C++):

thread 1

Create socket for port 10080

Bind socket for port 10080

Listen for port 10080

Accept for port 10080

.........................................................................

thread 2

Create socket for port 20081

Bind socket for port 20081

Listen for port 20081

Accept for port 20081

.........................................................................

thread 3

Create socket for port 30082

Bind socket for port 30082

Listen for port 30082

Accept for port 30082

.........................................................................

Doesn't matter which port I'm calling (10080, 20081 or 30082) always continues processing the "thread 3".

Anyone can help me to process the information in the correct thread?

Thanks.

PS: I'm monitoring what port is in the main socket and what port is in the socket created by the Accept() instruction and the main socket still correct (30082) and the Accept socket has the called port (10080, 20081 or 30082).

struct addrinfo lRequestAddrInfo;
struct addrinfo * lResultAddrInfo;
int lSocketOption = 1;

memset(&lRequestAddrInfo,0,sizeof(lRequestAddrInfo));
lRequestAddrInfo.ai_socktype=SOCK_STREAM;
lRequestAddrInfo.ai_flags=AI_PASSIVE;
int lReturn = 0;

lReturn = getaddrinfo(lAddress->ip.c_str(), lAddress->port.c_str(), &lRequestAddrInfo, &lResultAddrInfo);

int lSocket = socket(lResultAddrInfo->ai_family, SOCK_STREAM, lResultAddrInfo->ai_protocol);
setsockopt(lSocket, SOL_SOCKET, SO_REUSEADDR, &lSocketOption, sizeof(lSocketOption));
lReturn = bind(lSocket, lResultAddrInfo->ai_addr, lResultAddrInfo->ai_addrlen);
lReturn = listen(lSocket, SOMAXCONN);
while(IsConnected())
{
    struct sockaddr lSocketAddress;
    socklen_t lSocketAddresslen = sizeof(lSocketAddress);
    lNewSocket = accept(pListener->_connection, &lSocketAddress, &lSocketAddresslen);

    if (lNewSocket > -1)
    {
        //process information in new thread
    }   
}

This is the code inside thread. More info:

thread 1

lSocket = 3 (Port 10080)

thread 2

lSocket = 5 (Port 20081)

thread 3

lSocket = 7 (Port 30082)

When I call at port 10080

lSocket = 7 (Port 30082) lNewSocket = 4 (Port 10080)

When I call at port 20081

lSocket = 7 (Port 30082) lNewSocket = 6 (Port 20081)

When I call at port 30082

lSocket = 7 (Port 30082) lNewSocket = 8 (Port 30082)

Upvotes: 1

Views: 1674

Answers (2)

Marc Romero
Marc Romero

Reputation: 115

Finally I did it! I wrote the socket creation and listen action outside the thread and the accept action inside the thread.

I hope this help other people!

Thanks to all of you for the answers!

Upvotes: 0

Tõnu Samuel
Tõnu Samuel

Reputation: 2896

I think you miss important part of code. Because you did't include it, difficult to judge if you use FD_SET(), FD_ISSET() and friends at all. If no, then sure you get weird results. I think it is easier to paste code than explain in words. This is how similar thing works for me:

socket_descriptor=bindsock(thd);
while(true) {
        fd_set      rfs, wfs;
        FD_ZERO(&rfs);
        FD_ZERO(&wfs);

        FD_SET(socket_descriptor,&rfs);
        maxfd = conn_select(thd,&rfs, &wfs);

        if (select(maxfd + 1, &rfs, &wfs, NULL, NULL) == -1) {
            if (errno == EINTR) {
                continue;
            }
            break;
        }
        if (FD_ISSET(socket_descriptor, &rfs)) {
            thd->client_fd = accept(socket_descriptor, &thd->cliaddr,&clilen);

....

and inside of function:

int
conn_select(struct THD*thd,fd_set * rfs, fd_set * wfs) {
    int maxfd = -1;
    size_t i;
    DBUG_ENTER("conn_cullselect");

    if (vector == NULL) {
        DBUG_PRINT("info",("vector == NULL"));
        DBUG_RETURN(0);
    }

    for (i = 0; i < MAX_CONNECTIONS; i++) {
        conn_t     *v;

        if (vector[i] == NULL) {
            DBUG_PRINT("info",("continue"));
            continue;
        }
        v = vector[i];
        switch (v->state) {
            case AWAITING_REQUEST:
                DBUG_PRINT("info",("AWAITING_REQUEST"));
                if (maxfd < v->sd) {
                    maxfd = v->sd;
                }
                FD_SET(v->sd, rfs);
                break;
            case SENDING_FILE:
                DBUG_PRINT("info",("SENDING_FILE"));
                if (maxfd < v->fd) {
                    maxfd = v->fd;
                }
                FD_SET(v->fd, rfs);
                break;
            case SENDING_HEADER:
                DBUG_PRINT("info",("SENDING_HEADER"));
                if (maxfd < v->sd) {
                    maxfd = v->sd;
                }
                FD_SET(v->sd, wfs);
                break;
        }
    }
    DBUG_PRINT("info",("returning %d from conn_cullselect",maxfd));
    DBUG_RETURN(maxfd);
}

Idea is same, not depending how many ports you are listening.

Upvotes: 0

Related Questions