سؤال

I am a beginner to network programming. I have made a simple UDP server and UDP client . The client sends messages to the server and the server prints the message . As soon as the client stopped sending messages , then the recvfrom method was blocked . Hence , I tried to make a non-blocking socket with fcntl and select but it is not working. Following is my code of my UDP server .

#include "udpserver.h"

void start_udp_server(int PORT)
{
    struct sockaddr_in server_addr ;
    sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    FD_ZERO(&master_fds);
    FD_SET(sock_fd, &master_fds);

    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET ;
    server_addr.sin_addr.s_addr = htonl(0);
    server_addr.sin_port = htons(PORT);


    // bind the address with the socket
    if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr))<0)
        fprintf(stderr , "error binding the socket to the address\n");
    else
    {
        fprintf(stderr , "bind successful...\n");
        fflush(stdout);
    }


    if (fcntl(sock_fd, F_GETFL) & O_NONBLOCK)
    {
        printf("\nsocket is non-blocking");
    }

    int r =  fcntl(sock_fd, F_SETFL, fcntl(sock_fd, F_GETFL) | O_NONBLOCK);


    printf("r = %d",r);
    if (r < 0)
    {
        printf("error making the socket non-blocking %d",r);
    }

    if (fcntl(sock_fd, F_GETFL) & O_NONBLOCK)
    {
        printf("\nsocket is non-blocking");
    }

    fprintf(stderr , "server listening on port %d %s\n",ntohs(server_addr.sin_port) ,inet_ntoa(server_addr.sin_addr));
    fflush(stdout);

}

int receive_udp_msg()
{
    socklen_t lengthOfClientAddress  = sizeof(client_addr);
    int activity = 0 ;
    int l = 0 ;

    FD_ZERO(&read_fds);
    memcpy(&read_fds, &master_fds, sizeof(master_fds));

    printf("before select\n");
    activity = select(sock_fd + 1 , &read_fds, NULL, NULL, NULL);
    printf("after select\n");
    if (FD_ISSET(sock_fd, &read_fds))
    {
        printf("----activity happened on sock_fd\n");
        l = (int)recvfrom(sock_fd, buffer, 1000, 0, (struct sockaddr *)&client_addr , &lengthOfClientAddress) ;
        printf("received msg\n");
        if (l == - 1)
        {
            fprintf(stderr , "there was error \n");
            fflush(stdout);
            return -1 ;
        }

    }

    return l ;
}

int main()
{
   start_udp_server ;
   int l = 0 ;
   while(1)
   {
     l = receive_udp_msg();
     if(l > 0 )
       print("message received : %s",buffer);
   }

}

When the client has stopped sending messages , the program prints before select and after that it does not print anything.

هل كانت مفيدة؟

المحلول

Because you are using a NULL value for your timeout pointer passed to select, the call will block until there is socket activity.

activity = select(sock_fd + 1 , &read_fds, NULL, NULL, NULL);
                                                         ^
                                                         ^

This is fully explained in the man pages for select. If you do not want this, provide your call to select with a non-null pointer to a timeval struct populated with the desired timeout value.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top