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

新手上路,请多包涵

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

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()循环监听!浏览器请求数据后服务端的结果

阅读 3.4k
1 个回答

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

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

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

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

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

  1. 分批发送数据:可以通过按照较小的块大小(例如 4KB)进行多次读取和发送,而不是一次性读取整个文件并发送。这将减少发送缓冲区的压力。
  2. 使用非阻塞式 I/O 操作:可以将文件描述符设置为非阻塞模式,并使用非阻塞的读取操作(例如 read() 的返回值为 -2),以便及时响应套接字缓冲区的状态。
  3. 调整发送缓冲区大小:使用 setsockopt() 函数可以增加套接字的发送缓冲区大小,例如 SO_SNDBUF 选项。这可以提高发送大块数据的性能。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题