c - C TCP客户端-服务器分段故障问题
问题描述
我正在尝试使用 TCP 在 C 中实现客户端-服务器程序以进行练习。服务器应该能够为许多客户端提供服务。客户端请求服务器发送给他们的一些文件。每次客户端结束时,服务器都会因分段错误错误而崩溃。它打印“服务结束”,查看 gdb 它也返回到主函数,但在循环内调用“服务”函数后它从不打印“prova”。
在这里您可以看到我的服务器和我的客户端下方
/*
* TEMPLATE
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <rpc/xdr.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "../errlib.h"
#include "../sockwrap.h"
#define BUFLEN 1024 /* Buffer length */
char *prog_name;
char *err="-ERR\r\n";
void service(int s);
uint32_t getFileCreationTime(char *filename);
int main (int argc, char *argv[])
{
int conn_request_skt; /* passive socket */
uint16_t lport_n, lport_h; /* port used by server (net/host ord.) */
int bklog = 2; /* listen backlog */
int s; /* connected socket */
socklen_t addrlen;
struct sockaddr_in saddr, caddr; /* server and client addresses */
prog_name = argv[0];
if (argc != 2)
{
printf("Usage: %s <port number>\n", prog_name);
exit(1);
}
/* get server port number */
if (sscanf(argv[1], "%" SCNu16, &lport_h)!=1)
err_sys("Invalid port number");
lport_n = htons(lport_h);
/* create the socket */
printf("creating socket...\n");
s = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("done, socket number %u\n",s);
/* bind the socket to any local IP address */
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = lport_n;
saddr.sin_addr.s_addr = INADDR_ANY;
showAddr("Binding to address", &saddr);
Bind(s, (struct sockaddr *) &saddr, sizeof(saddr));
printf("done.\n");
/* listen */
printf ("Listening at socket %d with backlog = %d \n",s,bklog);
Listen(s, bklog);
printf("done.\n");
conn_request_skt = s;
/* main server loop */
for (;;)
{
printf("loop again\n");
/* accept next connection */
addrlen = sizeof(struct sockaddr_in);
s = Accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen);
showAddr("Accepted connection from", &caddr);
printf("new socket: %u\n",s);
/* serve the client on socket s */
service(s);
printf("Prova\n");
}
return 0;
}
uint32_t getFileCreationTime(char *filename)
{
struct stat *attr;
stat(filename, attr);
return attr->st_mtime;
}
void service(int s)
{
char rbuf[BUFLEN+1]; /* reception buffer */
char buf[BUFLEN]; /* sending buffer */
char sbuf[BUFLEN]; /* buffer that will contain the dimension of the file */
int n;
char *get, *filename, filename_stats[20];
size_t len;
uint32_t bsent, dimension, modtime;
FILE *fp;
struct stat * fstatus;
for (;;)
{
n=recv(s, rbuf, BUFLEN-1, 0);
if (n < 0)
{
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
}
else if (n==0)
{
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
}
else
{
rbuf[n]=0;
get = strtok(rbuf, " ");
filename = strtok(NULL, "\r\n");
if(strcmp(get, "GET") == 0)
{
printf("\nA client requested the file '%s'\n", filename);
fp = fopen(filename, "rb");
if (fp == NULL)
{
printf("-ERR\tCould not open the file\n");
if(writen(s, err, 6) != 6)
printf("Write error\n");
}
fseek (fp, 0, SEEK_END);
dimension = ftell (fp);
//dimension--;
fseek (fp, 0, SEEK_SET);
sprintf(sbuf, "+OK\r\n");
printf("Sending:\n%s\n", sbuf);
if(writen(s, sbuf, 5) != 5)
printf("Write error\n");
//printf("Sending:\n%d\n", dimension);
//dimension = htonl(dimension);
//printf("dimension net=%d\n", dimension);
if(writen(s, &dimension, 4) != 4)
printf("Write error\n");
//dimension = ntohl(dimension);
printf("dimension=%d\n", dimension);
bsent=0;
while(bsent!=dimension)
{
if(dimension-bsent < BUFLEN)
{
//printf("bytes to send <BUFLEN\n");
fread (buf, 1, dimension-bsent, fp);
printf("Sending last %d bytes of the file\n", dimension-bsent);
if(writen(s, buf, dimension-bsent) != dimension-bsent)
printf("Write error\n");
bsent+=dimension-bsent;
}
else
{
//printf("bytes to send > BUFLEN\n");
fread (buf, 1, BUFLEN, fp);
//printf("Sending:\n%s\n", buf);
if(writen(s, buf, BUFLEN) != BUFLEN)
printf("Write error\n");
bsent+=BUFLEN;
printf("Bytes sent: %d\n", bsent);
}
}
fclose (fp);
modtime = getFileCreationTime(filename);
printf("Sending:\n%d\n", modtime);
//modtime = htonl(modtime);
if(writen(s, &modtime, 4) != 4)
printf("Write error\n");
printf("File '%s' correctly sent to the requesting client\n", filename);
}
else //invalid request
{
printf("-ERR\tINVALID REQUEST\n");
if(writen(s, err, 6) != 6)
printf("Write error\n");
}
}
}
printf("End of service\n");
return;
}
这是客户:
/*
* TEMPLATE
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <rpc/xdr.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "../errlib.h"
#include "../sockwrap.h"
#define BUFLEN 1024 /* Buffer length */
char *prog_name;
int main (int argc, char *argv[])
{
char buf[BUFLEN]; /* transmission buffer */
char rbuf[BUFLEN]; /* receiving buffer */
char ok[5]; /* buffer used to receive the "+OK" message */
uint16_t tport_n, tport_h; /* server port number (net/host ord) */
char **filenames, *out="_out";
FILE* fp;
size_t len;
int s, result, i;
struct sockaddr_in saddr; /* server address structure */
struct in_addr sIPaddr; /* server IP addr. structure */
ssize_t nreadok, nread;
size_t nleft;
uint32_t breceived , bytes, timestamp;
prog_name = argv[0];
if(argc<4)
{
printf("Error! Usage: %s IP_addr port_number filename1 filename2 filename3 ...\n", prog_name);
return -1;
}
filenames = (char **) malloc(argc*sizeof(char*));
for(i=3; i<argc; i++)
{
filenames[i-3] = (char*) malloc (30*sizeof(char));
strcpy(filenames[i-3], argv[i]);
}
/* input IP address and port of server */
result = inet_aton(argv[1], &sIPaddr);
if (!result)
err_quit("Invalid address");
if (sscanf(argv[2], "%" SCNu16, &tport_h)!=1)
err_quit("Invalid port number");
tport_n = htons(tport_h);
/* create the socket */
printf("Creating socket\n");
s = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("done. Socket fd number: %d\n",s);
/* prepare address structure */
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = tport_n;
saddr.sin_addr = sIPaddr;
/* connect */
showAddr("Connecting to target address", &saddr);
Connect(s, (struct sockaddr *) &saddr, sizeof(saddr));
printf("done.\n");
for(i=3; i<argc; i++)
{
//filename=argv[i];
sprintf(buf, "GET %s\r\n", filenames[i-3]); //creating the request "GET filename"
len = strlen(buf);
printf("\n%s", buf);
if(writen(s, buf, len) != len) //sending the request
{
printf("Write error\n");
}
printf("\nwaiting for response...\n");
//filename=argv[i];
//char rbuf[BUFLEN];
nread = readn(s, rbuf, 5); //receiving "+OK\r\n"
if(nread == 0)
printf("Connection closed\n");
if(rbuf[0] == '-')
{
nread = readn(s, rbuf, 1); //remaining byte of the "-ERR\r\n" message
if(nread==0)
printf("Connection closed\n");
printf("-ERROR! The server could not answer the request\n");
close(s);
return -1;
}
bytes=0;
//printf("Bytes 0=%d\n", bytes);
nread = readn(s, &bytes, 4); //receiving the dimension
if(nread == 0)
printf("Connection closed\n");
//printf("Bytes net=%d\n", bytes);
//bytes = ntohl(bytes);
printf("Dimension of the file = %d\n", bytes);
/*
nread = readn(s, rbuf, bytes-1); //receiving the file
if(nread == 0)
printf("Connection closed\n");
*/
strcat(filenames[i-3], "_copy");
fp = fopen(filenames[i-3], "wb"); //creating the file "filename_out"
if (fp == NULL)
{
printf("Could not open the file\n");
}
else
{
//coping data into the copy of the file
breceived=0;
while(1)
{
rbuf[0]=0;
if(bytes-breceived < BUFLEN)
{
//printf("bytes to receive <BUFLEN\n");
printf("Receiving: %d bytes of the file\n", bytes-breceived);
if(readn(s, rbuf, bytes-breceived) != bytes-breceived)
printf("Connection closed\n");
//printf("receiving:\n%s\n", rbuf);
//fputs(rbuf, fp);
fwrite(rbuf, 1, bytes-breceived, fp);
breceived+=bytes-breceived;
printf("Bytes received: %d\n", breceived);
break;
}
else
{
printf("bytes to receive(>BUFLEN) = %d\n", bytes-breceived);
//printf("receiving:\n%s\n", rbuf);
if(readn(s, rbuf, BUFLEN) != BUFLEN)
printf("Connection closed\n");
//printf("receiving:\n%s\n", rbuf);
//fputs(rbuf, fp);
fwrite(rbuf, 1, BUFLEN, fp);
breceived=breceived+BUFLEN;
printf("Bytes received: %d\n", breceived);
}
}
}
if(rbuf[0] == '-')
{
nread = readn(s, rbuf, 1); //remaining byte of the "-ERR\r\n" message
if(nread==0)
printf("Connection closed\n");
printf("-ERROR! The server could not answer the request\n");
close(s);
return -2;
}
//rbuf[bytes]=0;
nread = readn(s, ×tamp, 4); //receiving the timestamp
if(nread == 0)
printf("Connection closed\n");
//timestamp = ntohl(timestamp);
printf("\nFile received: '%s'\t %d bytes \t last mod: %d\n\n", filenames[i-3], bytes, timestamp);
fclose(fp);
}
printf("Closing the connection\n");
close(s);
return 0;
}
解决方案
推荐阅读
- java - 在数据狗指标中记录销售额
- vue.js - 这个 curl 请求的等效 vue-apollo 选项是什么?
- c++ - C++:铸造成员函数指针
- mysql - MySQL - 基于多态表值的条件查询结果?
- c# - 拦截 HTTP 流量并添加自定义标头
- mercury - Det 中的 Mercury nondet
- python - 如何检测输入和输出文件之间的重复并防止在python中通过csv将重复项添加到输出文件中?
- java - 处理 > 库 > IntelliJ IDEA 上的 SVG 导出
- c# - 删除迁移在 VS 2015 中不起作用
- scala - 需要从字符串中删除第一行,然后在 scala 中删除前两个单词