Martha Pears
Martha Pears

Reputation: 149

Two way communication program using UDP not working properly

I am trying to write a two way chat program using UDP in C++. Here is my code:

 #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <iostream>
    #include <cstring>
    #include <unistd.h>
    #include <string>
    enum { RECV_PORT = 5023, MSGSIZE = 1024 };
    socklen_t addr_len = sizeof(sockaddr) ;
    int receiver( int socket_fd )
    {
        sockaddr_in my_addr ;
        std::memset( &my_addr, 0, sizeof(my_addr) ) ;
        my_addr.sin_family = AF_INET ;
        my_addr.sin_port = htons( RECV_PORT ) ;
        my_addr.sin_addr.s_addr = INADDR_ANY ;
        if ( bind( socket_fd, (sockaddr*)&my_addr, addr_len ) != 0 )
           return 2 ;
         sockaddr_in client_addr ;
        while( true )
        {
            char recv_data[MSGSIZE+1] ;

            int bytes_recd = recvfrom( socket_fd, recv_data, MSGSIZE, 0,
                                    (sockaddr*)&client_addr, &addr_len ) ;
            if( bytes_recd == -1 ) break ;
            recv_data[bytes_recd] = '\0' ;
            std::cout << "Message from " << inet_ntoa(client_addr.sin_addr)
                      << ':' << ntohs(client_addr.sin_port) << " - "
                      << recv_data << std::endl ;


        std::string send_str ;
        while( std::getline( std::cin, send_str ) )
        {
          send_str.resize(MSGSIZE) ;
          sendto( socket_fd, send_str.c_str(), MSGSIZE, 0,
                (sockaddr*)&client_addr, addr_len ) ;
        }

        return 0 ;
    }
}
    int sender( int socket_fd )
    {
        std::cout << "IP Address of server: " ;
        std::string address ; 
        std::cin >> address >> std::ws ;
        sockaddr_in member_addr ;
        std::memset( &member_addr, 0, sizeof(member_addr) ) ;
        member_addr.sin_family = AF_INET ;
        member_addr.sin_port = htons( RECV_PORT ) ;
        member_addr.sin_addr.s_addr =
                 *(in_addr_t*)(gethostbyname( address.c_str() )->h_addr) ;
        std::string send_str ;
        while( std::getline( std::cin, send_str ) )
        {
          send_str.resize(MSGSIZE) ;


 sendto( socket_fd, send_str.c_str(), MSGSIZE, 0,
            (sockaddr*)&member_addr, addr_len ) ;
    }
    while( true )
    {
        sockaddr_in server_addr ;
        char recv_data[MSGSIZE+1] ;

        int bytes_recd = recvfrom( socket_fd, recv_data, MSGSIZE, 0,
                                (sockaddr*)&server_addr, &addr_len ) ;
        if( bytes_recd == -1 ) break ;
            recv_data[bytes_recd] = '\0' ;
            std::cout << "Message from " << inet_ntoa(server_addr.sin_addr)
                      << ':' << ntohs(server_addr.sin_port) << " - "
                      << recv_data << std::endl ;
        }
        return 0 ;
    }
    int main()
    {
      int socket_fd = socket( AF_INET, SOCK_DGRAM, 0 ) ;
      if( socket_fd == -1 ) return 1 ;
      return fork() == 0 ? receiver( socket_fd ) : sender( socket_fd ) ;
    }

When I type a message on the client window, the message is displayed on the server window, but when I type a message on the server window, then the message is displayed not he server window only and not on the client window. Why is this happening? Can somebody please help me fix this?

Upvotes: 0

Views: 614

Answers (2)

Prabhu
Prabhu

Reputation: 3541

When I type a message on the client window..

You have separate terminal sessions? You are forking and binding to a port in one of the process(same SD as well). Hence running another instance of program from separate windows, wouldn't it have bind error? Though, your receiver logic would run. You should based on command line arguments decide whether the program instance is to be a client or a server.

BTW,the issue is, you are in a while loop in sender and receiver. In sender in while(true) loop for getting input from user and sending. And in other receving the data on socket. Obviously, one is destined to only receive data and the other to send data. It isn't bi-directional.

Upvotes: 0

Nikolai Fetissov
Nikolai Fetissov

Reputation: 84239

Do not code this with fork(2) - your parent and child processes share the same socket (child inherits parent's file descriptors). That surely messes everything up.

Just introduce a command line parameter telling main() which mode to operate in - sender or receiver - and run them in different terminal windows (eventually on different computers).

Upvotes: 1

Related Questions