#c #tcp #server #ip #tcp-ip
#c #tcp #сервер #ip #tcp-ip
Вопрос:
Я не знаю, почему он попадает в бесконечный цикл и не загружает файл, когда я пытаюсь выполнить эту командную строку:
./сервер 2000
./client получить имя файла localhost 2000 256
У меня есть два сомнения. Первый из них заключается в том, почему список файлов содержит несколько точек. Во-вторых, почему я не могу загрузить файл из каталога сервера.
клиентский код
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <arpa/inet.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int file_size;
FILE *received_file;
int remain_data = 0;
ssize_t len;
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
int TamBuffer;
if (argc < 3) {
fprintf(stderr,"usage %s hostname portn", argv[0]);
exit(0);
}
if(strcmp(argv[1],"list")==0){
TamBuffer=atoi(argv[4]);
char *comando = argv[1];
portno = atoi(argv[3]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[2]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such hostn");
exit(0);
}
bzero((char *) amp;serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)amp;serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) amp;serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
n=write(sockfd,comando,strlen(comando));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,TamBuffer);
bzero(buffer,TamBuffer);
n = read(sockfd,buffer,TamBuffer-1);
if (n < 0)
error("ERROR reading from socket");
printf("%sn",buffer);
close(sockfd);
}
if (strcmp(argv[1],"get")==0){
TamBuffer=atoi(argv[5]);
char *comando = argv[1];
portno = atoi(argv[4]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[3]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such hostn");
exit(0);
}
bzero((char *) amp;serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)amp;serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) amp;serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
strcat(comando,argv[2]);
n=write(sockfd,comando,strlen(comando));
if (n < 0)
error("ERROR writing to socket");
/* Receiving file size */
recv(sockfd, buffer, TamBuffer, 0);
file_size = atoi(buffer);
fprintf(stdout, "nFile size : %dn", file_size);
received_file = fopen("newfile", "w");
if (received_file == NULL)
{
fprintf(stderr, "Failed to open file foo --> %sn", strerror(errno));
exit(EXIT_FAILURE);
}
remain_data = file_size;
while (((len = recv(sockfd, buffer, TamBuffer, 0)) > 0) amp;amp; (remain_data > 0))
{
fwrite(buffer, sizeof(char), len, received_file);
remain_data -= len;
int received_byte = len;
fprintf(stdout, "Receive %d bytes and we hope :- %d bytesn", received_byte, remain_data);
}
fclose(received_file);
close(sockfd);
}
return 0;
}
серверный код
#include <errno.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
int sent_bytes = 0; // bytes de envio de arquivo
char file_size[256]; //tamanho do arquivo
struct stat file_stat;
off_t offset;
int remain_data;
ssize_t len;
int fd;
if (argc < 2) {
fprintf(stderr,"ERROR, no port providedn");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) amp;serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) amp;serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) amp;cli_addr,
amp;clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
if(strcmp("list",buffer)==0){
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d)
{
while ((dir = readdir(d)) != NULL)
{
n=write(newsockfd,dir->d_name,strlen(dir->d_name));
n=write(newsockfd, "n",1);
if (n < 0) error("ERROR writing to socketn");
}
closedir(d);
}
}
else {
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
int i;
for(i=0;i<strlen(buffer);i=i 1){
buffer[i]=buffer[3 i];
}
printf("%sn",buffer);
char* FILE_TO_SEND = buffer;
fd = open(FILE_TO_SEND, O_RDONLY);
if (fd == -1)
{
fprintf(stderr, "Error opening file --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Get file stats */
if (fstat(fd, amp;file_stat) < 0)
{
fprintf(stderr, "Error fstat --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
int num_filesize = file_stat.st_size;
fprintf(stdout, "File Size: n%d bytesn", num_filesize);
/* Sending file size */
len = send(newsockfd, file_size, sizeof(file_size), 0);
if (len < 0)
{
fprintf(stderr, "Error on sending greetings --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
printf("teste1/n");
int num_bytes_sent= len;
fprintf(stdout, "Server sent %d bytes for the sizen", num_bytes_sent);
offset = 0;
remain_data = file_stat.st_size;
/* Sending file data */
printf("teste2/n");
while (((sent_bytes = sendfile(newsockfd, fd, amp;offset, 256)) > 0) amp;amp; (remain_data > 0))
{
fprintf(stdout, "1. Server sent %d bytes from file's data, offset is now : %d and remaining data = %dn", sent_bytes, offset, remain_data);
remain_data -= sent_bytes;
fprintf(stdout, "2. Server sent %d bytes from file's data, offset is now : %d and remaining data = %dn", sent_bytes, offset, remain_data);
}
}
close(newsockfd);
close(sockfd);
return 0;
}
Комментарии:
1. Ну, одна вещь сразу ошибочна, порядок по условной оценке неверен в вашем клиентском цикле.
(remain_data > 0)
должно быть проверено первое условие; не последнее. Устраняет ли это вашу проблему или нет, как написано, это неправильно.2. Предлагаю вам использовать отладчик. Это поможет вам гораздо больше в решении этой проблемы и в вашей долгосрочной карьере научиться эффективно использовать отладчик.
3. Я также не вижу, где вы на самом деле заполняете содержимое
file_size
перед отправкой его в 256 байт по каналу с вашего сервера, поэтому, что бы ни получал клиент, это мусор. Он ожидает, что завершенная строка цифр будет соответствовать размеру файла.