当前位置: 首页 > 知识库问答 >
问题:

c++ - 如何使用bufferevent_write向浏览器发送MP3文件?

寇丰
2023-08-31

求解答,小文件能正发送至浏览器,大一点的发送失败,浏览器显示未收到服务器发送过来的数据

int send_file(struct bufferevent* bev,const char* filename){    int fd=open(filename,O_RDONLY);    if(fd == -1){        string str="open "s + filename +" failed"s;        perror(str.c_str());        return -1;    }    char buf[4096]{0};    int readsize=0;    int ret=0;    int sum=0;    while(1){        bzero(buf,sizeof(buf));        readsize=Read(fd,buf,sizeof(buf));        if(readsize == 0)   break;        else if(readsize == -2) continue;   // 连接是正常的,调用者 继续接收         else if(readsize == -1){            // 错误读取,退出调用            close(fd);            return -1;        }        ret=bufferevent_write(bev,buf,readsize);        // cout<<"errno = "<<errno<<endl; // 一直等于11        // perror("failed : ");           //Resource temporarily unavailable    }    close(fd);    return 0;}

我在实现基于Libevent库的b/s模型时,使用bufferevent_write向浏览器发送10M的mp3文件失败,打印错误码errno的值一直等于11 resource temporarily unavailable, 并在回调函数调用完之后异常终止,无错误信息。并非跳出event_base_dispatch()循环监听!浏览器请求数据后服务端的结果

共有1个答案

彭浩穰
2023-08-31

这个问题可能是由于发送数据速度过快而导致的缓冲区溢出。

在使用 Libevent 库中的 bufferevent_write() 函数发送数据时,该函数将数据写入内部缓冲区,并尝试异步地将缓冲区中的数据发送到套接字。如果缓冲区已满,调用将阻塞或返回 EAGAINEWOULDBLOCK 错误。

根据你提供的代码,你使用的是阻塞式的文件读取(read()),并直接将读取到的数据使用 bufferevent_write() 发送到客户端。由于数据一次读取并发送的速度较快,可能出现以下情况之一:

  1. 发送缓冲区溢出:发送缓冲区可能无法容纳一次性读取到的 10M 数据,导致缓冲区溢出。这可能会导致 EAGAINEWOULDBLOCK 错误,并且将数据写入缓冲区的操作被阻塞。
  2. 内核缓冲区溢出:发送缓冲区溢出后,数据可能会积累在内核缓冲区中,导致内核缓冲区溢出,并且无法将数据传输到网络套接字。这可能导致 EAGAINEWOULDBLOCK 错误。

为了解决这个问题,你可以尝试以下方法:

  1. 分批发送数据:可以通过按照较小的块大小(例如 4KB)进行多次读取和发送,而不是一次性读取整个文件并发送。这将减少发送缓冲区的压力。
  2. 使用非阻塞式 I/O 操作:可以将文件描述符设置为非阻塞模式,并使用非阻塞的读取操作(例如 read() 的返回值为 -2),以便及时响应套接字缓冲区的状态。
  3. 调整发送缓冲区大小:使用 setsockopt() 函数可以增加套接字的发送缓冲区大小,例如 SO_SNDBUF 选项。这可以提高发送大块数据的性能。
 类似资料:
  • 在过去的几个小时里,我一直在阅读推送通知应用编程接口和网络通知应用编程接口。我还发现谷歌 我试图了解我们是否可以使用桌面通知实现对浏览器的推送通知,我相信这就是Web通知API所做的。我在这里看到了一个关于如何为Chrome做到这一点的谷歌文档 现在我还不明白的是: 我们可以使用GCM/APNS向包括Firefox在内的所有Web浏览器发送推送通知吗 我相信所有这些答案都可以帮助很多有类似困惑的人

  • 问题内容: 在我的Node / Express应用程序中,我有以下代码,假设要从文件中读取PDF文档,并将其发送到浏览器: 我没有收到任何错误,但是我也没有在浏览器中获取文件。我究竟做错了什么? 问题答案: 您必须通过管道从Readable Stream到Writable流,而不是相反: 另外,您以错误的方式设置了编码,如果需要,可以通过编码传递对象。

  • 我已经实现了一个使用基本身份验证(使用Spring Security性)的web服务器。 我在访问URL时禁用了默认身份验证入口点(它只返回401,而不是用www身份验证标头响应401),目的是防止浏览器显示身份验证弹出窗口。 我能够用javascript代码和命令行工具(如curl)连接到服务器,但是当我用浏览器(chrome)测试它时 <代码>curl-v-u用户:密码本地主机:8080/用户

  • 尽管 ASP 主要用来创建和处理服务器端脚本,还是可以使用它生成由客户浏览器处理的客户端脚本来扩展其效用。通过组合传送到浏览器的脚本命令可以编写服务器端脚本。 通过组合由 HTML 注释括起来的客户端脚本和由定界符括起来的服务器端脚本可以做到这一点: <SCRIPT LANGUAGE="VBScript"> <!-- client script <% server script %> cli

  • 在处理 ASP 脚本时,任何没有包含在 ASP 定界符或 <SCRIPT> 标记中的文本或图形都将被简单地返回给浏览器。可以通过使用 Response 对象显示地把内容发送给浏览器。 发送内容 要将内容从 ASP 定界符内部或过程发送给浏览器,可以使用 Response 对象的 Write 方法。例如,下面的语句可以根据用户是否访问过此页而发送不同的问候语: <% If FirstTime =

  • 我有一个AngularJS WebAPI应用程序。 据我所知,OPTIONS请求是由浏览器自动构建的。 答复: 现在登录 我注销,这只不过是删除令牌并再次登录。发生了一些不同的事情。以前它没有发送选项,但现在它发送了。以前的请求/响应是否会影响浏览器在我第二次登录时的不同行为? 答复: 如果我重新设置浏览器并重新加载页面,它会返回到以前的状态,第一次不发送选项,我就可以登录了。 可能我需要更改服务