chinmaymhatre91
chinmaymhatre91

Reputation: 35

Issue with continuous flow of UDP packets between client and server

I have a client program that sends data "Hi" and receives reply "Hello" from a server. This data transfer occurs for 200 times. The corresponding server program on receiving a datagram from a client, replies "Hello" if the message sent was "Hi". I have shown the code here.

Client program:

void* func(void *arg){
    int dur = *((int*)arg);
    while(dur--){
        cout<<"Client sending..."<<endl;
        int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        int s, r;
        socklen_t len = sizeof(s);
        getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &s, &len);
        getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &r, &len);
        cout<<"Send is "<<s<<". Recv is "<<r<<endl;
        struct sockaddr_in server_sock_addr;
        const char *server_addr = "127.0.0.1";
        char *buf = (char*)malloc(1024);
        char *mess = (char*)malloc(100);
        char *reply = (char*)malloc(100);
        bzero((char*)&server_sock_addr, sizeof(server_sock_addr));
        server_sock_addr.sin_family = AF_INET;
        server_sock_addr.sin_port = htons(5000);
        int status = inet_aton(server_addr, &server_sock_addr.sin_addr);
        strcpy(mess, "Hi");
        memcpy(buf, mess, strlen(mess));
        socklen_t addr_len = sizeof(sockaddr_in);
        sendto(sock, buf, strlen(mess), 0, (sockaddr*)&server_sock_addr, addr_len);
        cout<<"Message is sent"<<endl;
        memset(buf, 0, 1024);
        cout<<"Blocking.."<<endl;
        int bytes = recvfrom(sock, buf, 1024, 0, (sockaddr*)&server_sock_addr, &addr_len);
        memcpy(reply, buf, bytes);
        cout<<"Reply is "<<reply<<endl;
        free(reply);
        free(mess);
        free(buf);
        close(sock);
        cout<<endl<<endl;
    }
    return NULL;
}

int main(int argc, char *argv[]) {
    int status;
    int i;
    vector<pthread_t> tid;
    vector<int> ue_num;

    int num = atoi(argv[1]);
    int dur = atoi(argv[2]);
    tid.resize(num);
    ue_num.resize(num);
    for (i = 0; i < num; i++) {
        ue_num[i] = i;
        status = pthread_create(&tid[i], NULL, func, &dur);
    }
    for (i = 0; i < num; i++) {
        pthread_join(tid[i],NULL);
    }
    cout << "Requested duration has ended. Finishing the program." << endl;
    return 0;
}

Server program:

int main(){
    while(1){
        cout<<"**************************"<<endl;
        cout<<"SERVER started"<<endl;
        cout<<"**************************"<<endl;
        int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        struct sockaddr_in server_sock_addr, client_sock_addr;
        const char *server_addr = "127.0.0.1";
        char *buf = (char*)malloc(1024);
        bzero((char*)&server_sock_addr, sizeof(server_sock_addr));
        server_sock_addr.sin_family = AF_INET;
        server_sock_addr.sin_port = htons(5000);
        int status = inet_aton(server_addr, &server_sock_addr.sin_addr);

        int reuse = 1;
        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
        status = bind(sock, (struct sockaddr*)&server_sock_addr, sizeof(server_sock_addr));

        socklen_t addr_len = sizeof(sockaddr_in);
        char *mess = (char*)malloc(100);
        char *reply = (char*)malloc(100);
        int bytes = recvfrom(sock, buf, 1024, 0, (sockaddr*)&client_sock_addr, &addr_len);
        memcpy(mess, buf, bytes);
        cout<<"Message is "<<mess<<" and bytes is "<<bytes<<endl;
        string str;
        str.assign(mess);
        if(str == "Hi"){
            memset(buf, 0, 1024);
            strcpy(reply, "Hello");
            memcpy(buf, reply, strlen(reply));
            status = sendto(sock, buf, strlen(reply), 0, (sockaddr*)&client_sock_addr, addr_len);
            cout<<"Send bytes is "<<status<<endl;
            if(status == 0){
                cout<<"Buffer full. Closing "<<endl;
                exit(-1);
            }
            cout<<"Reply is sent"<<endl;
        }
        free(mess);
        free(reply);
        free(buf);  
        close(sock);
    }
    return 0;
}

Issue faced:

When I run the program, the data transfer happens correctly only like 2 out of 10 times between client and server. Mostly the client gets blocked on the recvfrom() call, and the whole program just gets stuck with this blockage. The data transfer between client and server is supposed to happen for 200 times(dur=200). But during the 128th or 132nd(some random) instance of data transfer, this blockage happens.

I tried looking at the server. The server is not actually receiving this datagram sent by the client. When I tried to look at the same in Wireshark, it is showing "Destination unreachable(Port unreachable) error for this packet.

I am not able to understand why "port unreachable error" for this datagram, when all datagrams that were previously transmitted reached its destination without any problem. Please provide your comments in fixing this issue. The UDP buffer size is also sufficiently huge(both SND and RCV) - 25MB.

Thanks.

Upvotes: 0

Views: 544

Answers (1)

John Bollinger
John Bollinger

Reputation: 180058

Your client and server both open and close a socket for every iteration of the message exchange. This is very unusual, especially for a server, and it is likely the cause of your problem.

In particular, It is possible for the client to dispatch a message to the server such that it arrives between when the server closes one socket and when it opens the next. Such message will likely be discarded, and the "port unreachable" error you observe could easily correspond to this problem. Your client has no way to know that this has happened because, as we discussed in comments, UDP does not provide for reliable delivery. Of course the server will not respond to a message it never receives, so the client waits forever in vain.

That scenario will not arise if the server, at least, uses the same socket for all communication, so that it is ready to receive the next message as soon as it dispatches a response (and even before). Note, however, that in general, it is dangerous to wait indefinitely for a message to arrive over the network. You should consider setting a receive timeout on the client's socket(s) (look up SO_RCVTIMEO), so that if no message arrives within a reasonable time, the client doesn't hang. In this particular case, it could retry instead -- that would be a reasonable client-side fix to the problem.

Upvotes: 1

Related Questions