POSIX UDP套接字无法绑定到正确的IP

时间:2016-01-23 17:15:53

标签: c++ sockets

我正在编写一个大学项目,包括使用POSIX套接字和C ++编写聊天客户端和服务器。

客户端应该使用P2P进行交谈,例如每个客户端都有自己的开放UDP套接字,通过该套接字发送和接收来自/向其他客户端的消息。

我的问题是双重的:

  1. 我的UDPSocket类构造函数似乎完全忽略了端口号,无论参数如何都绑定到端口65535。
  2. 端口绑定到IP 255.255.255.255而不是我自己的IP(10.0.0.3),或者至少是我调用getpeername时得到的。
  3. 据我所知,传递INADDR_ANY应该绑定到我的本地地址,传递端口号0应该让操作系统选择一个空闲端口,我做错了什么?

    这是我的UDPSocket类的构造函数:

    UDPSocket::UDPSocket(int port){
    socket_fd = socket (AF_INET, SOCK_DGRAM, 0);
    
    // clear the s_in struct
    bzero((char *) &in, sizeof(in));  /* They say you must do this    */
    
    //sets the sin address
    in.sin_family = (short)AF_INET;
    in.sin_addr.s_addr = htonl(INADDR_ANY);    /* WILDCARD */
    in.sin_port = htons((u_short)port);
    
    fsize = sizeof(from);
    
    //bind the socket on the specified address
    if(bind(socket_fd, (struct sockaddr *)&in, sizeof(in))<0){
        perror ("Error naming channel");
    }
    }
    

    这是初始化:

    m_Socket = new UDPSocket(0);
    

    这是我用来检索绑定地址的方法:(UDPSocket继承Socket)

    std::string Socket::GetSocketAddress()
    {
        struct sockaddr_in  addr;
        int len = sizeof(addr);
        getpeername(socket_fd, (struct sockaddr*)&addr, (socklen_t*)&len);
    
        char ipAddressBuffer[50];
        memset(ipAddressBuffer, 0, sizeof(ipAddressBuffer));
        sprintf(ipAddressBuffer, "%s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    
        return ipAddressBuffer;
    }
    

    任何帮助将不胜感激, 阿维。

2 个答案:

答案 0 :(得分:2)

您正在使用foreach ($array as $key => $value) {} ,它会为您提供已连接套接字的远程地址。如果检查getpeername()的返回值,则应指示失败。

  • 您需要使用getsockname()而不是getpeername()来获取本地套接字的地址
  • 您需要检查getsockname()是否成功。

请注意,您的套接字绑定到特殊的0.0.0.0地址,这意味着&#34;所有本地接口&#34;,以便getockname()也将返回。

答案 1 :(得分:0)

回答更一般的问题“如何与UDP建立点对点通信”:

使用UDP套接字,虽然您可以使用connect,但您通常不希望这样做,因为这限制了每个套接字的单个对等体。相反,您希望在每个对等体中使用单个未连接的UDP套接字与sendtorecvfrom系统调用一起发送和接收具有不同地址的数据包。

sendto函数接收数据包和对等地址以发送它,而recvfrom函数返回数据包及其来自的对等地址。使用单个套接字,无需与selectpoll进行多路复用 - 您只需调用recvfrom即可从任何来源获取下一个数据包。当你得到一个数据包时,你也得到了对等地址来发送数据包(返回)。

启动时,您的对等方将创建一个套接字并将其绑定到INADDR_ANY(允许它在计算机上的任何接口或广播地址上接收数据包)以及分配给您的特定端口程序或端口0 (允许操作系统选择任何未使用的端口)。在后一种情况下,您需要使用getsockname来获取端口并将其报告给用户。一旦设置了套接字,对等程序就可以sendto它所知道的任何对等体,或者recvfrom任何对等体(包括那些它还不知道的对等体)。

所以唯一棘手的部分是引导 - 让第一个数据包流动,以便对等方可以接收它们并找出它们的对等地址进行通信。一种方法是在启动每个对等体时在命令行上指定对等地址。你将开始没有参数的第一个(因为它还没有同行)。它将仅从(在套接字设置之后)重新获取以从对等体获取分组。以第一个地址作为参数开始第二个。它向第一个对等体发送一个或多个数据包,一旦获得第一个数据包,就会知道新的对等体。现在在命令行上启动第三个客户端,其中包含前两个地址...