将文件从客户端发送到服务器
Send a file from Client to a Server
我正在用 C 开发一个 client/server 程序。服务器向客户端发送一个 txt 文件,但名称好像已损坏。内容不错,就是名字不好。
谁能告诉我为什么?谢谢!
这是发送文件的代码:
fd = open(appoggio1, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "unable to open '%s': %s\n", appoggio1, strerror(errno));
exit(1);
}
while ((nread = read(fd, buffer2, sizeof(buffer2))) > 0)
{
write(servers_fd, buffer2, nread);
read(servers_fd,buffer2,sizeof(char));
}
printf("Trasmissione completata con successo\n\n");
write(servers_fd,fine,strlen(fine));
read(servers_fd,fine,strlen(fine));
close(fd);
这是接收文件的代码:
fd = open(nomefile, O_CREAT | O_WRONLY, 0755);
if (fd < 0)
{
fprintf(stderr, "errore open(): %s\n", strerror(errno));
exit(errno);
}
while ((nread = read(conn_fd, buffer, sizeof(buffer))) > 0)
{
if(!strncmp(buffer,fine,7))
break;
write(fd, buffer, nread);
write(conn_fd,buffer,sizeof(char));
}
write(conn_fd,fine,strlen(fine));
}
问题出在你的协议上。
您发送文件,然后发送名称。但是客户端无法知道文件何时结束以及名称何时开始。
您可以通过先发送名称长度然后发送实际名称来修复它:
#include <arpa/inet.h>
// Write the file name with length marker
uint32_t nameLength = htonl(strlen(fine));
write(servers_fd, &nameLength, sizeof nameLength);
write(servers_fd, fine, strlen(fine));
// Write the actual file.
在客户端中:
#include <arpa/inet.h>
uint32_t nameLength;
read(conn_fd, &nameLength, sizeof nameLength);
nameLength = ntohl(nameLength);
read(conn_fd, fine, nameLength);
fine[nameLength] = '[=11=]'; // Add nul-terminator to file name.
// Read the rest of the file
htonl
和 ntohl
将数字转换为网络字节顺序,即使客户端和服务器使用不同的字节顺序(big/little 字节序),您的代码也能正常工作。
注意:除非您也为实际文件使用大小标记,否则客户端将不知道它有多大,并且连接只会对一个有效文件下载。
注2:我忽略了大小和文件名可能被分成多个网络包的可能性。
我正在用 C 开发一个 client/server 程序。服务器向客户端发送一个 txt 文件,但名称好像已损坏。内容不错,就是名字不好。
谁能告诉我为什么?谢谢!
这是发送文件的代码:
fd = open(appoggio1, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "unable to open '%s': %s\n", appoggio1, strerror(errno));
exit(1);
}
while ((nread = read(fd, buffer2, sizeof(buffer2))) > 0)
{
write(servers_fd, buffer2, nread);
read(servers_fd,buffer2,sizeof(char));
}
printf("Trasmissione completata con successo\n\n");
write(servers_fd,fine,strlen(fine));
read(servers_fd,fine,strlen(fine));
close(fd);
这是接收文件的代码:
fd = open(nomefile, O_CREAT | O_WRONLY, 0755);
if (fd < 0)
{
fprintf(stderr, "errore open(): %s\n", strerror(errno));
exit(errno);
}
while ((nread = read(conn_fd, buffer, sizeof(buffer))) > 0)
{
if(!strncmp(buffer,fine,7))
break;
write(fd, buffer, nread);
write(conn_fd,buffer,sizeof(char));
}
write(conn_fd,fine,strlen(fine));
}
问题出在你的协议上。
您发送文件,然后发送名称。但是客户端无法知道文件何时结束以及名称何时开始。
您可以通过先发送名称长度然后发送实际名称来修复它:
#include <arpa/inet.h>
// Write the file name with length marker
uint32_t nameLength = htonl(strlen(fine));
write(servers_fd, &nameLength, sizeof nameLength);
write(servers_fd, fine, strlen(fine));
// Write the actual file.
在客户端中:
#include <arpa/inet.h>
uint32_t nameLength;
read(conn_fd, &nameLength, sizeof nameLength);
nameLength = ntohl(nameLength);
read(conn_fd, fine, nameLength);
fine[nameLength] = '[=11=]'; // Add nul-terminator to file name.
// Read the rest of the file
htonl
和 ntohl
将数字转换为网络字节顺序,即使客户端和服务器使用不同的字节顺序(big/little 字节序),您的代码也能正常工作。
注意:除非您也为实际文件使用大小标记,否则客户端将不知道它有多大,并且连接只会对一个有效文件下载。
注2:我忽略了大小和文件名可能被分成多个网络包的可能性。