程序:在这个项目中,我必须读取客户端程序中的文件,并将其发送到服务器程序
问题:在生成的文件中,我得到了客户端程序中的所有字符,以及最后的一些不需要的字符。
我认为原因是:如果我在要发送的文件中放入15个字符,我会得到正确的输出(请注意,我的缓冲区大小,即我一次发送的字符数是16)。如果我使用14个或更少的字符,我得到1' \ 00'在末尾。如果我使用更少的字符,那么我会得到一个' \ 00'对应于每个缺失的。也许我的' \ 0' (这就是我设置空格,或缓冲区中的额外字符)在输出文件中表示为' \ 00'。
这是客户端程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#define BUFSIZE 16
#define USAGE \
"usage:\n" \
" transferclient [options]\n" \
"options:\n" \
" -s Server (Default: localhost)\n" \
" -p Port (Default: 8888)\n" \
" -o Output file (Default foo.txt)\n" \
" -h Show this help message\n"
/* Main ========================================================= */
int main(int argc, char **argv) {
int option_char = 0;
char *hostname = "127.0.0.1";
unsigned short portno = 8888;
char *filename = "foo.txt";
// Parse and set command line arguments
while ((option_char = getopt(argc, argv, "s:p:o:h")) != -1) {
switch (option_char) {
case 's': // server
hostname = optarg;
break;
case 'p': // listen-port
portno = atoi(optarg);
break;
case 'o': // filename
filename = optarg;
break;
case 'h': // help
fprintf(stdout, "%s", USAGE);
exit(0);
break;
default:
fprintf(stderr, "%s", USAGE);
exit(1);
}
}
/* Socket Code Here */
int sockfd = 0, n = 0;
char recvBuff[BUFSIZE], sendBuff[BUFSIZE];
struct sockaddr_in serv_addr;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0))< 0) {
printf("Error: Could not create socket \n");
return 1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
serv_addr.sin_addr.s_addr = inet_addr(hostname);
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0) {
printf("Error: Connect Failed\n");
return 1;
}
FILE *fp = fopen(filename, "rb");
if(fp == NULL) {
printf("Error: file not found.\n");
return 0;
}
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
memset(sendBuff, '\0', BUFSIZE);
sprintf(sendBuff, "%d", size);
write(sockfd, sendBuff, strlen(sendBuff));
printf("size: %d\n", size);
memset(sendBuff, '\0', BUFSIZE);
int temp = fread(sendBuff, 1, BUFSIZE, fp);
while(temp > 0) {
write(sockfd, sendBuff, BUFSIZE);
memset(sendBuff, '\0', BUFSIZE);
temp = fread(sendBuff, 1, BUFSIZE, fp);
}
fclose(fp);
printf("done sending data to server.\n");
memset(recvBuff, '\0', BUFSIZE);
while((n = read(sockfd, recvBuff, BUFSIZE)) > 0) {
recvBuff[n] = '\0';
if(fputs(recvBuff, stdout) == EOF) {
printf("Error: Fputs error\n");
}
printf("\n");
}
if( n < 0) {
printf("Read Error\n");
}
return 0;
}
这是服务器程序:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#if 0
/*
* Structs exported from netinet/in.h (for easy reference)
*/
/* Internet address */
struct in_addr {
unsigned int s_addr;
};
/* Internet style socket address */
struct sockaddr_in {
unsigned short int sin_family; /* Address family */
unsigned short int sin_port; /* Port number */
struct in_addr sin_addr; /* IP address */
unsigned char sin_zero[...]; /* Pad to size of 'struct sockaddr' */
};
/*
* Struct exported from netdb.h
*/
/* Domain name service (DNS) host entry */
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
}
#endif
#define BUFSIZE 4096
#define CLIENTBUFSIZE 16
#define USAGE \
"usage:\n" \
" transferserver [options]\n" \
"options:\n" \
" -p Port (Default: 8888)\n" \
" -f Filename (Default: bar.txt)\n" \
" -h Show this help message\n"
int num_of_digits(int num) {
if(num <= 0) printf("Error: size <= 0.\n");
if(num <= 0) exit(1);
int n = 0;
while(num > 0) {
n++;
num /= 10;
}
return n;
}
int main(int argc, char **argv) {
int option_char;
int portno = 8888; /* port to listen on */
char *filename = "bar.txt"; /* file to transfer */
// Parse and set command line arguments
while ((option_char = getopt(argc, argv, "p:f:h")) != -1){
switch (option_char) {
case 'p': // listen-port
portno = atoi(optarg);
break;
case 'f': // listen-port
filename = optarg;
break;
case 'h': // help
fprintf(stdout, "%s", USAGE);
exit(0);
break;
default:
fprintf(stderr, "%s", USAGE);
exit(1);
}
}
/* Socket Code Here */
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[BUFSIZE], recvBuff[BUFSIZE];
listenfd = socket(AF_INET, SOCK_STREAM, 0);
printf("socket retrieve success\n");
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));
if(listen(listenfd, 5) == -1) {
printf("Failed to listen\n");
return -1;
}
int size, temp;
while(1) {
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); // accept awaiting request
memset(recvBuff, '\0', BUFSIZE);
read(connfd, recvBuff, BUFSIZE);
sscanf(recvBuff, "%d", &size);
temp = strlen(recvBuff) - num_of_digits(size);
size -= temp;
printf("size: %d\n", size);
printf("Data from client:\n%s", (recvBuff + num_of_digits(size)));
FILE * fp = fopen(filename, "wb");
int temp;
while(size > 0) {
read(connfd, recvBuff, CLIENTBUFSIZE);
printf("%s", recvBuff);
temp = fwrite(recvBuff, 1, CLIENTBUFSIZE, fp);
size -= temp;
printf("temp: %d\n", temp);
printf("Remaining data: %d\n", size);
}
fclose(fp);
printf("size: %d\n", size);
printf("\n\nFinished reading from client.\n");
strcpy(sendBuff, "Message from server: your message has been recieved.");
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
return 0;
}
这里是输入文件内容:
12345678901234
这里是输出文件内容:
12345678901234
\ 00
答案 0 :(得分:1)
read()
系统调用返回读取的字节数(或-1表示错误)。您将结果丢弃并将CLIENTBUFSIZE
字节的整个缓冲区写入您的文件,即使您发送的字节少于16个字节。