recvcfrom()和sendto()要使用的ip地址

时间:2012-01-16 11:35:35

标签: c++ sockets bind sendto

实际上,我想在C中创建一个应用程序,这样两个人就可以互相聊天。让我们假设他们知道他们的IP(实际上,我认为我在这里犯了错误。我从www.whatismyip.com获取我的IP)。

void recv_data(char *from, unsigned short int Port, char *data, int data_length)
{
                WSADATA wsaData;
                SOCKET RecvSocket;
                sockaddr_in RecvAddr;
                char RecvBuf[data_length];
                sockaddr_in SenderAddr;
                int SenderAddrSize = sizeof (SenderAddr);
                WSAStartup(MAKEWORD(2, 2), &wsaData);
                RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                RecvAddr.sin_family = AF_INET;
                RecvAddr.sin_port = htons(Port);
                   RecvAddr.sin_addr.s_addr = inet_addr(from);
                bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
                recvfrom(RecvSocket, RecvBuf, data_length, 0, (SOCKADDR *) & SenderAddr, &SenderAddrSize);
                int i;
            for(i=0;i<=data_length-1;i++)
                *(data+i)=RecvBuf[i];
            WSACleanup();
}

以上是接收其他人发送内容的功能。当“127.0.0.1”是from的值但是当我的ip(117.193.52.176)被使用时,它会显示其他内容。谁能告诉我哪里错了?

1 个答案:

答案 0 :(得分:0)

您传递给“绑定”的地址可能是错误的。只需使用INADDR_ANY(0)的IP进行绑定调用即可。我怀疑117.193.52.176可能是您的家庭NAT之外的外部IP地址。您PC的真实IP地址是192.168.1.2或类似的东西。从命令行键入“ipconfig / all”。在任何情况下,只需绑定到INADDR_ANY,这样您就不必知道您的真实IP地址。

此代码的其他问题:

  1. 不检查套接字API的返回值
  2. 不要为每次recvfrom调用调用WSAStartup和WSACleanup。只需在您的应用中调用WSAStartup一次,不要担心调用WSACleanup。
  3. 我不完全确定行“char RecvBuf [data_length];”将编译。 (堆栈上的动态长度静态缓冲区?可能是一个新的编译器功能)。
  4. 不要为每次recvfrom调用创建一个新套接字。创建一次并绑定到它,然后将其用于所有后续的send / recv调用。
  5. 5 ..更多的基金设计问题。除非您和您正在通信的人直接连接到Internet(不是NAT且没有防火墙),否则发送和接收UDP数据包将很困难。阅读有关打孔here的文章。

    在任何情况下,这里都是您的代码的更简洁版本:

    int g_fWinsockInit = 0;
    
    void initWinsock()
    {
        WSADATA wsaData = {};
    
        if(!g_fWinsockInit)
        {
            WSAStartup(MAKEWORD(2,2), &wsaData);
            g_fWinsockInit = 1;
        }
    }
    
    void recv_data(char *from, unsigned short int Port, char *data, int data_length)
    {
        SOCKET RecvSocket;
        sockaddr_in RecvAddr = {}; // zero-init, this will implicitly set s_addr to INADDR_ANY (0)
    
        sockaddr_in SenderAddr = {}; // zero-init
        int SenderAddrSize = sizeof(SendAddr);
        int ret;
    
        initWinsock();
    
        RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (RecvSocket == INVALID_SOCK)
        {
            printf("Error - socket failed (err = %x)\n", WSAGetLastError());
            return;
        }
    
        RecvAddr.sin_family = AF_INET;
        RecvAddr.sin_port = htons(Port);
    
        ret = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
        if (ret < 0)
        {
           printf("bind failed (error = %x)\n", WSAGetLastError());
           return;
        }
    
        ret = recvfrom(RecvSocket, data, data_length, 0, (SOCKADDR *) &SenderAddr, &SenderAddrSize);
    
        if (ret < 0)
        {
           printf("recvfrom failed (error = %x)\n", WSAGetLastError());
        }
        else
        {
            printf("received %d bytes\n");
        }
    
    }