2015-03-27 3 views
0

У меня есть аппаратное управление ARM как UDP-сервер, и я общаюсь с ним с помощью кода, написанного на C#. ПК - это клиент UDP. Сервер просто перекликается с данными.Не удается получить данные с UDP-сервера в win32-приложении UDP-сокета

Это нормально работает без каких-либо проблем, и это стабильно.

using System.Net.Sockets; 
using System.Net; 
using System.Text; 
using System; 

namespace UDPSocket 
{ 
    class UDPSender 
    { 
     static void Main(string[] args) 
     { 
      UInt32 i=0; 
      Int32 PORT = 45555; 
      for (; i < 15;) 
      { 
       Console.WriteLine(i++); 
       Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 
        ProtocolType.Udp); 

       IPAddress broadcast = IPAddress.Parse("192.168.0.10"); 

       byte[] sendbuf = Encoding.ASCII.GetBytes("Shriganesh Damle, Infineon Techonologies India Pvt Ltd, Bangalore"); 
       IPEndPoint ep = new IPEndPoint(broadcast, PORT); 

       //Creates a UdpClient for reading incoming data. 
       UdpClient receivingUdpClient = new UdpClient(PORT); 

       s.SendTo(sendbuf, ep); 

       Console.WriteLine("Message sent to the broadcast address"); 

       //Creates an IPEndPoint to record the IP Address and port number of the sender. 
       // The IPEndPoint will allow you to read datagrams sent from any source. 
       IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); 

       // Blocks until a message returns on this socket from a remote host. 
       Byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint); 

       string returnData = Encoding.ASCII.GetString(receiveBytes); 

       Console.WriteLine("This is the message you received " + 
              returnData.ToString()); 
       Console.WriteLine("This message was sent from " + 
              RemoteIpEndPoint.Address.ToString() + 
              " on their port number " + 
              RemoteIpEndPoint.Port.ToString()); 
       //Console.Read(); 
       receivingUdpClient.Close(); 
      } 
      Console.Read(); 
     } 
    } 
} 

Теперь, мне нужен тот же код ПК в приложении Win32 C. Я попробовал код ниже.

/* 
    Simple udp client  
*/ 
#include<stdio.h> 
#include<winsock2.h> 

#pragma comment(lib,"ws2_32.lib") //Winsock Library 

#define SERVER "192.168.0.10" //ip address of udp server 
#define BUFLEN 512 //Max length of buffer 
#define PORT 45555 //The port on which to listen for incoming data 

int main(void) 
{ 
    struct sockaddr_in si_other; 
    int s, slen=sizeof(si_other); 
    char buf[BUFLEN]; 
    char message[BUFLEN]; 
    WSADATA wsa; 

    //Initialise winsock 
    printf("\nInitialising Winsock..."); 
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) 
    { 
     printf("Failed. Error Code : %d",WSAGetLastError()); 
     exit(EXIT_FAILURE); 
    } 
    printf("Initialised.\n"); 

    //create socket 
    if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) 
    { 
     printf("socket() failed with error code : %d" , WSAGetLastError()); 
     exit(EXIT_FAILURE); 
    } 

    //setup address structure 
    memset((char *) &si_other, 0, sizeof(si_other)); 
    si_other.sin_family = AF_INET; 
    si_other.sin_port = htons(PORT); 
    si_other.sin_addr.S_un.S_addr = inet_addr(SERVER); 

    //start communication 
    while(1) 
    { 
     printf("Enter message : "); 
     gets(message); 

     //send the message 
     if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR) 
     { 
      printf("sendto() failed with error code : %d" , WSAGetLastError()); 
      exit(EXIT_FAILURE); 
     } 

     //receive a reply and print it 
     //clear the buffer by filling null, it might have previously received data 
     memset(buf,'\0', BUFLEN); 
     //try to receive some data, this is a blocking call 
     if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR) 
     { 
      printf("recvfrom() failed with error code : %d" , WSAGetLastError()); 
      exit(EXIT_FAILURE); 
     } 

     puts(buf); 
    } 

    closesocket(s); 
    WSACleanup(); 

    return 0; 
} 

Этот код может отправлять на UDP-сервер, и он перекликается. Но recvfrom call будет ждать данных до бесконечного времени. recvfrom блокирует вызов. Я даю правильный IP-адрес и PORT. Тем не менее я не могу получать данные с сервера в приложении Win32. Вы можете помочь?

+1

вместо того, чтобы получать (сообщение), попробуйте указать код сообщения; посмотрите, работает ли это –

+1

Явная ошибка в вашем коде заключается в том, что вы не указали символ «\ 0» в конце messag []. Это означает, что поведение strlen() будет неожиданным. –

+0

Не работает даже после жесткого кодирования :( – SHRI

ответ

1

Если вы хотите получать данные в сокете, вам необходимо привязать его к одному или нескольким локальным адресам и локальному порту. Ваша версия C# достигает этого через new UdpClient(PORT) (обратите внимание на аргумент PORT), но ваша версия C не делает ничего сопоставимого.

После создания сокета, сделать

sockaddr_in localAddr; 

localAddr.sin_family = AF_INET; 
localAddr.sin_port = htons(PORT); 
localAddr.sin_addr.S_un.S_addr = INADDR_ANY; 

bind(s, &localAddr, sizeof(sockaddr_in)); 

и убедитесь, что она возвращает 0, чтобы указать успех.

Альтернативно, версия C будет более параллельной версии C#, если вы создали второй сокет для получения ответа сервера. Я не думаю, что это необходимо сделать в C (в Winsock2, если быть более точным), но возможно, что использование одного и того же сокета для отправки и получения потребует от вас привязки к определенному локальному адресу, а не к INADDR_ANY ,

+0

bind (s, INADDR_ANY, PORT), возвращает код ошибки 10014. Если я изменяю INADDR_ANY на определенный адрес, 192.168 .0.2, я получаю код ошибки 10049. – SHRI

+1

@SHRI, мой плохой, я написал слишком поспешно. Код ошибки 10014 должен быть разрешен моим обновлением выше. –

+0

еще один вопрос: правильно ли UDPClient использовать API 'bind' а не «connect» API? – SHRI

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