2010-02-12 6 views
2

Как получить длину принятого пакета UDP? Используя wirehark, я мог видеть правильную длину дейтаграммы. Как я могу напечатать это значение в моей простой программе udp-сервера? Я получаю двоичные данные (непечатаемые символы ascii как данные). Поэтому я не могу использовать strlen (buf), который порождает неправильную длину.Полученная длина пакета UDP

 if (ret=recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *)&si_other, &slen)==-1){ 
      error = ioctl(s, FIONREAD, &value); 
      printf(" from ioctl UDP packet length is : %d error is : %d\n", value, error); 
     } 

Длина пакета udp всегда равна «0» из приведенного выше кода. Любые комментарии?

Я также попытался, как показано ниже

  if (ret=recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *)&si_other, &slen)!=-1){ 
      unsigned short iphdrlen; 
      struct iphdr* iph = (struct iphdr*)buf; 
      iphdrlen =iph->ihl*4; 

      printf("IP version :%d\n", ((unsigned int)((iph->version)))); 
      printf("protocol .. %d\n", ((unsigned int)(iph->protocol))); 
      printf("total len .. %d\n", (ntohs(iph->tot_len))); 
     } 

Приведенный выше код всегда возвращает мне неправильные значения из заголовка IP? Любые комментарии?

Оригинальный файл C включен здесь.

#include "udp_common.h" 

int main(void) 
{ 
     struct sockaddr_in si_me, si_other; 
     int s, i, slen=sizeof(si_other); 
     unsigned char buf[BUFLEN]; 
     int noofbytes=0; 
     int ret=0,error,value; 

     memset(buf, 0, 512); 
     if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) 
       diep("socket"); 

     memset((char *) &si_me, 0, sizeof(si_me)); 
     si_me.sin_family = AF_INET; 
     si_me.sin_port = htons(PORT); 
     si_me.sin_addr.s_addr = htonl(INADDR_ANY); 
     if (bind(s, (struct sockaddr *)&si_me, sizeof(si_me))==-1) 
       diep("bind"); 

     for (i=0; ; i++) 
     //for (i=0; i<NPACK ; i++) 
     { 
       if (ret=recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *)&si_other, &slen)==-1) 
       diep("recvfrom()"); 
       printf(" source port is : %d %d\n", ntohs(si_other.sin_port), slen); 

       unsigned short iphdrlen; 
       struct iphdr* iph = (struct iphdr*)buf; 
       iphdrlen =iph->ihl*4; 

       printf("IP version :%d\n", ((unsigned int)((iph->version)))); 
       printf("protocol .. %d\n", ((unsigned int)(iph->protocol))); 
       printf("total len .. %d\n", (ntohs(iph->tot_len))); 
       error = ioctl(s, FIONREAD, &value); 
       printf(" from ioctl UDP packet length is : %d error is : %d\n", value, error); 
       printf(" Return code from recvfrom is : %d\n", ret); 
       printf("Received packet from %s:%d\nData: %s\n\n", 
       inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf); 

       int j=0; 
       for (j = 0; j <20; j++) 
       { 
         char x = buf[j]; 
         short int i; 
         for (i=1;i<9;i++) 
         { 
           ((x | (1<<8-i)) == x)?printf("1"):printf("0"); 
         } 
         printf(" "); 
       } 
       printf("\n"); 
     } 


     close(s); 
     return 0; 
} 

И выход я receivingis следующим образом:

source port is : 4232 16 
IP version :1 
protocol .. 65 
total len .. 4096 
from ioctl UDP packet length is : 0 error is : 0 
Return code from recvfrom is : 0 
Received packet from 127.0.0.1:4232 
Data: 

00010000 00000001 00010000 00000000 11110001 00010001 00010001 00100100 01000100 01000001 00010001 00100100 01000100 01000000 00000000 00010000 00000000 00010000 10100000 10100000 

Приведенные выше данные расшифровываются совпадающая с моим отправленных данных.

ответ

6

Как вы создали свой сокет? Является ли это сырой сокет (SOCK_RAW) или сокет dgram (SOCK_DGRAM)? Во втором случае вы не получите заголовки ip/udp, а только полезную нагрузку.

Кстати, длина пакета - это возвращаемое значение функции recvfrom - в вашем случае - переменная «ret». Проверьте страницу recvfrom.

+0

Я создал сокет с помощью SOCK_DGRAM. Значение переменной 'ret' всегда равно '0'. Однако, если я вслепую расшифровку данных, я мог правильно видеть исходные отправленные данные. – user271757

+0

Если значение равно 0, то по какой-то причине сокет как раз вышел из строя (и я в порядке, это вам не очень помогает;)) – Patrick

+4

эй, когда вы делаете if (ret = recvfrom (. .. материал ..) == -1), вы забыли пару круглых скобок. Написанный таким образом ret будет влиять на значение «recvfrom (... stuff ..) == -1», а не значение recvfrom. Вы должны написать: «if ((ret = recvfrom (...)) == -1) ... – Patrick

1

Короткий ответ (хотя он уже приведен в комментариях выше): recvfrom возвращает количество полученных байтов.

0

проблема здесь:

if (ret=recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *)&si_other, &slen)==-1) 

переписывают это как:

ret=recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *)&si_other, &slen) 
if (ret==-1) 
{ 
} 

RET будет содержать число байт

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