我正在尝试为客户端编写C程序,该程序可以使用TCP从服务器下载文件。客户端从服务器接收文件后,将打印并保存文件内容。要编译客户端程序,它需要服务器的IP地址和端口号。我在Linux中实现了它,但是在收到文本后显示0。保存的文本文件是相同的。我不知道如何仅输出文本。接收缓冲区中可能有错误吗?
服务器代码:
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pthread.h>
#define portnum 12345
#define FILE_SIZE 500
#define BUFFER_SIZE 1024
void *client_fun(void * fd);
int main()
{
int new_fd;
pthread_t thread_id;
int server_fd=socket(AF_INET,SOCK_STREAM,0);
if(-1==server_fd)
{
perror("socket");
exit(1);
}
struct sockaddr_in server_addr;
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portnum);
(server_addr.sin_addr).s_addr=htonl(INADDR_ANY);
if(-1==bind(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)))
{
perror("bind");
close(server_fd);
exit(6);
}
if(-1==listen(server_fd,5))
{
perror("listen");
close(server_fd);
exit(7);
}
while(1)
{
struct sockaddr_in client_addr;
int size=sizeof(client_addr);
new_fd=accept(server_fd,(struct sockaddr *)&client_addr,&size);
if(new_fd < 0)
{
perror("accept");
continue;
}
printf("accept client ip锛?s:%d\n",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);
//printf("new_fd=%d\n",new_fd);
if (new_fd > 0)
{
pthread_create(&thread_id, NULL, client_fun, (void *)&new_fd);
pthread_detach(thread_id);
}
}
close(server_fd);
return 0;
}
void *client_fun(void *arg)
{
int new_fd = *((int *)arg);
int file2_fp;
int len;
char buffer[BUFFER_SIZE];
memset( buffer,0, sizeof(buffer) );
while(1)
{
if((len=recv(new_fd, buffer, sizeof(buffer), 0)) <= 0)
{
continue;
}
char file_name[FILE_SIZE];
memset( file_name,0, sizeof(file_name) );
strncpy(file_name, buffer, strlen(buffer)>FILE_SIZE?FILE_SIZE:strlen(buffer));
memset( buffer,0, sizeof(buffer) );
printf("Client requests file %s\n", file_name);
if( strcmp(file_name,"exit")==0 )
{
break;
}
file2_fp = open(file_name,O_RDONLY,0777);
if(file2_fp<0)
{
printf("File %s Not Found\n", file_name);
char* err_info = "File not found\n";
if (write(new_fd, err_info, sizeof(err_info)) < 0)
{
printf("Send error information failed\n");
break;
}
continue;
}
else
{
int length = 0;
memset( buffer,0, sizeof(buffer) );
while( (length = read(file2_fp, buffer, sizeof(buffer))) > 0 )
{
if( write(new_fd, buffer, length) < 0)
{
printf("Send File %s Failed.\n", file_name);
break;
}
memset( buffer,0, sizeof(buffer) );
}
close(file2_fp);
printf("Transfer file %s successfully!\n", file_name);
}
}
close(new_fd);
}
客户代码:
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pthread.h>
int main(int argc, char *argv[])
{
int sockfd = 0;
char recvBuff[1024];
char file_name[500];
char *serverIP=argv[1];
int portno=atoi(argv[2]);
printf("IP Addresses: %s Port Number: %s\n", argv[1], argv[2]);
memset(recvBuff,'0',sizeof(recvBuff));
struct sockaddr_in server_addr;
/* Creat a socket*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/*Initialize sockaddr_in structure*/
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portno);
(server_addr.sin_addr).s_addr=inet_addr(serverIP);
/*Attempt a connection*/
printf("Connect status: ");
if (connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr))<0)
{
printf("fail\n");
return 0;
}
printf("success\n");
/*Request file from server*/
while(1)
{
printf("Input the file name to be requested from the server: ");
fgets(file_name,500, stdin);
char *p=strchr(file_name,'\n');
if (p) *p=0;
if (send(sockfd, file_name, strlen(file_name), 0)<0)
{
printf("Send failed.\n");
break;
}
printf("Send success.\n");
if (strcmp(file_name,"exit")==0)
break;
int length=0;
printf("Send status: ");
if (length=read(sockfd, recvBuff, sizeof(recvBuff))<0)
{
printf("fail\n");
continue;
}
else if (strcmp(recvBuff,"File not found\n")==0)
{
printf("fail\n");
continue;
}
else
{
printf("success\n");
/*Create file where text will be stored*/
FILE *fp;
fp=fopen("received_file.txt","w");
printf("Open file status: ");
if (fp==NULL)
{
printf("fail\n");
continue;
}
printf("success\n");
printf("Received text: ");
if (fprintf(fp, "%s", recvBuff)<0)
{
printf("Save status: fail\n");
continue;
}
fflush(fp);
printf("%s",recvBuff);
memset(recvBuff,0,1024);
while ((length=read(sockfd, recvBuff, sizeof(recvBuff)))>0)
{
if (fprintf(fp, "%s", recvBuff)<0)
{
printf("Save status: fail\n");
break;
}
fflush(fp);
printf("%s",recvBuff);
memset(recvBuff,0,1024);
}
printf("Save status: success");
}
}
}
另一个问题是,客户端应该一直请求文件,直到发送“退出”为止。但是在收到第一个文件后,它不再要求客户端输入文件名。循环出了什么问题?
最佳答案
你有几个问题。
首先:-比较运算符的优先级高于赋值,因此长度获得FALSE(0)值,而不是接收到的数据的实际数量
if (length=read(sockfd, recvBuff, sizeof(recvBuff))<0)
它应该是:
if ((length=read(sockfd, recvBuff, sizeof(recvBuff)))<0)
秒:您正在使用零终止的字符串进行操作,但是您没有从服务器发送零('\0'),并且客户端未在数据块的末尾设置它。
因此,您需要在此处在客户端显式设置它
if ((length=read(sockfd, recvBuff, sizeof(recvBuff)))<0)
{
printf("fail\n");
continue;
}
else if (strcmp(recvBuff,"File not found\n")==0)
{
printf("fail\n");
continue;
}
else
{
recvBuff[length]='\0';
和这里:
while ((length=read(sockfd, recvBuff, sizeof(recvBuff)))>0){
recvBuff[length]='\0';
关于c - 使用TCP从服务器下载文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58957234/