我正在构建一个非阻塞的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)