IP-адрес recvcfrom () и sendto (), который будет использоваться - PullRequest
0 голосов
/ 16 января 2012

На самом деле я хочу создать приложение на C, чтобы 2 человека могли общаться друг с другом.Давайте предположим, что они знают свой IP (На самом деле, я думаю, что я здесь ошибаюсь. Я получаю свои IP-адреса от www.whatismyip.com).

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 голосов
/ 17 января 2012

Адрес, который вы передаете «bind», скорее всего, неправильный.Просто используйте IP-адрес INADDR_ANY (0) для вызова для привязки.Я подозреваю, что 117.193.52.176, вероятно, ваш внешний IP-адрес за пределами вашего домашнего NAT.Реальный IP-адрес вашего ПК - 192.168.1.2 или что-то в этом роде.Введите «ipconfig / all» из командной строки.В любом случае просто свяжитесь с INADDR_ANY, чтобы вам не нужно было знать ваш реальный IP-адрес.

Другие проблемы с этим кодом:

  1. Не проверка возвращаемых значений из API сокетов
  2. Не вызывайте WSAStartup и WSACleanup для каждого вызова recvfrom.Просто вызовите WSAStartup один раз в своем приложении, и не беспокойтесь о вызове WSACleanup.
  3. Я не совсем уверен, что строка "char RecvBuf [data_length];"скомпилирует.(Динамическая длина статического буфера в стеке? Может быть, это новая функция компилятора).
  4. Не создавайте новый сокет для каждого вызова recvfrom.Создайте его один раз и привяжите к нему, а затем используйте его для всех последующих вызовов send / recv.

5 .. Еще одна проблема с фундаментальным дизайном.Если вы и человек, с которым вы общаетесь, не подключены напрямую к Интернету (не к NAT и без брандмауэра), отправка и получение пакетов UDP будут затруднены.Прочитайте статью о пробивании отверстий здесь .

В любом случае, вот более чистая версия вашего кода:

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

}
...