#c #linux #sockets #diff #binaryfiles
#c #linux #сокеты #разница #двоичные файлы
Вопрос:
это программа для сервера и клиента передачи файлов
Как серверный, так и клиентский код я запускал нормально. Однако, когда я использовал команду diff для сравнения исходного файла и переданного файла, только двоичные файлы слов test.txt и receivefile.txt отличия» были выведены. Я знаю, что вы можете сравнивать двоичные файлы с помощью cmp, но я должен использовать diff . Как мне изменить код, чтобы я мог сравнить их с помощью команды diff?
серверный код
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFSIZE 4096
#define SERVERPORT 7799
int main(void){
int s_sock, c_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t c_addr_size;
char buf[BUFFSIZE] = {0};
char filename[BUFFSIZE] = {0};
int read_len;
int newfile;
int writefile;
int fileread_len;
s_sock = socket(AF_INET, SOCK_STREAM, 0);
bzero(amp;server_addr, sizeof(server_addr));
int option = 1;
setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, amp;option, sizeof(option));
// already in use error
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVERPORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(s_sock, (struct sockaddr *) amp;server_addr, sizeof(server_addr)) == -1){
perror("bind error");
exit(1);
}
listen(s_sock,1);
c_addr_size = sizeof(struct sockaddr);
c_sock = accept(s_sock, (struct sockaddr *) amp;client_addr, amp;c_addr_size);
if(c_sock == -1){
perror("accept error");
exit(1);
}
read_len = read(c_sock, buf, BUFFSIZE);
if(read_len > 0){
strcpy(filename,buf);
}else{
close(c_sock);
printf("file len error");
}
newfile = open(filename, O_RDONLY);
if(!newfile){
perror("there is no file for open");
exit(1);
}
while((fileread_len=read(newfile, buf, BUFFSIZE)) != 0){
writefile = write(c_sock, buf, BUFFSIZE);
}
close(c_sock);
close(newfile);
close(s_sock);
return 0;
}
клиентский код
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFSIZE 4096
#define SERVERPORT 7799
int main(int argc, char* argv[]){
if(argc != 4){
printf("<Usage : ./hw11c IP PORT FILENAME >n");
}
int c_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t c_addr_size;
char buf[BUFFSIZE] = {0};
char filename[BUFFSIZE] = {0};
int receivefile;
int filenamelen;
int recv_len;
c_sock = socket(AF_INET, SOCK_STREAM, 0);
bzero(amp;server_addr, sizeof(server_addr));
int option = 1;
setsockopt(c_sock, SOL_SOCKET, SO_REUSEADDR, amp;option, sizeof(option));
// already in use
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
strcpy(filename,argv[3]);
filenamelen = strlen(filename);
if(connect(c_sock,(struct sockaddr *)amp;server_addr, sizeof(server_addr)) == -1){
perror("connect error");
exit(1);
}
send(c_sock, filename, filenamelen, 0);
receivefile = open("receivefile.txt", O_CREAT | O_EXCL | O_WRONLY ,0700);
// receivefile = open(filename, O_CREAT | O_EXCL | O_RDWR);
if(!receivefile){
perror("there is no receive file");
exit(1);
}
while((recv_len = recv(c_sock, buf, BUFFSIZE, 0)) != 0)
{
write(receivefile, buf, recv_len);
}
close(receivefile);
close(c_sock);
return 0;
}
Комментарии:
1. ‘read_len = read(c_sock, buf, BUFFSIZE); if(read_len> 0){ strcpy(filename,buf); ‘ В TCP нет сообщений длиннее одного байта. Ваше предположение о том, что все имя файла, не меньше и не больше, будет загружено только одним вызовом recv(), является ложным и опасным.
2. Спасибо за совет. Но имеет ли это какое-либо отношение к этой ошибке? Я спрашиваю, потому что я действительно не знаю.
3. Кто знает? Такая же неспособность корректно и полностью обработать результаты, возвращаемые системными вызовами, применяется к send(), recv() во всем вашем коде: (
4. Как насчет этого для идеи — выполните некоторую отладку / протоколирование. Как насчет распечатки recv_len, чтобы вы могли проверить, сколько байтов было получено?
5. Подождите, что это? ‘while((fileread_len=read(newfile, buf, BUFFSIZE))!= 0){ writefile = write(c_sock, buf, BUFFSIZE);’ ??? Вы читаете ‘fileread_len’ в одной строке, затем записываете байты размера буфера в сокет? Зачем тебе это делать?