C 当我通过套接字发送图片文件时,为什么字节会有差异?
我目前正在构建一个C/C++应用程序,它通过网络套接字发送和接收图片文件。但是,当我通过套接字发送文件时,与源文件相比,目标文件的字节略有不同 为了使此应用程序正常运行,目标客户端文件必须与源服务器文件在字节方面完全相同 客户端代码:C 当我通过套接字发送图片文件时,为什么字节会有差异?,c,sockets,byte,client-server,C,Sockets,Byte,Client Server,我目前正在构建一个C/C++应用程序,它通过网络套接字发送和接收图片文件。但是,当我通过套接字发送文件时,与源文件相比,目标文件的字节略有不同 为了使此应用程序正常运行,目标客户端文件必须与源服务器文件在字节方面完全相同 客户端代码: int client_app(int argc, char *argv[]) { // create a socket int network_socket; network_socket = socket(AF_INET, SOCK_ST
int client_app(int argc, char *argv[]) {
// create a socket
int network_socket;
network_socket = socket(AF_INET, SOCK_STREAM, 0);
// specify an address for the socket
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
// connect returns an integer
int connection_status = connect(network_socket, (struct sockaddr *) &server_address, sizeof(server_address));
if (connection_status == -1) {
printf("Error making connection to remote socket \n\n");
}
// read picture byte array
printf("Reading picture byte array...\n");
char p_array[BUFSIZ];
// convert it back into a pic
printf("Converting byte array to DNG...\n");
FILE *image = fopen("out_compressed.GPR", "w");
int nb;
while ((nb = read(network_socket, p_array, BUFSIZ)) > 0) {
fwrite(p_array, 1, nb, image);
bzero(p_array, BUFSIZ);
}
fclose(image);
// and then close the socket
close(network_socket);
}
服务器代码:
int server_app(int argc, char *argv[]) {
char *process_argv[100];
*process_argv = *argv;
int process_argc = 0;
for (int i = 1; i < 6; i++) {
process_argv[i] = argv[i + 1];
process_argc++;
}
process(process_argc, process_argv);
// create the server socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
// define the port number
int port = 9002;
// define the server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind the socket to our specified IP and port
bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));
// listen for connections on the socket
listen(server_socket, 5);
// create client socket for the server to send data to
int client_socket;
client_socket = accept(server_socket, nullptr, nullptr);
// get picture size
char *fpath = process_argv[4];
FILE *picture;
picture = fopen(fpath, "r");
int size;
fseek(picture, 0, SEEK_END);
size = ftell(picture);
fseek(picture, 0, SEEK_SET);
// send picture size
write(client_socket, &size, sizeof(size));
// send picture as byte array
char send_buffer[BUFSIZ];
int nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
while (!feof(picture)) {
write(client_socket, send_buffer, nb);
nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
}
// then close the sockets
close(server_socket);
close(client_socket);
}
当我在客户端收到一个文件时,它看起来大小相同,但我无法对它执行某些压缩操作,这与源文件不同
在我的终端中运行cmp以比较源文件和目标文件时,我得到以下结果:
compressed.GPR out\u compressed.GPR不同:字符1,第1行
如何使这些文件在字节方面完全相同
谢谢 在客户端发送文件大小,然后发送内容。在服务器中,您假定只发送内容,即您将最初发送的大小信息作为内容存储在新文件中
除此之外,您只需假设write将实际写入给定的所有数据,这是不保证的。因此,您需要检查实际写入的字节数。如果您在Windows上,则最好以二进制形式打开文件,即rb而不是r,wb而不是w,因为您在这里处理的是二进制数据。在客户端,您发送文件大小,然后发送内容。在服务器中,您假定只发送内容,即您将最初发送的大小信息作为内容存储在新文件中
write(client_socket, &size, sizeof(size));
除此之外,您只需假设write将实际写入给定的所有数据,这是不保证的。因此,您需要检查实际写入的字节数。如果你在Windows上,你最好以二进制文件的形式打开文件,即rb而不是r,wb而不是w,因为你在这里处理的是二进制数据
write(client_socket, &size, sizeof(size));
已将图像文件的大小写入套接字,但未检查写入是否成功。始终检查返回代码,以确保您编写了您认为您所做的。。客户机不使用此信息,而是将其合并到文件中。根据客户端当前的编码方式,完成文件后立即关闭套接字,您可以放弃代码计算并发送长度。当套接字关闭时,文件完成。不需要将长度作为辅助对象发送
此外,图像几乎肯定是二进制信息。使用打开文件
FILE *image = fopen("out_compressed.GPR", "w");
及
将以文本模式打开,并可能执行一些转换,其中最著名的转换是\r\n到\n并破坏文件。分别用wb和rb打开
已将图像文件的大小写入套接字,但未检查写入是否成功。始终检查返回代码,以确保您编写了您认为您所做的。。客户机不使用此信息,而是将其合并到文件中。根据客户端当前的编码方式,完成文件后立即关闭套接字,您可以放弃代码计算并发送长度。当套接字关闭时,文件完成。不需要将长度作为辅助对象发送
此外,图像几乎肯定是二进制信息。使用打开文件
FILE *image = fopen("out_compressed.GPR", "w");
及
将以文本模式打开,并可能执行一些转换,其中最著名的转换是\r\n到\n并破坏文件。分别用wb和rb打开。有两个主要错误 首先,服务器在内容之前写入文件大小,但客户端立即开始读取内容,因此文件大小成为客户端内容的一部分。客户机不需要大小,因此只需不在服务器端发送文件大小即可实现 第二个问题是在使用feof时: 当fread读取文件的最后一部分(即小于缓冲区大小的量)时,设置EOF标志。这意味着feof返回true,在将文件的最后一段写入套接字之前退出循环 更好的处理方法是在从文件中读取1个或更多字节时进行循环:
int nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
while (nb > 0) {
write(client_socket, send_buffer, nb);
nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
}
除此之外,您不会对调用的任何函数执行错误检查。您应该检查所有套接字和文件相关函数的返回值,如果失败,则使用perror打印错误消息。有两个主要错误 首先,服务器在内容之前写入文件大小,但客户端立即开始读取内容,因此文件大小成为客户端内容的一部分。客户机不需要大小,因此只需不在服务器端发送文件大小即可实现 第二个问题是在使用feof时: 当fread读取文件的最后一部分(即小于缓冲区大小的量)时,设置EOF标志。这意味着feof返回true,在写入之前退出循环 将文件的最后一段插入套接字 更好的处理方法是在从文件中读取1个或更多字节时进行循环:
int nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
while (nb > 0) {
write(client_socket, send_buffer, nb);
nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
}
除此之外,您不会对调用的任何函数执行错误检查。您应该检查所有套接字和文件相关函数的返回值,如果失败,请使用Pror打印错误消息。您需要以二进制模式打开文件。选择一个、C或C++,并从问题中删除另一个标记。@ RICHARDCRITTEN感谢您的响应!以二进制模式打开文件并不能解决此问题。当在终端中进行比较时,我现在在FielNeM.GPRE上获得EOF。您需要以二进制模式打开文件。选择一个、C或C++,并从问题中删除另一个标记。@ RICHARDCRITTEN感谢您的响应!以二进制模式打开文件并不能解决此问题。在终端中进行比较时,我现在在filename.GPR上获得EOF。感谢您的回复。删除图片大小的段读取并将其写入客户端套接字并不能解决问题,也不能以二进制模式打开文件。请看我上面对Richard的回复。谢谢您的回复。删除图片大小的段读取并将其写入客户端套接字并不能解决问题,也不能以二进制模式打开文件。请看我上面对Richard的回复。嗨,谢谢你的回复。如何检查服务器中写入的字节数?@GnlTsoChicken写入的字节数或失败时的错误代码是写入的返回值。您好,感谢您的回复。如何检查服务器中写入的字节数?@GnlTsoChicken写入的字节数或失败时的错误代码是写入的返回值。感谢您的回复,您的修复成功了!现在可以理解为什么在比较源文件和目标文件时在源文件之前到达EOF。也将添加一些错误处理。再次感谢!感谢您的回复,您的修复成功了!现在可以理解为什么在比较源文件和目标文件时在源文件之前到达EOF。也将添加一些错误处理。再次感谢!