【问题标题】:Sending Picture via TCP通过 TCP 发送图片
【发布时间】:2016-02-20 09:21:45
【问题描述】:

我正在尝试使用 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;

}

谢谢。

【问题讨论】:

  • 两个系统(发送方/接收方)是否相同字节序?哪种字节序?第一次 recv 调用接收了多少字节?小于 sizeof(buf)?添加更多调试输出或在调试器中运行并提供更多信息。

标签: c++ sockets tcp client-server tcp-ip


【解决方案1】:

您正在使用可变长度数组,它不是标准 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模式打开输出文件。

【讨论】:

  • 你说的似乎是对的,但是当我更正我的代码时,我仍然遇到同样的问题......
  • @EngineerN:上面的代码不能接收超过siz个字符,并且不能写更多...查看我的编辑以了解另一个可能的原因
  • 我发现了问题。这些文件需要以二进制模式打开。下面看看我的回答。感谢您的帮助
  • @EngineerN: 看起来我们是同时找到的 :-)
  • 它应该当然send(sock, Sbuf, n, 0)fwrite(Rbuffer, sizeof(char), siz, image); 应该是 fwrite(Rbuffer, sizeof(char), n, image);。而且这个必须在一个循环中。你不能假设一次阅读就读完了整本书。
【解决方案2】:

已解决:

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");

这是主要问题。谢谢。

【讨论】:

    猜你喜欢
    • 2018-10-24
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 2014-08-13
    相关资源
    最近更新 更多