通过 TCP 发送图片
Sending Picture via TCP
我正在尝试使用 TCP 从客户端向服务器发送一个 jpg 文件。当图片到达服务器端时我无法打开它,除了接收到的图片大小比发送的大(发送= 880 字节,接收= 894 字节)。你们中有人知道如何解决这个问题吗?这是我的代码:
客户代码:
static int send_server_image(SOCKET sock){
int n = 0;
int siz = 0;
FILE *picture;
char buf[50];
char *s="";
cout << "Getting image size" << endl;
picture = fopen("C:\Users\n.b\Desktop\c++\TCP\tcp_client_image_pp\test.jpg", "r");
fseek(picture, 0, SEEK_END);
siz = ftell(picture);
cout << siz << endl; // Output 880
cout << "Sending picture size to the server" << endl;
sprintf(buf, "%d", siz);
if((n = send(sock, buf, sizeof(buf), 0)) < 0)
{
perror("send_size()");
exit(errno);
}
char Sbuf[siz];
cout << "Sending the picture as byte array" << endl;
fseek(picture, 0, SEEK_END);
siz = ftell(picture);
fseek(picture, 0, SEEK_SET); //Going to the beginning of the file
while(!feof(picture)){
fread(Sbuf, sizeof(char), sizeof(Sbuf), picture);
if((n = send(sock, Sbuf, sizeof(Sbuf), 0)) < 0)
{
perror("send_size()");
exit(errno);
}
memset(Sbuf, 0, sizeof(Sbuf));
}
}
服务器代码:
static int recv_client_image(SOCKET sock){
int n = 0;
cout << "Reading image size" << endl;
char buf[50];
int siz = 0;
if ((n = recv(sock, buf, sizeof(buf), 0) <0)){
perror("recv_size()");
exit(errno);
}
siz = atoi(buf);
cout << siz << endl; // 880 output
char Rbuffer[siz];
cout << "Reading image byte array" << endl;
n = 0;
if ((n = recv(sock, Rbuffer, sizeof(Rbuffer), 0)) < 0){
perror("recv_size()");
exit(errno);
}
cout << "Converting byte array to image" << endl;
FILE *image;
image = fopen("recu.jpg", "w");
fwrite(Rbuffer, sizeof(char), sizeof(Rbuffer), image);
fclose(image);
cout << "done" << endl;
}
谢谢。
您正在使用可变长度数组,这不是标准的 C++ (ref)。即使它被你的编译器接受,你也应该避免使用 sizeof
。
并且您在 while(!feof(picture))
中遇到了问题。您从文件 中读取了 siz 个字节,没有任何错误,也没有设置 eof 标志。在第二次读取时,您读取了 0 个字节并设置了标志,但也发送了另一个缓冲区。
你应该这样写:
while(!feof(picture)){
n = fread(Sbuf, sizeof(char), siz, picture);
if (n > 0) { /* only send what has been read */
if((n = send(sock, Sbuf, siz, 0)) < 0) /* or (better?) send(sock, Sbuf, n, 0) */
{
perror("send_data()");
exit(errno);
}
}
/* memset(Sbuf, 0, sizeof(Sbuf)); useless for binary data */
}
服务器部分相同:
if ((n = recv(sock, Rbuffer, siz, 0)) < 0){
perror("recv_size()");
exit(errno);
}
cout << "Converting byte array to image" << endl;
FILE *image;
image = fopen("recu.jpg", "w");
fwrite(Rbuffer, sizeof(char), siz, image);
fclose(image);
还有最后一个错误的可能性,至少如果你在一个区分文本文件和二进制文件的平台上,比如 Windows 就是你忘记以二进制模式打开文件,这可能会破坏 jpg 图像。因为在二进制文件的 windows 上,字节 0x10 被视为新行 (\n'
) 并写为 2 个字节 0x0d 0x10 (\r\n
).
所以你必须在rb
模式下打开输入文件,在wb
模式下打开输出文件。
已解决:
Serge Ballesta 的所有更正都是正确的。但问题出在我打开文件的方式上。
您需要以二进制模式打开文件 ("rb"用于读取,"wb"用于写入),不是默认的文本模式。
客户:
picture = fopen("C:\Users\n.b\Desktop\c++\TCP\tcp_client_image_pp\test.jpg", "rb");
服务器:
image = fopen("recu.jpg", "wb");
这是主要问题。谢谢。
我正在尝试使用 TCP 从客户端向服务器发送一个 jpg 文件。当图片到达服务器端时我无法打开它,除了接收到的图片大小比发送的大(发送= 880 字节,接收= 894 字节)。你们中有人知道如何解决这个问题吗?这是我的代码:
客户代码:
static int send_server_image(SOCKET sock){
int n = 0;
int siz = 0;
FILE *picture;
char buf[50];
char *s="";
cout << "Getting image size" << endl;
picture = fopen("C:\Users\n.b\Desktop\c++\TCP\tcp_client_image_pp\test.jpg", "r");
fseek(picture, 0, SEEK_END);
siz = ftell(picture);
cout << siz << endl; // Output 880
cout << "Sending picture size to the server" << endl;
sprintf(buf, "%d", siz);
if((n = send(sock, buf, sizeof(buf), 0)) < 0)
{
perror("send_size()");
exit(errno);
}
char Sbuf[siz];
cout << "Sending the picture as byte array" << endl;
fseek(picture, 0, SEEK_END);
siz = ftell(picture);
fseek(picture, 0, SEEK_SET); //Going to the beginning of the file
while(!feof(picture)){
fread(Sbuf, sizeof(char), sizeof(Sbuf), picture);
if((n = send(sock, Sbuf, sizeof(Sbuf), 0)) < 0)
{
perror("send_size()");
exit(errno);
}
memset(Sbuf, 0, sizeof(Sbuf));
}
}
服务器代码:
static int recv_client_image(SOCKET sock){
int n = 0;
cout << "Reading image size" << endl;
char buf[50];
int siz = 0;
if ((n = recv(sock, buf, sizeof(buf), 0) <0)){
perror("recv_size()");
exit(errno);
}
siz = atoi(buf);
cout << siz << endl; // 880 output
char Rbuffer[siz];
cout << "Reading image byte array" << endl;
n = 0;
if ((n = recv(sock, Rbuffer, sizeof(Rbuffer), 0)) < 0){
perror("recv_size()");
exit(errno);
}
cout << "Converting byte array to image" << endl;
FILE *image;
image = fopen("recu.jpg", "w");
fwrite(Rbuffer, sizeof(char), sizeof(Rbuffer), image);
fclose(image);
cout << "done" << endl;
}
谢谢。
您正在使用可变长度数组,这不是标准的 C++ (ref)。即使它被你的编译器接受,你也应该避免使用 sizeof
。
并且您在 while(!feof(picture))
中遇到了问题。您从文件 中读取了 siz 个字节,没有任何错误,也没有设置 eof 标志。在第二次读取时,您读取了 0 个字节并设置了标志,但也发送了另一个缓冲区。
你应该这样写:
while(!feof(picture)){
n = fread(Sbuf, sizeof(char), siz, picture);
if (n > 0) { /* only send what has been read */
if((n = send(sock, Sbuf, siz, 0)) < 0) /* or (better?) send(sock, Sbuf, n, 0) */
{
perror("send_data()");
exit(errno);
}
}
/* memset(Sbuf, 0, sizeof(Sbuf)); useless for binary data */
}
服务器部分相同:
if ((n = recv(sock, Rbuffer, siz, 0)) < 0){
perror("recv_size()");
exit(errno);
}
cout << "Converting byte array to image" << endl;
FILE *image;
image = fopen("recu.jpg", "w");
fwrite(Rbuffer, sizeof(char), siz, image);
fclose(image);
还有最后一个错误的可能性,至少如果你在一个区分文本文件和二进制文件的平台上,比如 Windows 就是你忘记以二进制模式打开文件,这可能会破坏 jpg 图像。因为在二进制文件的 windows 上,字节 0x10 被视为新行 (\n'
) 并写为 2 个字节 0x0d 0x10 (\r\n
).
所以你必须在rb
模式下打开输入文件,在wb
模式下打开输出文件。
已解决:
Serge Ballesta 的所有更正都是正确的。但问题出在我打开文件的方式上。
您需要以二进制模式打开文件 ("rb"用于读取,"wb"用于写入),不是默认的文本模式。
客户:
picture = fopen("C:\Users\n.b\Desktop\c++\TCP\tcp_client_image_pp\test.jpg", "rb");
服务器:
image = fopen("recu.jpg", "wb");
这是主要问题。谢谢。