ZBLOG

BaseSocket::recvStream(void *pBuff, int iBuffLen, int timeout) { int ret = 0; timeval tv; fd_set fd; int rc; FD_ZERO( &fd ); FD_SET( m_socket , &fd ); tv.tv_sec = timeout/1000; tv.tv_usec = (timeout%1000) * 1000; ...

您提供的代码片段是一个在C++中使用selectrecv函数实现的接收数据流的示例。下面对这段代码进行解释并给出一些改进建议。

代码解析

  1. 函数定义:

    BaseSocket::recvStream(void *pBuff, int iBuffLen, int timeout)
    

    这是 BaseSocket 类中的一个成员函数,用于从套接字接收数据。

  2. 变量定义:

    int ret = 0;
    timeval tv;
    fd_set fd;
    int rc;
    
    • ret: 用于存储 select 的返回值。
    • tv: 用于设置超时。
    • fd: 文件描述符集合。
    • rc: 用于存储 recv 的返回值。
  3. 设置文件描述符集合:

    FD_ZERO(&fd);
    FD_SET(m_socket, &fd);
    

    清空文件描述符集合并将当前套接字添加到集合中。

  4. 设置超时时间:

    tv.tv_sec = timeout / 1000; 
    tv.tv_usec = (timeout % 1000) * 1000;
    

    将毫秒转换为秒和微秒,便于 select 使用。

  5. 调用 select 函数:

    ret = select(1, &fd, NULL, NULL, &tv);
    

    检查是否有可读的数据。如果有可读的数据,返回值将为1;如果超时,则返回0;如果发生错误,则返回-1。

  6. 接收数据:

    if (ret == 1)
    {
        rc = ::recv(m_socket, (char*)pBuff, iBuffLen, 0);
    }
    else
        return -1;
    
    
    return rc;
    

改进建议

  1. 错误处理:

    在调用 select()recv() 后应当检查这些系统调用的错误情况。例如,检查 select() 返回负值,并根据 errno 获取错误信息。此外,在调用 recv() 时也应当处理不同的返回值,如:

    • 如果返回值为0,表示连接已关闭;
    • 如果返回负值且 errno 为 EAGAIN 或 EWOULDBLOCK,则表示没有数据可以读取(非阻塞模式)。
  2. 更灵活的超时机制:

    如果希望可以取消等待,可以考虑在代码中引入信号或其他机制,以便能够优雅地中断等待状态。

  3. 类型安全性与参数验证:

    可以添加对输入参数的验证,例如确保缓冲区指针不为空,长度大于零等,从而提高函数的健壮性。

  4. 清晰注释与文档:

    可以为每个步骤添加注释以增强代码可读性,这对团队合作或者后期维护都非常重要。

改写后的示例

以下是加入了一些改进后可能会看起来如何:

int BaseSocket::recvStream(void *pBuff, int iBuffLen, int timeout)
{
    if (!pBuff || iBuffLen <= 0) {
        return -1; // 参数验证
    }

    int ret = 0;
    timeval tv;
    fd_set fd;

    FD_ZERO(&fd);
    FD_SET(m_socket , &fd);

    tv.tv_sec = timeout / 1000; 
    tv.tv_usec = (timeout % 1000) * 1000;

    ret = select(m_socket + 1, &fd, NULL, NULL, &tv); // 使用 m_socket + 1 确保正确

	if (ret < 0) {
		// 错误处理,比如打印errno相关信息
		return -1; // select 出错了
	} else if (ret == 0) {
		return -2; // 超时处理,可以自定义码表示超时  
	}

	int rc = ::recv(m_socket, static_cast<char*>(pBuff), iBuffLen, 0);
	
	if (rc < 0) {
        // recv 出错,比如打印errno相关信息
        return -1; // recv 出错了
	} else if (rc == 0) {
	    // 表示连接已关闭
	    return -3; // 自定义码表示连接关闭  
	}
    
	return rc; // 返回实际读取字节数
}

希望这些解释和改进建议能帮助到你!如果还有其他问题,请随时提问。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=20886

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?