как read () может поместить 32-битные целые в буфер? - PullRequest
2 голосов
/ 24 апреля 2020

У меня есть следующая программа (в значительной степени пример из руководства по GNU), которая открывает сокет TCP, ждет подключения и затем распечатывает полученные байты данных. Или так я подумал ...

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define PORT    19000
#define MAXMSG  512


int
make_socket (uint16_t port)
{
  int sock;
  struct sockaddr_in name;

  /* Create the socket. */
  sock = socket (PF_INET, SOCK_STREAM, 0);
  if (sock < 0)
    {
      perror ("socket");
      exit (EXIT_FAILURE);
    }

  /* Give the socket a name. */
  name.sin_family = AF_INET;
  name.sin_port = htons (port);
  name.sin_addr.s_addr = htonl (INADDR_ANY);
  if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
    {
      perror ("bind");
      exit (EXIT_FAILURE);
    }

  return sock;
}

int
read_from_client (int filedes)
{
  char buffer[MAXMSG];
  int nbytes;

  nbytes = read (filedes, buffer, MAXMSG);
  if (nbytes < 0)
    {
      /* Read error. */
      perror ("read");
      exit (EXIT_FAILURE);
    }
  else if (nbytes == 0)
    /* End-of-file. */
    return -1;
  else
    {
      /* Data read. */
      fprintf (stderr, "Server: got message:\n");
      for (int i = 0; i < nbytes; i++) {
        printf(" %02x", buffer[i] & 0xff);
      }
      printf("\n");

      return 0;
    }
}

int
main (void)
{
  extern int make_socket (uint16_t port);
  int sock;
  fd_set active_fd_set, read_fd_set;
  int i;
  struct sockaddr_in clientname;
  size_t size;

  /* Create the socket and set it up to accept connections. */
  sock = make_socket (PORT);
  if (listen (sock, 1) < 0)
    {
      perror ("listen");
      exit (EXIT_FAILURE);
    }

  /* Initialize the set of active sockets. */
  FD_ZERO (&active_fd_set);
  FD_SET (sock, &active_fd_set);

  while (1)
    {
      /* Block until input arrives on one or more active sockets. */
      read_fd_set = active_fd_set;
      if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0)
        {
          perror ("select");
          exit (EXIT_FAILURE);
        }

      /* Service all the sockets with input pending. */
      for (i = 0; i < FD_SETSIZE; ++i)
        if (FD_ISSET (i, &read_fd_set))
          {
            if (i == sock)
              {
                /* Connection request on original socket. */
                int new;
                size = sizeof (clientname);
                new = accept (sock,
                              (struct sockaddr *) &clientname,
                              (socklen_t *)&size);
                if (new < 0)
                  {
                    perror ("accept");
                    exit (EXIT_FAILURE);
                  }
                fprintf (stderr,
                         "Server: connect from host %s, port %hd.\n",
                         inet_ntoa (clientname.sin_addr),
                         ntohs (clientname.sin_port));
                FD_SET (new, &active_fd_set);
              }
            else
              {
                /* Data arriving on an already-connected socket. */
                if (read_from_client (i) < 0)
                  {
                    close (i);
                    FD_CLR (i, &active_fd_set);
                  }
              }
          }
    }
}

Когда я запускаю это, и клиент подключается и отправляет данные, это выглядит так:

Server: connect from host 10.6.65.167, port -8348.
Server: got message:
 ffffffcc ffffffdd ffffffee ffffffff 15 27 00 00 04 13 69 00 ffffff9c 00 00 00 00 00 00 00 ffffffb4 ffffffee ffffffb9 3b 00 00 34 30 36 41 38 45 35 41 45 39 35 31 31 31 31 31 31 50 57 32 41 32 45 30 36 45 2d 47 59 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 61 30 31 39 61 38 64 62 64 34 64 65 35 64 66 61 62 63 31 61 65 30 37 39 33 63 30 32 37 62 38 66 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Server: got message:
 ffffffcc ffffffdd ffffffee ffffffff 15 27 00 00 04 13 69 00 ffffff9c 00 00 00 00 00 00 00 ffffffb4 ffffffee ffffffb9 3b 00 00 34 30 36 41 38 45 35 41 45 39 35 31 31 31 31 31 31 50 57 32 41 32 45 30 36 45 2d 47 59 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 61 30 31 39 61 38 64 62 64 34 64 65 35 64 66 61 62 63 31 61 65 30 37 39 33 63 30 32 37 62 38 66 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...and so on...

Почему существуют 32-битные "байты" в моем буфере? Как они вообще туда попали? Когда я смотрю на сетевой трафик c в Wireshark, первые 4 байта - это "cc", "dd", "ee" и "ff", как и ожидалось. Я в замешательстве.

1 Ответ

1 голос
/ 24 апреля 2020

все в порядке с полученными данными.

У вас возникла проблема с интерпретацией данных в вашей памяти.

Я уверен, что вы знакомы с концепцией объединения.

union {
    int8_t sb[4];
    uint8_t ub[4];
    int16_t ss[2];
    uint16_t us[2];
    float f;
} z;

предположим, что вы заполняете эту переменную из потока сокетов.

read (d, &z, sizeof(z));

вопрос в том, что находится в этой переменной?

ответ: как вам угодно.

если вам нужно интерпретировать его как 4 байта со знаком, то вы можете адресовать свои данные как z.sb [0], z.sb [1], z.sb [2], z.sb [3]

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

Но важно, как вы интерпретировать данные, когда вы получили их из памяти. Таким образом, вы можете объявить ваш буфер как:

unsigned char buffer[MAXMSG];

или использовать указатель на uint8_t для адресации отдельных байтов в вашем буфере.

char buffer[MAXMSG];
uint8_t *b=(uint8_t *)buffer;

for (int i = 0; i < nbytes; i++) {
 printf(" %02x", b[i]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...