【问题标题】:Sending images over stream socket通过流套接字发送图像
【发布时间】:2011-04-11 00:44:49
【问题描述】:

谁能指导我是否有通过 tcp 套接字发送图像(特别是 .jpeg 文件)的特殊方式?到目前为止,我正在开发一个似乎可以很好地发送所有文本数据的网络服务器。当涉及到 jpeg 图像时,会发送标头,但是在发送实际数据时,Cygwin 控制台会冻结。

我发送数据的方式是首先打开文件,将数据读入缓冲区,然后将其推送。有什么建议吗?

    while(!feof(sendFile)){

            bzero(send_buffer,sizeof(send_buffer));
            result = fread (send_buffer,1,sizeof(send_buffer),sendFile);

            while(result>0){
                result = fread (send_buffer,1,sizeof(send_buffer),sendFile);

                if(ferror(sendFile)){
                    printf("Error reading file: %s\n",request_page);
                }
                if((test=send(new_fd,send_buffer,sizeof(send_buffer),0))<0){
                    printf("Send returned %d\n",test);
                    printf("Sending %s Failed\n", request_page);
                    exit(1);
                }
                bzero(send_buffer,sizeof(send_buffer));
            }
        }
        fclose(sendFile);

【问题讨论】:

  • 我在数据传输中学到的一点:我通常会在发送前进行base64编码,在接收时进行解码,这样编码转换时数据不会丢失
  • 没错,但我只是在编写服务器代码。我正在尝试为来自现有浏览器(例如 Firefox)的请求提供服务。
  • 使用 HTTP 协议时不需要对数据进行 base64 编码。它旨在按原样处理二进制数据。

标签: c sockets tcp transactions


【解决方案1】:

您的一个主要逻辑缺陷是您调用 fread() 的次数过多。您调用它一次,然后在调用 send() 之前再次调用它覆盖之前需要发送的缓冲区

在读取下一个缓冲区之前,您也没有检查以确保 send() 实际上发送了完整的缓冲区。当您应该只发送 fread() 实际读取的字节数时,您正在发送整个缓冲区。

试试这个:

unsigned char send_buffer[...];
bool error = false;

while (!feof(sendFile) && !error)
{ 
    bzero(send_buffer, sizeof(send_buffer)); 

    result = fread(send_buffer, 1, sizeof(send_buffer), sendFile);
    if (result < 1)
    {
        if (ferror(sendFile))
        {
            printf("Error reading file: %s\n", request_page); 
            error = true;
        }
        break;
    } 

    unsigned char *send_buffer_ptr = send_buffer;
    do
    {
        test = send(new_fd, send_buffer_ptr, result, 0);
        if (test <= 0)
        { 
            printf("Send returned %d\n", test); 
            printf("Sending %s Failed\n", request_page); 
            error = true;
            break; 
        } 

        send_buffer_ptr += test;
        result -= test;
    }
    while (result > 0);
}

fclose(sendFile); 

if (error)
    exit(1);

【讨论】:

    【解决方案2】:

    此代码有几处错误或可能错误。

    result = fread (send_buffer,1,Fsize,sendFile);
    

    这一行从sendFile 读取Fsize 字节到send_buffer。现在,我看不到你从哪里得到Fsize,但鉴于它的名字,我猜它是文件的大小。您是否确保send_buffer 足够大以容纳Fsize 字节?如果没有,你自己这里就有一个潜在的缓冲区溢出,这可能会导致随机数据被写入你的堆栈,从而导致各种麻烦。您可能是想阅读sizeof(send_buffer)。你似乎也有一个常数,MAX_MSG。这等于发送缓冲区的大小吗?如果没有,那条线也会有问题。一般来说,您应该尝试使用一种一致的方法来引用此缓冲区的大小,这样您就不会被两个不同的值混淆而导致问题。

    接下来,您尝试测试读取文件的错误:

    if(result != Fsize && (result!=0)) {
    printf("Reading error"); 
    exit (1);
    }
    

    现在,让我们来看看documentation for fread 是怎么说的:

    fread() 和 fwrite() 返回数字 成功读取或写入的项目 (即,不是字符数)。 如果发生错误,或者文件结束 达到,返回值为 短项目数(或零)。

    fread() 不区分 文件结尾和错误,以及调用者 必须使用 feof(3) 和 ferror(3) 来 确定发生了什么。

    在这里,如果您没有确切的 Fsize 或零项,则会引发错误。现在,根据文档,在错误或文件结尾的情况下,您可以有一个短计数或零。要区分您是需要提前跳出循环还是因错误而死,您需要调用feof 和/或ferror

    我猜你的错误在于上面提到的缓冲区溢出,但我建议修复这两个问题。

    【讨论】:

    • 嗨,布赖恩,非常感谢您提供的这些提示。我在我的代码中修复了这些小问题,它确实有所作为——一些我在正常工作之前无法打开的页面。但是我仍然对 jpeg 图像有问题 =s。
    • 我已经用更新的代码编辑了我的帖子。 send() 语句返回 -1,对于我来说,我无法弄清楚为什么......:s
    • 它给出的错误是:连接被对等方重置。我猜套接字正在以某种方式关闭。我在 setsockopt 下也启用了 TCP_Keepalive 选项。仍然没有变化..
    • 在发送文件数据之前,您具体发送了哪些 HTTP 标头?它对接收方读取和解释您发送的数据的方式有很大影响。
    猜你喜欢
    • 2012-08-17
    • 2013-12-31
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 2013-12-17
    相关资源
    最近更新 更多