read()如何将32位整数放入缓冲区?

时间:2020-04-24 11:27:19

标签: c sockets tcp

我有以下程序(几乎是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位长的“字节”?他们是怎么到达那里的?当我查看Wireshark中的网络流量时,按预期,前4个字节是“ cc”,“ dd”,“ ee”和“ ff”。我很困惑。

1 个答案:

答案 0 :(得分:1)

您收到的数据一切正常。

您对内存中数据的解释有疑问。

我确定您熟悉工会概念。

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));

问题是:那个变量中有什么?

answer:随您喜欢。

如果您需要将其解释为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]);
}
相关问题