Yuvi
Yuvi

Reputation: 1350

How to reduce message dropping in UDP socket communication, using only single port?

I have writter code snippet for UDP Client and server. I am using same port for sending and receiving. My problem is that there are many messages drops at client side, so can someone help me to optimize my code, here is my code for UDP client:

#define SERVERIP "192.168.170.155"
#define SERVERPORT 5000
#define DEVICE_SEND_PORT 5000
#define DEVICE_RECEIVE_PORT 5000
#define BUFFERSIZE 2048

/**For socket file descriptor identification*/
#define S1READY 0x01

int m_SendSocketId;
int m_ReceiveSocketId;
int msgcount;
int socketbuffsize = 1*1024*1024;


/**
* FUNCTION NAME : waitToRead
* Implementation of select and non-blocking socket mechanism
* @param socket Socket that needs to be in select and non blocking mode
* @return Returnd the file descriptors which, returned by select function
*/
int waitToRead(int socket)
{
    fd_set fds;
    struct timeval timeout;
    int rc; // number of file descriptor returned
    int result; // result 
    int fd; // file descriptor

    fd=fcntl(socket,F_GETFL,0);
    fcntl(socket,F_SETFL,fd | O_NONBLOCK);

    // Set time limit. 
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
    // Create a descriptor containing our sockets.
    FD_ZERO(&fds);
    FD_SET(socket, &fds);
    rc = select(sizeof(fds)*8, &fds, NULL, NULL, &timeout);
    if (rc==-1)
    {
        printf("[%s:%d#%s] Select Failed\n",__FILE__, __LINE__,__func__);
        return -1;
    }

    result = 0;
    if (rc > 0)
    {
        if (FD_ISSET(socket, &fds))
            result |= S1READY;
    }
    return result;
}
/**
* FUNCTION NAME : receiveMessage
* This function opens particular port that is defined in the 
* Configuration file, and listens on that port.
* @return if there'll be any issue in listening, then it will return 
* false otherwise it will return true.
*/
bool receiveMessage()
{
    struct sockaddr_in serverAddr; //Information about the Device UDP Server
    struct sockaddr_in client_addr; // Information about Qgate Server
    char buffer[BUFFERSIZE]; // Buffer to store incoming message
    int addr_len; // to store client address length 
    int serverlen; // to store server address length
    int sockResult; // to store result given by waitToRead
    int optval = 1;
    int receivedByte = 0;

    //Open a datagram Socket
    if((m_ReceiveSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        printf("[%s:%d#%s] UDP Client - socket() error\n",__FILE__, __LINE__,__func__);
        return false;
    }

    //Configure Server Address.
    //set family and port
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(DEVICE_RECEIVE_PORT);


    setsockopt(m_ReceiveSocketId, SOL_SOCKET,SO_REUSEADDR, &optval, sizeof(optval));

    /*if (setsockopt(m_ReceiveSocketId, SOL_SOCKET, SO_RCVBUF, &socketbuffsize, sizeof(socketbuffsize)) == -1) 
    {
        printf("Recieve Socket memory Allocation fail\n");
    }*/

    if((serverAddr.sin_addr.s_addr = INADDR_ANY) == (unsigned long)INADDR_NONE)
    {

        printf("[%s:%d#%s] Host Not found(%d)\n",__FILE__, __LINE__,__func__,h_errno);
        close(m_ReceiveSocketId); // close the socket
        return false;
    }

    if (bind(m_ReceiveSocketId, (struct sockaddr *) &serverAddr,sizeof(struct sockaddr_in)) < 0 )
    {
        printf("[%s:%d#%s] UDP Client- Socket Bind error=%s\n",__FILE__, __LINE__,__func__,strerror(errno));
        close(m_ReceiveSocketId); // close the socket
        return false;
    }

    serverlen = (int )sizeof(serverAddr);
    addr_len = sizeof(struct sockaddr); 
    // Loop and listen for incoming message 
    while(1)
    {
        //wait at select to, read
        sockResult = waitToRead(m_ReceiveSocketId);

        if(sockResult == S1READY)
        {
            receivedByte = read(m_ReceiveSocketId,buffer,BUFFERSIZE);   
            buffer[receivedByte] = '\0';

            if(receivedByte == -1)
            {
                printf("[%s:%d#%s] UDP Client - receive error", __FILE__,__LINE__,__func__);
                close(m_ReceiveSocketId);
                return false;
            }
            else if(receivedByte > 0)
            {
                //printf("[%s:%d#%s] received message = %d bytes\n",__FILE__,__LINE__,__func__,(int)strlen(buffer));
                printf("count: %d, buffer %s \n", msgcount++, buffer);
            }
        }

        memset(buffer, 0, BUFFERSIZE);
        fflush(stdout);
    }

    close(m_ReceiveSocketId); // close the socket
    printf("[%s:%d#%s] Recieve socket closed:%s\n",
                            __FILE__, __LINE__,__func__, strerror(errno));
    return true;
}


bool sendMessage(char *message)
{
    struct sockaddr_in  serverAddr; //Information about the server
    struct sockaddr_in deviceAddr; //Device UDP Client Address for sending message
    int optval = 1;

    //Open a datagram Socket
    if((m_SendSocketId = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        printf("[%s:%d#%s] UDP Client - socket() error\n",__FILE__, __LINE__,__func__);
        return false;
    }

    // Clear out the device struct
    memset(&deviceAddr, 0x00, sizeof(struct sockaddr_in));

    deviceAddr.sin_family = AF_INET;
    deviceAddr.sin_port = htons(DEVICE_SEND_PORT);

    setsockopt(m_SendSocketId, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

    /*if (setsockopt(m_SendSocketId, SOL_SOCKET, SO_SNDBUF, &socketbuffsize, sizeof(socketbuffsize)) == -1) 
    {
        printf("send Socket memory Allocation fail\n");
    }*/

     if((deviceAddr.sin_addr.s_addr = INADDR_ANY) == (unsigned long)INADDR_NONE)
    {
        // in netdb.h 
        printf("[%s:%d#%s] Host Not found(%d)\n",__FILE__, __LINE__,__func__,  h_errno);
        close(m_SendSocketId); // close the socket
        return false;
    }

    if (bind(m_SendSocketId, (struct sockaddr *) &deviceAddr,sizeof(struct sockaddr_in)) < 0 )
    {
        printf("[%s:%d#%s] UDP Client- Socket Bind error=%s\n",__FILE__, __LINE__,__func__,strerror(errno));
        close(m_SendSocketId); // close the socket
        return false;
    }


    // Clear out the server struct
    memset(&serverAddr, 0x00, sizeof(struct sockaddr_in));

    //Configure Server Address.
    //set family and port
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(SERVERPORT);
    //serverAddr.sin_addr.s_addr = htonl(39898);

    if((serverAddr.sin_addr.s_addr = inet_addr(SERVERIP)) == (unsigned long)INADDR_NONE)
    {
        printf("[%s:%d#%s] Host Not found %d\n",__FILE__, __LINE__,__func__,h_errno);
        close(m_SendSocketId);
        return false;
    }

    // Send data to the server.
    if( sendto(m_SendSocketId, message,strlen(message) ,0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0 )
    {
        printf("[%s:%d#%s] UDP Client - sendto() error=%s \n",__FILE__, __LINE__,__func__,strerror(errno));
        close(m_SendSocketId);  
        return false;
    }

    close(m_SendSocketId);
    return true;
}

int main ()
{
    int loop;
    char str[10];
    msgcount = 1;   
    pthread_t receiveThread;

    if(pthread_create(&receiveThread, NULL,(void *)&receiveMessage, NULL) != 0)
    {
        printf("[%s:%d#%s] thread create Failed(%s)\n",
            __FILE__, __LINE__,__func__, strerror(errno));
        return false;
    }

    for(loop =0; loop < 1000; loop++)
    {
        sprintf(str,"%4d",loop);
        sendMessage(str);   
    }

    pthread_join(receiveThread, NULL);  
    return 0;
}

Here is the temporary UDP server code, it receives almost above 90% messages and also sends the same, but udpclient is not able to receive the messages.

int main()
{
        int sock;
        int addr_len, bytes_read, bytes_send;
        char recv_data[1024];
        int i;
        int count=0;
        struct sockaddr_in server_addr , client_addr;


        if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
            perror("Socket");
            exit(1);
        }

        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(5000);
        server_addr.sin_addr.s_addr = INADDR_ANY;
        bzero(&(server_addr.sin_zero),8);

        //client_addr.sin_family = AF_INET;

        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

        if (bind(sock,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)
        {
            perror("Bind");
            exit(1);
        }

        addr_len = sizeof(struct sockaddr);

        printf("\nUDPServer Waiting for client on port 5000");
        fflush(stdout);

    while (1)
    {
        bytes_read = recvfrom(sock,recv_data,1024,0,(struct sockaddr *)&client_addr, (socklen_t *)&addr_len);
        recv_data[bytes_read] = '\0';


        if(recv_data[0]!=0x07)
        {
            recv_data[0] = 0x09;
            //client_addr.sin_port = htons(51254);

            bytes_send = sendto(sock, recv_data, bytes_read, 0, (struct sockaddr *)&client_addr, (socklen_t)sizeof(client_addr));
            if(bytes_send < 0 )
            {
                perror("send to ");
            }
            printf("\nNumber  %d", ++count);
            memset(&recv_data, 0x00, 1024);

        }
        else
        {
            printf("Received Keep ALive\n");        
        }
        memset(&client_addr, 0x00, sizeof(struct sockaddr_in));

        fflush(stdout);

    }
    return 0;
}

Any help would be highly appreciated. Thanks Yuvi

Upvotes: 2

Views: 1724

Answers (2)

Yuvi
Yuvi

Reputation: 1350

The problem was in sendMessage Function, here I was recreating socket every time when I need to send message, and I think that takes time. I don't know yet which is calls are blocking but making sending socket resolves my problem. Now the dropping of message is upto 20 to 30 % only.

Upvotes: -1

user207421
user207421

Reputation: 310893

Your code has nothing to do with UDP dropping packets, except possibly that you are sending packets too fast for the network or the receiver. UDP isn't reliable. It drops packets. If your application protocol requires no dropped packets, you have to build in reliability at that level, via an ACK-based or NACK-based protocol with retries.

Or use TCP like everybody else does in this situation.

Upvotes: 2

Related Questions