使用UDP的双向通信程序无法正常工作

时间:2015-04-15 23:18:30

标签: c++ sockets udp

我正在尝试使用C ++中的UDP编写双向聊天程序。这是我的代码:

 #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 ) ;
    }

当我在客户端窗口上键入消息时,消息显示在服务器窗口上,但是当我在服务器窗口上键入消息时,消息显示的不是服务器窗口而不是客户端窗口。为什么会这样?有人可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

请勿使用fork(2)对此进行编码 - 您的父进程和子进程 share 使用相同的套接字(子进程继承父进程的文件描述符)。这肯定会搞砸一切。

只需引入一个命令行参数,告诉main()在发送方或接收方中运行哪种模式,并在不同的终端窗口(最终在不同的计算机上)运行它们。

答案 1 :(得分:0)

  
    

当我在客户端窗口上输入消息时..

  

您有单独的终端会话?您正在分叉并绑定到其中一个进程中的端口(同样SD也是如此)。因此,从单独的窗口运行另一个程序实例,它不会有绑定错误吗?但是,您的receiver逻辑会运行。您应该基于命令行参数来决定程序实例是客户端还是服务器。

顺便说一句,问题是,你在发送者和接收者中处于一个循环中。在while(true)循环中的发件人中,用于从用户获取输入和发送。而在其他接收套接字上的数据。显然,一个注定只接收数据而另一个注定要发送数据。它不是双向的。