gpt4 book ai didi

c - 使用TCP从服务器下载文件

转载 作者:行者123 更新时间:2023-12-03 12:07:56 24 4
gpt4 key购买 nike

我正在尝试为客户端编写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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com