测试非阻塞UDP套接字时中止的过程

时间:2018-07-09 22:03:26

标签: c sockets memory memory-management asyncsocket

我正在构建一个非阻塞的UDP套接字客户端/服务器对。简介是客户端通过流量整形器向服务器发送txt文件,服务器接收该文件,将其接收的内容写入文件,然后以<Run number>/<Packet number>格式发送回“ ACK”。我要发送的文件是1048576字节,所有文件都压缩为string.txt,您将在下面看到。我还将文件划分为每个1024个字节的数据包(1024个数据包),并设置发送/接收确认时间。现在,我遇到了一个问题。我尝试发送一个相对较小的2048字节文件(2个数据包),并且一切正常。但是,当我尝试发送此巨大文件时,出现corrupted_size vs. prev_size错误。请参阅下面的完整错误。我知道这是一个巨大的飞跃,但我希望它仍然能够正常工作。关键点:我不需要每个包都到达。我只需要相当数量的内存,而不会出现内存错误。我已尝试调试所有可能的方法,但无济于事。我无法修复该愚蠢的错误。我正在Linux Ubuntu 16.04 BTW上运行。

谢谢。

服务器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <limits.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>

#define ITOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 2)

void error(const char *msg, const char *detail);
void PrintSocketAddress(const struct sockaddr *address, FILE *stream);
void SIGIOHandler(int signalType);
char * itoa_base(char *s, int x, int base);

#define ITOA(x,b) itoa_base((char [ITOA_BASE_N]){0} , (x), (b))

int sock, run, acknum, maxpack; // GLOBAL for signal handler

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

  if (argc != 5)
    error("Parameter(s)", "<Server Port/Service> <Number of ACKs> <Maximum packet length> <Number of trials>");

  struct sockaddr_in servAddr;
  in_port_t service = atoi(argv[1]);
  acknum = atoi(argv[2]);
  maxpack = atoi(argv[3]);
  int trials = atoi(argv[4]); // must coordinate with client
  run = 0;

  sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (sock < 0)
    error("socket() failed", "");

  memset(&servAddr, 0, sizeof(servAddr));
  servAddr.sin_family = AF_INET;
  servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servAddr.sin_port = htons(service);

  if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
    error("bind() failed", "");

  struct sigaction handler;
  handler.sa_handler = SIGIOHandler;
  if (sigfillset(&handler.sa_mask) < 0)
    error("sigfillset() failed", "mask not set");
  handler.sa_flags = 0;

  if (sigaction(SIGIO, &handler, 0) < 0)
    error("sigaction() failed", "SIGIO behavior unable to be modified");

  if (fcntl(sock, F_SETOWN, getpid()) < 0)
    error("Unable to set process owner to us", "");

  if (fcntl(sock, F_SETFL, O_NONBLOCK | FASYNC) < 0)
    error(
        "Unable to put client sock into non-blocking/async mode", "");

  for (;;) {
    if (run == trials) {
      close(sock);
      exit(0);
    }
    printf(".");
    fflush(stdout);
    sleep(1);
  }
}

void error(const char *msg, const char *detail) {
  fputs(msg, stderr);
  if (*detail != '\0') {
    fputs(": ", stderr);
    fputs(detail, stderr);
  }
  fputc('\n', stderr);
  exit(1);
}

void SIGIOHandler(int signalType) {
  printf("\n");
  fclose(fopen("output.txt", "wb"));
  struct sockaddr_in clntAddr;
  socklen_t clntLen = sizeof(clntAddr);
  ssize_t numBytes;
  int packets = 0;
  FILE *fp = fopen("output.txt", "ab");
  if (fp == NULL)
    error("Error opening file", "");
  char buffer[maxpack];
  char *output = malloc(maxpack * sizeof(char));
  if (output == NULL)
    error("malloc() failed", "");
  memset(buffer, 0, sizeof(buffer));
  memset(output, 0, sizeof(output));
  do {
    numBytes = recvfrom(sock, buffer, maxpack, 0, (struct sockaddr *) &clntAddr, &clntLen);
    if (numBytes < 0) {
      if (errno != EWOULDBLOCK) // only acceptable error
        error("recvfrom() failed", "");
    } else {
      packets += 1;
      if (packets != 1) {
        output = realloc(output, maxpack * packets * sizeof(char));
        if (output == NULL)
          error("realloc() failed", "");
      }
      memmove(output + maxpack * (packets - 1), buffer, strlen(buffer));

      fprintf(stdout, "Handling client ");
      PrintSocketAddress((struct sockaddr *) &clntAddr, stdout);
      fprintf(stdout, "\n\t%s\n", buffer);
    }
  } while (numBytes >= 0);
  run += 1;
  output[strlen(output) - 1] = 0;
  fprintf(fp, "%s", output);

  fclose(fp);
  free(output);

  char *ack = ITOA(run, 10);
  char *append = ITOA(packets, 10);
  strcat(ack, "/");
  strcat(ack, append);
  for (int i = 0; i < acknum; i++) {
    numBytes = sendto(sock, ack, sizeof(ack), 0, (struct sockaddr *) &clntAddr, clntLen);
    if (numBytes < 0)
      error("sendto() failed", "");
  }
}

char * itoa_base(char *s, int x, int base) {
  s += ITOA_BASE_N - 1;
  *s = '\0';
  if (base >= 2 && base <= 36) {
    int x0 = x;
    do {
      *(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[abs(x % base)];
      x /= base;
    } while (x);
    if (x0 < 0) {
      *(--s) = '-';
    }
  }
  return s;
}

客户:

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

static const unsigned int TIMEOUT_SECS = 2; // Seconds between retransmits

void error(const char *msg, const char *detail);

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

  if ((argc < 6) || (argc > 7))
    error("Parameter(s)", "<Server Address/Name> <Echo File> <Server Port/Service> <Maximum packet length> <Number of trials> [<Seconds between trials>]");

  char *server = argv[1];
  FILE *fp = fopen(argv[2], "rb");
  if (fp == NULL)
    error("Error opening file", "");

  fseek(fp, -1, SEEK_END);
  unsigned long stringlen = (getc(fp) == '\n' ? (ftell(fp) - 1) : ftell(fp));
  rewind(fp);

  char *string = malloc(stringlen * sizeof(char));
  for (int i = 0; i < stringlen; i++) {
    *(string + i) = fgetc(fp);
  }
  printf("%lu\n", stringlen);

  fclose(fp);

  in_port_t service = atoi(argv[3]);
  int maxpack = atoi(argv[4]);
  int trials = atoi(argv[5]); // must coordinate with server
  if (trials < 1)
    error("invalid trials parameter", "entered a nonpositive number");
  int sleeptime = (argc == 7) ? atoi(argv[6]) : 5;

  int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (sock < 0)
    error("socket() failed", "");

  struct timeval timeout;
  timeout.tv_sec = TIMEOUT_SECS;
  timeout.tv_usec = 0;
  if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, sizeof(timeout)) < 0)
    error("setsockopt() failed", "");
  if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, sizeof(timeout)) < 0)
    error("setsockopt() failed", "");

  struct sockaddr_in servAddr;
  memset(&servAddr, 0, sizeof(servAddr));
  servAddr.sin_family = AF_INET;
  int rc = inet_pton(AF_INET, server, &servAddr.sin_addr.s_addr);
  if (rc == 0)
    error("inet_pton() failed", "invalid address string");
  else if (rc < 0)
    error("inet_pton() failed", "");
  servAddr.sin_port = htons(service);

  for (int num = 0; num < trials; num++) {
    struct timespec start, end;
    uint64_t diff;
    ssize_t numBytes;
    for (int i = 0; i < (int) ceil((double) stringlen / maxpack); i++) {
      if (i == 0)
        clock_gettime(CLOCK_MONOTONIC, &start);
      numBytes = sendto(sock, string + i * maxpack, maxpack, 0, (struct sockaddr* ) &servAddr, sizeof(servAddr));
      if (numBytes < 0)
        error("sendto() failed", "");
    }

    struct sockaddr_in fromAddr;
    socklen_t fromAddrlen = sizeof(fromAddr);
    char buffer[strlen(argv[3]) + 1];
    memset(&buffer, 0, sizeof(buffer));
    do {
      numBytes = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *) &fromAddr, &fromAddrlen);
      if (numBytes < 0)
        error("recvfrom() failed", "");
      buffer[numBytes] = '\0';
    } while (atoi(buffer) == num);

    clock_gettime(CLOCK_MONOTONIC, &end);
    diff = 1000000000L * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec;

    printf("Received: %s\n", buffer);
    printf("Time: %f ms\n", (double) (diff / (double) 1000000));
    sleep(sleeptime);
  }

  free(string);
  close(sock);

  exit(0);
}

void error(const char *msg, const char *detail) {
  fputs(msg, stderr);
  if (*detail != '\0') {
    fputs(": ", stderr);
    fputs(detail, stderr);
  }
  fputc('\n', stderr);
  exit(1);
}

错误:

*** Error in `./test.c': corrupted size vs. prev_size: 0x08122970 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67377)[0xb759d377]
/lib/i386-linux-gnu/libc.so.6(+0x6d2f7)[0xb75a32f7]
/lib/i386-linux-gnu/libc.so.6(+0x6e48a)[0xb75a448a]
./test.c[0x80490c1]
[0xb7709404]
[0xb7709428]
/lib/i386-linux-gnu/libc.so.6(nanosleep+0x20)[0xb75e63a0]
/lib/i386-linux-gnu/libc.so.6(sleep+0x6d)[0xb75e62fd]
./test.c[0x8048da3]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xb754e637]
./test.c[0x8048a31]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:01 3145801    /home/ccnx/cgood/New-Sender-Receiver/Book Code/test.c
0804a000-0804b000 r--p 00001000 08:01 3145801    /home/ccnx/cgood/New-Sender-Receiver/Book Code/test.c
0804b000-0804c000 rw-p 00002000 08:01 3145801    /home/ccnx/cgood/New-Sender-Receiver/Book Code/test.c
08122000-08164000 rw-p 00000000 00:00 0          [heap]
b73e3000-b73ff000 r-xp 00000000 08:01 2490445    /lib/i386-linux-gnu/libgcc_s.so.1
b73ff000-b7400000 rw-p 0001b000 08:01 2490445    /lib/i386-linux-gnu/libgcc_s.so.1
b7400000-b7421000 rw-p 00000000 00:00 0 
b7421000-b7500000 ---p 00000000 00:00 0 
b7535000-b7536000 rw-p 00000000 00:00 0 
b7536000-b76e6000 r-xp 00000000 08:01 2490387    /lib/i386-linux-gnu/libc-2.23.so
b76e6000-b76e8000 r--p 001af000 08:01 2490387    /lib/i386-linux-gnu/libc-2.23.so
b76e8000-b76e9000 rw-p 001b1000 08:01 2490387    /lib/i386-linux-gnu/libc-2.23.so
b76e9000-b76ec000 rw-p 00000000 00:00 0 
b7707000-b7709000 rw-p 00000000 00:00 0 
b7709000-b770a000 r-xp 00000000 00:00 0          [vdso]
b770a000-b772d000 r-xp 00000000 08:01 2490382    /lib/i386-linux-gnu/ld-2.23.so
b772d000-b772e000 r--p 00022000 08:01 2490382    /lib/i386-linux-gnu/ld-2.23.so
b772e000-b772f000 rw-p 00023000 08:01 2490382    /lib/i386-linux-gnu/ld-2.23.so
bfb49000-bfb6a000 rw-p 00000000 00:00 0          [stack]
Handling client 172.168.4.101-37691Aborted (core dumped)

0 个答案:

没有答案