SRT源码分析--CChanel分析

打印 上一主题 下一主题

主题 991|帖子 991|积分 2973

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
void srt::CChannel::createSocket(int family)
  {
  m_iSocket = ::socket(family, SOCK_DGRAM, IPPROTO_UDP);
  }
  
  void srt::CChannel:pen(int family)
  {
  // 创建一个 socket,利用传入的协议族(family)参数。
  createSocket(family);
  
  // 界说 addrinfo 结构体,用于指定 getaddrinfo 函数的搜刮条件。
  addrinfo hints;
  // 界说 addrinfo 结构体指针,用于存储 getaddrinfo 函数的返回效果。
  addrinfo* res;
  
  // 将 hints 结构体初始化为 0。
  memset(&hints, 0, sizeof(struct addrinfo));
  
  // 设置搜刮条件。
  hints.ai_flags = AI_PASSIVE; // 利用被动模式,通常用于服务器端,表示地址适用于绑定。
  hints.ai_family = family; // 设置协议族,如 AF_INET、AF_INET6 等。
  hints.ai_socktype = SOCK_DGRAM; // 设置 socket 类型为 UDP。
  
  // 利用 getaddrinfo 函数分析当地地址,返回效果存储在 res 指针中。
  const int eai = ::getaddrinfo(NULL, "0", &hints, &res);
  
  // 查抄 getaddrinfo 是否乐成。如果失败,不实行绑定操作,直接跳到设置 UDP 套接字选项。
  if (eai != 0)
  {
  // 如果 getaddrinfo 失败,这里没有处理错误,而是直接跳过绑定步骤。
  // 这大概不是最佳实践,由于通常应该处理错误,例如记录日志或抛出非常。
  }
  
  // 绑定 socket 到获取的地址,这里缺少了对 getaddrinfo 失败的查抄。
  // 如果 getaddrinfo 失败,res 将是 NULL,这将导致绑定操作失败。
  if (0 != ::bind(m_iSocket, res->ai_addr, (socklen_t)res->ai_addrlen))
  {
  // 如果 bind 函数失败,这里没有处理错误,而是直接跳过设置 UDP 套接字选项。
  // 同样,这大概不是最佳实践,由于通常应该处理错误。
  }
  
  // 设置 UDP socket 选项,如缓冲区大小等。
  setUDPSockOpt();
  }
  
  void srt::CChannel:pen(int family)
  {
  // 创建一个 socket,利用传入的协议族(family)参数。
  createSocket(family);
  
  // sendto 或 WSASendTo 也会自动绑定 socket,以是这里不需要显式绑定。
  addrinfo hints; // 界说 addrinfo 结构体,用于指定 getaddrinfo 函数的搜刮条件。
  addrinfo* res; // 界说 addrinfo 结构体指针,用于存储 getaddrinfo 函数的返回效果。
  
  // 将 hints 结构体初始化为 0。
  memset(&hints, 0, sizeof(struct addrinfo));
  
  // 设置搜刮条件。
  hints.ai_flags = AI_PASSIVE; // 利用被动模式,通常用于服务器端,表示地址适用于绑定。
  hints.ai_family = family; // 设置协议族,如 AF_INET、AF_INET6 等。
  hints.ai_socktype = SOCK_DGRAM; // 设置 socket 类型为 UDP。
  
  // 利用 getaddrinfo 函数分析当地地址,返回效果存储在 res 指针中。
  const int eai = ::getaddrinfo(NULL, "0", &hints, &res);
  if (eai != 0)
  {
  // 如果 getaddrinfo 函数失败,抛出非常。这里的错误码 eai 被通报给非常。
  throw CUDTException(MJ_SETUP, MN_NORES, eai);
  }
  
  // 将 res 指向的地址信息用于绑定 socket。
  // Windows 下 ai_addrlen 类型为 size_t(无符号),而 bind 函数需要 int 类型。
  if (0 != ::bind(m_iSocket, res->ai_addr, (socklen_t)res->ai_addrlen))
  {
  // 如果 bind 函数失败,开释 res 指向的地址信息并抛出非常。
  ::freeaddrinfo(res);
  throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR);
  }
  // 将绑定的地址信息生存到 m_BindAddr 成员变量中。
  m_BindAddr = sockaddr_any(res->ai_addr, (sockaddr_any::len_t)res->ai_addrlen);
  
  #ifdef SRT_ENABLE_PKTINFO
  // 如果启用了 SRT_ENABLE_PKTINFO 特性,标志为绑定掩码。
  m_bBindMasked = true;
  #endif
  
  // 开释 getaddrinfo 函数分配的地址信息。
  ::freeaddrinfo(res);
  
  // 利用日志记录绑定到的当地地址。
  HLOGC(kmlog.Debug, log << "CHANNEL: Bound to local address: " << m_BindAddr.str());
  
  // 设置 UDP socket 选项,如缓冲区大小等。
  setUDPSockOpt();
  }
  
  void srt::CChannel::attach(UDPSOCKET udpsock, const sockaddr_any& udpsocks_addr)
  {
  // 这行解释说明在调用此函数之前,已经利用 getsockname() 获取了 socket 的名称,
  // 并将效果存储在 udpsocks_addr 中。
  
  // 将传入的 UDP socket 描述符赋值给类的成员变量 m_iSocket。
  m_iSocket = udpsock;
  
  // 将传入的 UDP socket 地址赋值给类的成员变量 m_BindAddr。
  m_BindAddr = udpsocks_addr;
  
  // 调用 setUDPSockOpt 函数来设置 UDP socket 选项,如缓冲区大小等。
  setUDPSockOpt();
  }
  
  void srt::CChannel::setUDPSockOpt()
  {
  // BSD体系如果哀求的缓冲区大小凌驾了体系的最大值,setsockopt会失败。
  // 这里界说了一个名为maxsize的变量,其值为64000,用作缓冲区大小的上限。
  int maxsize = 64000;
  
  // 实行设置UDP接收缓冲区的大小为m_mcfg.iUDPRcvBufSize。
  // 如果设置失败(返回值非0),则实行将接收缓冲区大小设置为体系最大值maxsize。
  if (0 != ::setsockopt(
  m_iSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&m_mcfg.iUDPRcvBufSize, sizeof m_mcfg.iUDPRcvBufSize))
  {
  ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&maxsize, sizeof maxsize);
  }
  
  // 实行设置UDP发送缓冲区的大小为m_mcfg.iUDPSndBufSize。
  // 如果设置失败(返回值非0),则实行将发送缓冲区大小设置为体系最大值maxsize。
  if (0 != ::setsockopt(
  m_iSocket, SOL_SOCKET, SO_SNDBUF, (const char*)&m_mcfg.iUDPSndBufSize, sizeof m_mcfg.iUDPSndBufSize))
  {
  ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (const char*)&maxsize, sizeof maxsize);
  }
  }
  
  int srt::CChannel::getSndBufSize() //设置发送buffer大小
  {
  socklen_t size = (socklen_t)sizeof m_mcfg.iUDPSndBufSize;
  ::getsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_mcfg.iUDPSndBufSize, &size);
  return m_mcfg.iUDPSndBufSize;
  }
  
  int srt::CChannel::getRcvBufSize() //获取接收buffer大小
  {
  socklen_t size = (socklen_t)sizeof m_mcfg.iUDPRcvBufSize;
  ::getsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_mcfg.iUDPRcvBufSize, &size);
  return m_mcfg.iUDPRcvBufSize;
  }
  void srt::CChannel::getSockAddr(sockaddr_any& w_addr) const
  {
  // getsockname 函数只需要充足的目标空间来复制套接字名称,
  // 它不需要与地址族相关联。因此,任何名称的最大空间,
  // 不论眷属如何,都可以胜任。
  socklen_t namelen = (socklen_t)w_addr.storage_size(); // 获取 w_addr 提供的存储空间大小。
  ::getsockname(m_iSocket, (w_addr.get()), (&namelen)); // 利用 getsockname 函数获取当前套接字的当地地址。
  w_addr.len = namelen; // 更新 w_addr 的长度为获取的地址长度。
  }
  void srt::CChannel::getPeerAddr(sockaddr_any& w_addr) const
  {
  // 获取 w_addr 提供的存储空间大小。
  socklen_t namelen = (socklen_t)w_addr.storage_size();
  // 利用 getpeername 函数获取当前套接字的远程(对端)地址。
  ::getpeername(m_iSocket, (w_addr.get()), (&namelen));
  // 更新 w_addr 的长度为获取的地址长度。
  w_addr.len = namelen;
  }
  
  
  
  

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

悠扬随风

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表