通过套接字发送图像

7
我正在尝试通过C语言的TCP套接字发送图像文件,但是服务器端没有正确地重新组装图像。我想知道是否有人能指出错误所在?
我知道服务器正在接收正确的文件大小,并构建了一个相同大小的文件,但它并不是一个图像文件。
客户端
//Get Picture Size
printf("Getting Picture Size\n");
FILE *picture;
picture = fopen(argv[1], "r");
int size;
fseek(picture, 0, SEEK_END);
size = ftell(picture);

//Send Picture Size
printf("Sending Picture Size\n");
write(sock, &size, sizeof(size));

//Send Picture as Byte Array
printf("Sending Picture as Byte Array\n");
char send_buffer[size];
while(!feof(picture)) {
    fread(send_buffer, 1, sizeof(send_buffer), picture);
    write(sock, send_buffer, sizeof(send_buffer));
    bzero(send_buffer, sizeof(send_buffer));
}

服务器

//Read Picture Size
printf("Reading Picture Size\n");
int size;
read(new_sock, &size, sizeof(int));

//Read Picture Byte Array
printf("Reading Picture Byte Array\n");
char p_array[size];
read(new_sock, p_array, size);

//Convert it Back into Picture
printf("Converting Byte Array to Picture\n");
FILE *image;
image = fopen("c1.png", "w");
fwrite(p_array, 1, sizeof(p_array), image);
fclose(image);

编辑:在服务器代码中修复了 sizeof(int)。


1
有几个问题需要解决...你没有倒回文件,你的服务器sizeof(1)应该是sizeof(int),你发送的是sizeof(buffer)而不是从fread()读取的实际内容,还可能有其他问题。 - utopianheaven
如何“倒带”文件,或者有更好的方法获取文件大小? - Takkun
3个回答

8

在阅读之前,您需要寻找文件的开头。

fseek(picture, 0, SEEK_END);
size = ftell(picture);
fseek(picture, 0, SEEK_SET);

或者使用 fstat 函数来获取文件大小。

如果在Linux上,您还可以使用pread()来读取固定位置/偏移量为零(始终在文件开头)。 - Gabriel Staples

0

查看 freadfwrite 的语法:

size_t fread(void *ptr, size_t size, size_t n, FILE *fp);

size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);

在您的情况下,正确的语句应该是:

fread(send_buffer, sizeof(send_buffer), 1, picture);

fwrite(p_array, sizeof(p_array), 1,image);


0

虽然这是一篇旧帖子,但我必须强调原始代码中的一些问题:

  • 在调用feof之前,picture文件指针总是为false。您必须在调用feof之前进行读取
  • read(new_sock, p_array, size)不能保证读取size字节,它取决于size的值、网络负载、服务器负载等因素。

一个正确(至少更加健壮)的版本应该是:

//Send Picture as Byte Array (without need of a buffer as large as the image file)
printf("Sending Picture as Byte Array\n");
char send_buffer[BUFSIZE]; // no link between BUFSIZE and the file size
int nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
while(!feof(picture)) {
    write(sock, send_buffer, nb);
    nb = fread(send_buffer, 1, sizeof(send_buffer), picture);
    // no need to bzero
}

服务器端同样存在的问题:

//Read Picture Byte Array
printf("Reading Picture Byte Array\n");
char p_array[size];
char* current = p_array;
int nb = read(new_sock, current, size);
while (nb >= 0) {
    current = current + nb;
    nb = read(new_sock, current, size);
}

在服务器端,您可以避免创建一个与图像文件一样大的缓冲区(这可能会成为大型图像的问题):
//Read Picture Byte Array and Copy in file
printf("Reading Picture Byte Array\n");
char p_array[BUFSIZE];
FILE *image = fopen("c1.png", "w");
int nb = read(new_sock, p_array, BUFSIZE);
while (nb > 0) {
    fwrite(p_array, 1, nb, image);
    nb = read(new_sock, p_array, BUFSIZE);
}
fclose(image);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接