连接我的webserver图片和视频数据无法正常传输

(ps: 就自己留着以后看,对大家的帮助不大)

问题描述:

在用浏览器连接 webserver 服务器,并选择查看图片或者视频时发现图片传一半,视频传不过来。(准确说,当时发现的问题是小图片能正确传输,图片大了就传不过来)

尝试了一下 tcpdump (其实感觉没看出来啥),但是当看到传输过程中 seq 和 ack 以及 length 之间没有很好的对应,又确认连接没有被断开。已经察觉的是系统调用 writev() 这一个阶段出现了问题。检查代码:

bool http_conn::write(){
    int temp = 0;
    if( bytes_to_send == 0 ){
        modfd( m_epollfd, m_sockfd, EPOLLIN );
        init();
        return true;
    }
    while( 1 ){
        // iovec 结构体封装了一块内存的地址起始位置和长度
        // struct iovec { 
        //     ptr_t iov_base; /* Starting address */ 
        //     size_t iov_len; /* Length in bytes */ 
        // }; */
        temp = writev( m_sockfd, m_iv, m_iv_count ); // #include <sys/uio.h>
        if( temp <= -1 ){
            /* 如果 TCP 写缓冲没有空间。则等待下一轮 EPOLLOUT 事件。虽然在此期间,服务器无法立即接收到同一
            客户的下一个请求,但这可以保证连接的完整性 */
            if( errno == EAGAIN ){
                modfd( m_epollfd, m_sockfd, EPOLLOUT );
                return true;
            }
            unmap();
            return false;
        }
        // to_send 需要发送的
        // have_send 已经发送的
        // printf("bytes_to_send_before:%d\n", bytes_to_send);
        // printf("bytes_have_send_after:%d\n", bytes_have_send);
        bytes_to_send -= temp;
        bytes_have_send += temp;
        // printf("bytes_to_send:%d\n", bytes_to_send);
        // printf("bytes_have_send:%d\n", bytes_have_send);

        if( bytes_have_send >= m_iv[0].iov_len){
            m_iv[0].iov_len = 0;
            m_iv[1].iov_base = m_file_address + (bytes_have_send - m_write_idx);
            m_iv[1].iov_len = bytes_to_send;
        }
        else{
            m_iv[0].iov_base = m_write_buf + bytes_have_send;
            m_iv[0].iov_len = m_iv[0].iov_len - bytes_have_send;
        }

        if( bytes_to_send <= 0 ){
            unmap();
            modfd(m_epollfd, m_sockfd, EPOLLIN);
            if( m_linger ){
                init();
                modfd( m_epollfd, m_sockfd, EPOLLIN );
                return true;
            }
            else{
                modfd( m_epollfd, m_sockfd, EPOLLIN );
                return false;
            }
        }
    }
}

这已经是修改后的代码,关键点就在注释处:

  •  // iovec 结构体封装了一块内存的地址起始位置和长度
     // struct iovec { 
     //     ptr_t iov_base; /* Starting address */ 
     //     size_t iov_len; /* Length in bytes */ 
     // }; 
    
  •   bytes_to_send
      bytes_have_send
    

之前的代码找不到不好做对比了,这里就简单记一下当时问题是什么原因。

简单来说就是在进行写操作时,没有将图片和视频的数据大小传递在 bytes_to_send

也就是 http_conn::process_write( HTTP_CODE ret) 这个方法中的这一步:

case FILE_REQUEST:
{
    add_status_line( 200, ok_200_title );
    if( m_file_stat.st_size != 0 ){
        add_headers( m_file_stat.st_size );
        m_iv[0].iov_base = m_write_buf; // 这里是自己写的响应的内存地址
        m_iv[0].iov_len = m_write_idx;	// 响应数据长度
        m_iv[1].iov_base = m_file_address;	// 文件内存地址(照片或者视频)
        m_iv[1].iov_len = m_file_stat.st_size;	// 文件大小
        m_iv_count = 2;
        bytes_to_send = m_write_idx + m_file_stat.st_size; // 之前没有这一步
        return true;
    }

当然其他地方也产生了影响,但是核心是这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Artintel

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值