Socket

image.png
PhysicalSocketServer 真正物理网络连接的socket工厂类,多平台使用。
Win32SocketServer Windows下的处理socket事件工厂类,只能在Windows下。
NullSocketServer 只有基础事件处理功能,没有socket功能,不能处理网络事件。

PhysicalSocket::Connect

支持域名和ip连接。
image.png
判断是否还没解析成ip,没有则创建一个线程AsncResolver来异步解析,解析成功后调用OnResolverResult,里面也会调用DonConnect来连接服务器。
AsyncResolver继承了AsyncResolverInterface,主要使用了 sigslot::signal1信号槽机制。

代码分析

BasicNetworkManager::UpdateNetworksOnce

在这里调用QueryDefaultLocalAddress获取本地默认的ip地址和端口,然后set_default_local_addresses来设置本地默认的ip地址和端口。

  1. void BasicNetworkManager::UpdateNetworksOnce() {
  2. if (!start_count_)
  3. return;
  4. NetworkList list;
  5. if (!CreateNetworks(false, &list)) {
  6. SignalError();
  7. } else {
  8. bool changed;
  9. NetworkManager::Stats stats;
  10. MergeNetworkList(list, &changed, &stats);
  11. set_default_local_addresses(QueryDefaultLocalAddress(AF_INET),
  12. QueryDefaultLocalAddress(AF_INET6));
  13. if (changed || !sent_first_update_) {
  14. SignalNetworksChanged();
  15. sent_first_update_ = true;
  16. }
  17. }
  18. }

—》QueryDefaultLocalAddress

BasicNetworkManager::QueryDefaultLocalAddress

  1. IPAddress BasicNetworkManager::QueryDefaultLocalAddress(int family) const {
  2. RTC_DCHECK(thread_->socketserver() != nullptr);
  3. RTC_DCHECK(family == AF_INET || family == AF_INET6);
  4. // 创建AsyncSocket对象
  5. std::unique_ptr<AsyncSocket> socket(
  6. thread_->socketserver()->CreateAsyncSocket(family, SOCK_DGRAM));
  7. if (!socket) {
  8. RTC_LOG_ERR(LERROR) << "Socket creation failed";
  9. return IPAddress();
  10. }
  11. // 连接服务器
  12. /* 宏定义是
  13. const char kPublicIPv4Host[] = "8.8.8.8";
  14. const char kPublicIPv6Host[] = "2001:4860:4860::8888";
  15. const int kPublicPort = 53; // DNS port.
  16. */
  17. if (socket->Connect(SocketAddress(
  18. family == AF_INET ? kPublicIPv4Host : kPublicIPv6Host, kPublicPort)) <
  19. 0) {
  20. if (socket->GetError() != ENETUNREACH &&
  21. socket->GetError() != EHOSTUNREACH) {
  22. // Ignore the expected case of "host/net unreachable" - which happens if
  23. // the network is V4- or V6-only.
  24. RTC_LOG(LS_INFO) << "Connect failed with " << socket->GetError();
  25. }
  26. return IPAddress();
  27. }
  28. return socket->GetLocalAddress().ipaddr();
  29. }

PhysicalSocketServer::CreateAsyncSocket

H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\rtc_base\physical_socket_server.cc

  1. // 这里创建了socket分发器
  2. AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) {
  3. SocketDispatcher* dispatcher = new SocketDispatcher(this);
  4. if (dispatcher->Create(family, type)) {
  5. return dispatcher;
  6. } else {
  7. delete dispatcher;
  8. return nullptr;
  9. }
  10. }
  11. --》
  12. bool SocketDispatcher::Create(int family, int type) {
  13. // Change the socket to be non-blocking.
  14. if (!PhysicalSocket::Create(family, type))
  15. return false;
  16. // 里面将socket弄成非阻塞
  17. if (!Initialize())
  18. return false;
  19. #if defined(WEBRTC_WIN)
  20. do {
  21. id_ = ++next_id_;
  22. } while (id_ == 0);
  23. #endif
  24. return true;
  25. }
  26. -》
  27. bool PhysicalSocket::Create(int family, int type) {
  28. Close();
  29. s_ = ::socket(family, type, 0);
  30. udp_ = (SOCK_DGRAM == type);
  31. family_ = family;
  32. UpdateLastError();
  33. if (udp_) { // 这里如果是udp类型,则允许读写事件
  34. SetEnabledEvents(DE_READ | DE_WRITE);
  35. }
  36. return s_ != INVALID_SOCKET;
  37. }
  38. bool SocketDispatcher::Initialize() {
  39. RTC_DCHECK(s_ != INVALID_SOCKET);
  40. // Must be a non-blocking
  41. #if defined(WEBRTC_WIN)
  42. u_long argp = 1;
  43. ioctlsocket(s_, FIONBIO, &argp);
  44. #elif defined(WEBRTC_POSIX)
  45. fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
  46. #endif
  47. #if defined(WEBRTC_IOS)
  48. // iOS may kill sockets when the app is moved to the background
  49. // (specifically, if the app doesn't use the "voip" UIBackgroundMode). When
  50. // we attempt to write to such a socket, SIGPIPE will be raised, which by
  51. // default will terminate the process, which we don't want. By specifying
  52. // this socket option, SIGPIPE will be disabled for the socket.
  53. int value = 1;
  54. ::setsockopt(s_, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
  55. #endif
  56. ss_->Add(this);
  57. return true;
  58. }

image.png

PhysicalSocket::Connect

  1. int PhysicalSocket::Connect(const SocketAddress& addr) {
  2. // TODO(pthatcher): Implicit creation is required to reconnect...
  3. // ...but should we make it more explicit?
  4. if (state_ != CS_CLOSED) {
  5. SetError(EALREADY);
  6. return SOCKET_ERROR;
  7. }
  8. // 这里已经是ip地址了,就不会执行下面大括号里面的代码
  9. if (addr.IsUnresolvedIP()) {
  10. RTC_LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
  11. resolver_ = new AsyncResolver();
  12. resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
  13. resolver_->Start(addr);
  14. state_ = CS_CONNECTING;
  15. return 0;
  16. }
  17. return DoConnect(addr);
  18. }
  19. void PhysicalSocket::OnResolveResult(AsyncResolverInterface* resolver) {
  20. if (resolver != resolver_) {
  21. return;
  22. }
  23. int error = resolver_->GetError();
  24. if (error == 0) {
  25. error = DoConnect(resolver_->address());
  26. } else {
  27. Close();
  28. }
  29. if (error) {
  30. SetError(error);
  31. SignalCloseEvent(this, error);
  32. }
  33. }

image.png//
image.png

PhysicalSocket::DoConnect

  1. int PhysicalSocket::DoConnect(const SocketAddress& connect_addr) {
  2. if ((s_ == INVALID_SOCKET) && !Create(connect_addr.family(), SOCK_STREAM)) {
  3. return SOCKET_ERROR;
  4. }
  5. sockaddr_storage addr_storage;
  6. size_t len = connect_addr.ToSockAddrStorage(&addr_storage);
  7. sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
  8. int err = ::connect(s_, addr, static_cast<int>(len));
  9. UpdateLastError();
  10. uint8_t events = DE_READ | DE_WRITE;
  11. if (err == 0) {
  12. state_ = CS_CONNECTED;
  13. } else if (IsBlockingError(GetError())) {
  14. state_ = CS_CONNECTING;
  15. events |= DE_CONNECT;
  16. } else {
  17. return SOCKET_ERROR;
  18. }
  19. EnableEvents(events);
  20. return 0;
  21. }

这里使用了新的结构sockaddr_storage,但是又强转为sockaddr,然后调用connect函数连接。连接成功后,调用BasicNetworkManager::QueryDefaultLocalAddress里面的socket->GetLocalAddress().ipaddr()返回连接后的ip地址。