0

I am not sure whether I need to use any synchronisation in the thread functions(sendMsg() and receiveMsg()) in the following program. I'm using a single global UDP socket in the program which is being used in these functions which will be used in multiple threads.

Please also note that the IP and port for receiving and sending the messages are constant.

#include <string.h>
#include <unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>


const char* g_upfIp;
unsigned short g_upfPort;
const char* g_smfIp;
unsigned short g_smfPort;
sa_family_t g_ipType;


void initialiseSocket();
int sendMsg(char* pkbuf, size_t len);   
int receiveMsg(char* payload, size_t payloadLength);
void udpServer();    

int main(int argc, char** argv)
{
     //Initialise IP and port
     ...
     initialiseSocket();
     // Now I'll be using multiple threads for udpServer() and sendMsg();
}

void initialiseSocket() {
        if(g_ipType == AF_INET6) {
                g_socket = socket(PF_INET6, SOCK_DGRAM, 0);

                if (g_socket < 0) {
                        perror("creating socket");
                        exit(1);
                }

                addr6.sin6_family = g_ipType;
                inet_pton(g_ipType, g_smfIp, &addr6.sin6_addr);
                addr6.sin6_port = htons(g_smfPort);
                bind(g_socket, (sockaddr*)&addr6, sizeof(addr6));
        }
        else {
                g_socket = socket(PF_INET, SOCK_DGRAM, 0);

                if (g_socket < 0) {
                        perror("creating socket");
                        exit(1);
                }

                addr4.sin_family = g_ipType;
                inet_pton(g_ipType, g_smfIp, &addr4.sin_addr);
                addr4.sin_port = htons(g_smfPort);
                bind(g_socket, (sockaddr*)&addr4, sizeof(addr4));
        }
}

int sendMsg(char* pkbuf, size_t len)
{
        printf("\n[%s::%d]Inside sendMsg dest IP[%s], dest port[%d], srcIP[%s]\n",__FILE__,__LINE__,g_upfIp,g_upfPort,g_smfIp);
        size_t size;
        struct sockaddr_in6 serverAddr6;
        struct sockaddr_in serverAddr4;
        if(g_ipType == AF_INET6) {
                memset(&serverAddr6, 0, sizeof(serverAddr6));
                serverAddr6.sin6_family = g_ipType;
                inet_pton(g_ipType, g_upfIp, &serverAddr6.sin6_addr);
                serverAddr6.sin6_port = htons(g_upfPort);
                size  = sendto(g_socket, pkbuf, len, 0 , (const struct sockaddr *) &serverAddr6,sizeof(serverAddr6));
                if(size < 0) {
                        printf("Error in sending message\n");
                        return -1;
                }
        }
        else {
                memset(&serverAddr4, 0, sizeof(serverAddr4));
                serverAddr4.sin_family = g_ipType;
                inet_pton(g_ipType, g_upfIp, &serverAddr4.sin_addr);
                serverAddr4.sin_port = htons(g_upfPort);
                size  = sendto(g_socket, pkbuf, len, 0 , (const struct sockaddr *) &serverAddr4,sizeof(serverAddr4));
                if(size < 0) {
                        printf("Error in sending message\n");
                        return -1;
                }
        }
                printf("[%d] bytes written to %s:%d\n",size, g_upfIp, g_upfPort);
                return 0;
}

int receiveMsg(char* payload, size_t payloadLength) {
        printf("\nInside receiveMsg IP[%s], port[%d]\n",g_smfIp,g_smfPort);
        int size;
        char srcIp[1000] = {0};
        unsigned short srcPort;
        if(g_ipType == AF_INET6) {
                sockaddr_in6 addr = {0};
                socklen_t addrlen;
                addrlen = sizeof(addr);
                size = recvfrom(g_socket, payload, payloadLength, MSG_TRUNC , (struct sockaddr *) &addr,&addrlen);
        }
        else {
                sockaddr_in addr = {0};
                socklen_t addrlen;
                addrlen = sizeof(addr);
                size = recvfrom(g_socket, payload, payloadLength, MSG_TRUNC , (struct sockaddr *) &addr,&addrlen);
        }
        printf("\n[%d] bytes received from %s:%d\n",size,g_upfIp,g_upfPort);
        return size;
}

void udpServer() {
        printf("\n[%s::%d]Inside udpServer\n",__FILE__,__LINE__);
        int size;

        //In a while loop, receive incoming message in a buffer.
        while(true) {
                char buffer[1024]={0};
                size = receiveMsg(buffer,1024);
                printf("\nMsg Received --> %s\n",buffer);
        }
}    
Vishal Sharma
  • 1,670
  • 20
  • 55
  • > `if(g_ipType == g_ipType)` the test is true more than 'very often' ;-) – bruno Apr 21 '20 at 12:17
  • to use `recvfrom` in parallel has no sense so the problem only concern sendto – bruno Apr 21 '20 at 12:23
  • @bruno I'm going to take a look at the link given. However I didn't understand your comment about recvfrom. – Vishal Sharma Apr 21 '20 at 12:25
  • if several threads try to read on the same socket at the same time who win ? who read what if several msg was sent allowing several reads ? Several to one has a sense, one to several don't have – bruno Apr 21 '20 at 12:27
  • so is that an undefined behaviour? – Vishal Sharma Apr 21 '20 at 12:29
  • it is random behavior, not undefined behavior as `char * p; *p = 0;` is – bruno Apr 21 '20 at 12:32
  • why do you want to read on the socket in several threads ? – bruno Apr 21 '20 at 12:33
  • @bruno I didn't want to do reads in multiple threads. I didn't think about the implications of doing so. Mainly I was concerned about using multiple threads for sending and another thread for receiving simultaneously. As per the link shared by you, it looks like in case of UDP, there shouldn't be any problem. Btw why did you differentiate between random and undefined behavior? aren't both the same? – Vishal Sharma Apr 21 '20 at 12:42
  • in that case there is no problem. Several thread can write in parallel, and you can read when writtings are on going (see link) – bruno Apr 21 '20 at 12:43
  • @VishalSharma Regarding the distinction between random and undefined behaviour, [undefined behaviour](https://en.cppreference.com/w/cpp/language/ub) has a very specific meaning in c++. – G.M. Apr 21 '20 at 12:46

0 Answers0