Использование htonl () и ntonhl () для неподписанного символа - PullRequest
1 голос
/ 29 июля 2011

Я вставляю код моего клиента и сервера ниже. Моя программа работает нормально, за исключением того, что я пытаюсь отправить IP-адрес в поле src и dest, и по какой-то причине, даже если я отправляю его как 131.199.166.232, он печатается как 232.166.199.131. Но остальные значения моего пакета печатаются надлежащим образом. Я использовал memcpy (), поэтому я чувствую, что это memcpy, что где-то я сделал неправильно, но в руководстве Биджа, поскольку есть раздел @ порядок байтов в разных компьютерных архитектурах ..... Я не использовал htonl () и все, так что, возможно, это из-за этого. Пожалуйста, направьте меня туда, где я иду не так. Также, пожалуйста, скажите мне, как я отправляю данные, как использовать функцию htonl () в моем коде .... Заранее спасибо.

Клиент:

       #include <stdio.h>
     #include <stdlib.h>
     #include <string.h>
     #include <math.h>
     #include <sys/types.h>
     #include <sys/socket.h>
     #include <netinet/in.h>
     #include <netdb.h>
     #define MAXPROFILES  2

    int main(int argc, char *argv[])

  {
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    unsigned char buf[1024];
    unsigned int srcAddress = 2193598184;
    unsigned int destAddress = 2193598182;

   struct profile_t
 {
   unsigned char length;
   unsigned char type;
   unsigned char *data;
 };

   typedef struct profile_datagram_t
 {
unsigned char src[4];
unsigned char dst[4];
unsigned char ver;
unsigned char n;
struct profile_t profiles[MAXPROFILES];
 } header;


    header outObj;

    int j =0;
    int i =0;
   // for loop for doing the malloc so that we can allocate memory to all profiles
    for(i=0;i<MAXPROFILES;i++){
outObj.profiles[i].data = malloc(5);
  }


    for(i=3;i>=0;i--){
outObj.src[i] = (srcAddress >> (i*8)) & 0xFF;
outObj.dst[i] = (destAddress >> (i*8)) & 0xFF;
printf("%d",outObj.src[i]);
 }
    outObj.ver = 1;
    outObj.n = 2;

    memcpy(buf,&outObj.src,4);
    memcpy(buf+4,&outObj.dst,4);
    memcpy(buf+8,&outObj.ver,1);
    memcpy(buf+9,&outObj.n,1);


    outObj.profiles[0].length = 5;
    outObj.profiles[0].type = 1;
    outObj.profiles[1].length = 5;
    outObj.profiles[1].type = 2;

    for(i=0;i<MAXPROFILES;i++){
for(j=0;j<5;j++){
    outObj.profiles[i].data[j] = j+1;
}

}

    int k = 10;

        // for loop to do memcopy of length,type and data.
    for(i=0;i<MAXPROFILES;i++){
memcpy(buf+k,&outObj.profiles[0].length,1);
memcpy(buf+k+1,&outObj.profiles[0].type,1);
memcpy(buf+k+2,outObj.profiles[0].data,5);
k +=7;

}

   if (argc < 3) {
   fprintf(stderr,"usage: %s hostname port\n", argv[0]);
   exit(0);
}
   portno = atoi(argv[2]); //Convert ASCII to integer
   sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor


   if (sockfd < 0)
   error("ERROR DETECTED !!! Problem in opening socket\n");

   server = gethostbyname(argv[1]);
   if (server == NULL) {
   fprintf(stderr,"ERROR DETECTED !!!, no such server found \n");
    exit(0);
}

  bzero((char *) &serv_addr, sizeof(serv_addr)); //clear the memory for server address

  serv_addr.sin_family = AF_INET;
  bcopy((char *)server->h_addr,
        (char *)&serv_addr.sin_addr.s_addr,
     server->h_length);

  serv_addr.sin_port = htons(portno);

  printf("Client 1 trying to connect with server host %s on port %d\n", argv[1], portno);


  if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
  error("ERROR in connection");

      printf("SUCCESS !!! Connection established \n");


   if (write(sockfd, buf, k) < 0)
   {
  error("Write error has occured ");
   }


  return 0;

Сервер:

          #include <stdio.h>
           #include <stdlib.h>
           #include <string.h>
           #include <sys/types.h>
           #include <sys/socket.h>
           #include <netinet/in.h>
           #define MAXPROFILES  2

           int main(int argc, char *argv[])
        {
           int sockfd, newsockfd, portno, clilen;
           struct sockaddr_in serv_addr, cli_addr;
           unsigned char buf[1024];
           int my_data2[10] = {1,3,9,10};
           int my_data[10] = {1,2,3,4,5};
       int myDataBinary[500] = {0};
       int myDataBinary2[500] = {0};
       int recData[500] = {0};
       int index1=0;


       struct profile_t
        {
        unsigned char length;
        unsigned char type;
        unsigned char *data;
        };

            typedef struct profile_datagram_t
       {
        unsigned char src[4];
        unsigned char dst[4];
        unsigned char ver;
        unsigned char n;
       struct profile_t profiles[MAXPROFILES];
        } header;


            header outObj;

        int j =0;
        int i =0;



            if (argc < 2) {
            fprintf(stderr,"usage: %s port_number1",argv[0]);
            exit(1);
         }
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd < 0)
            error("ERROR DETECTED !!! Problem in opening socket");

            bzero((char *) &serv_addr, sizeof(serv_addr));
            portno = atoi(argv[1]);

            serv_addr.sin_family = AF_INET;
            serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
            serv_addr.sin_port = htons(portno);

            if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
            error("ERROR DETECTED !!! There was a problem in binding");

            listen(sockfd, 10);
            clilen = sizeof(cli_addr);



             printf("Server listening on port number %d...\n", serv_addr.sin_port);

             newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);

             if (newsockfd < 0)
         error("ERROR DETECTED !!! the connection request was not accepted");

         int rc = read(newsockfd,buf,100);
         if(rc < 0){
     printf("error");
      }
         else {
        printf("success %d",rc);
      }


      memcpy(&outObj.src,buf+0,4);
      memcpy(&outObj.dst,buf+4,4);
      memcpy(&outObj.ver,buf+8,1);
      memcpy(&outObj.n,buf+9,1);

          printf("\nsrc ip = ");
          for(int i=0;i<4;i++){
       printf("%d ",outObj.src[i]);
       }

          printf("\ndest ip = ");
          for(int i=0;i<4;i++){
         printf("%d ",outObj.src[i]);
        }

         printf("\nversion = %d",outObj.ver);
         printf("\nnumber = %d",outObj.n);

         int k = 10;

         for(i=0;i<outObj.n;i++){
     memcpy(&outObj.profiles[i].length,buf+k,1);
     memcpy(&outObj.profiles[i].type,buf+k+1,1);
     outObj.profiles[i].data = malloc(outObj.profiles[i].length);
     memcpy(outObj.profiles[i].data,buf+k+2,5);
        k +=7;
       }

         for(int i=0;i<outObj.n;i++){
    printf("\nMessage %d :",i+1);
    printf("\nLength : %d",outObj.profiles[i].length);
    printf("\nType : %d",outObj.profiles[i].type);
    for(int j=0;j<5;j++){
        printf("\ndata %d : %d",j,outObj.profiles[i].data[j]);
    }
}


         for(int i=0; i<sizeof(my_data)/sizeof(int);i++)
      {
     if(my_data[i] > 0){
    index1 = my_data[i];
    myDataBinary[index1] = 1;
    printf("my data %d = %d\n",index1,myDataBinary[index1]);
}
}

       for(int i=0; i<sizeof(my_data2)/sizeof(int);i++)
{
    if(my_data2[i] > 0){
        index1 = my_data2[i];
        myDataBinary2[index1] = 1;
        printf("my data %d = %d\n",index1,myDataBinary2[index1]);
    }
}


         int sumRecievedData = 0;
         int sumMyData = 0;
         int sumMultpliedData = 0;
         float Cov =0;
         float sdMyData = 0;
         float sdRecievedData =0;
         int n = 500;
         float rho;

                for(int i=0;i<outObj.n;i++){
              index1=0;
              for (int j=0; j<outObj.profiles[i].length;j++) {

               if(outObj.profiles[i].data[j] > 0){
               index1 = outObj.profiles[i].data[j];
               recData[index1] = 1;
              printf("rec data %d = %d\n",index1,recData[index1]);
       }
     }
   }


        return 0;

    }

Ответы [ 2 ]

1 голос
/ 29 июля 2011

IP-адрес действительно является массивом unsigned char.

uchar ip[] = {127,0,0,1};

Является точным представлением адреса обратной связи. Но массив из четырех байтов и int на самом деле не так уж и велики; с одним исключением endiannes ! Итак, предположим, что я создаю int, который представляет этот IP. Наивный подход может быть:

 int ip = (127<<24)|(0<<16)|(0<<8)|(1)

Конечно, на машинах с прямым порядком байтов , таких как x86, и вооружите его так:

char *char_ip = (void*)&ip;

и итерация по этому массиву приведет к:

1, 0, 0, 127

Но на машине с прямым порядком байтов , такой как PowerPC или SPARC, у нас будет то, что мы ожидаем,

127, 0, 0, 1

Big endian также известен как «сетевой порядок байтов», что означает n в htonl: «host to network long». Эти функции часто используются при чтении или записи целых чисел по сети. Предположим, сервер хочет отправить клиенту какой-нибудь номер:

uint32_t important = htonl(42);
write(client, &important, sizeof important);

Затем, чтобы прочитать это, клиент идет:

uint32_t important;
read(server, &important, sizeof important);
important = ntohl(important);

Причина, по которой ваш IP-адрес был перевернут, заключалась в том, что IP-адреса, как ожидается, должны быть в сетевом порядке байтов, но вместо этого у вас был порядок байтов. htonl на ip типа int перевернет его для вас.

0 голосов
/ 29 июля 2011

Это слишком много кода для меня, чтобы читать, но если вы просто хотите создать байтовый массив для сериализации, вам вообще не нужны никакие специальные функции, вы можете просто написать его алгебраически:

unsigned char buf[sizeof(uint_type)];

uint_type value;

for (size_t i = 0; i != sizeof(uint_type); ++i)
{
  // Little-endian
  buf[i] = value >> (i * CHAR_BIT);

  // Big-endian
  buf[sizeof(uint_type - i - 1)] = value >> (i * CHAR_BIT);
}

Обратите внимание, что этот код не зависит от порядкового номера вашей системы.


Поскольку вы спросили, функции htonl / ntohl предназначены для непосредственного обращения с uint32_t целыми числами без явных массивов символов:

uint32_t value;

myfile.read((char*)&value, sizeof(value));  // network endianness
value = ntohl(value);                       // host endianness

/* fiddle fiddle */

value = htonl(value);
yourfile.write((const char*)&value, sizeof(value));

(Более вероятно, что вы будете писать в сокет, а не в файл.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...