2012-01-16 3 views
0

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

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) используется, появляется что-то еще. Может ли кто-нибудь сказать мне, где я ошибаюсь?

+3

Что вы имеете в виду «появляется что-то еще»? Также проверьте возвращаемые значения всех функций и распечатайте любые ошибки, которые вы получаете (если функция не работает, проверьте «WSAGetLastError»). –

+0

Вы находитесь за любым маршрутизатором/брандмауэром? – Default

+0

Что-то еще означает текст, который я даже не отправил из моего приложения для говорящего ... На самом деле куча сердец, лица в DOS –

ответ

0

Адрес, который вы передаете «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-пакетов будет затруднительным. Прочтите статью о дырочной штамповке 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"); 
    } 

} 
+0

Спасибо за советы! –

Смежные вопросы