Socket

PhysicalSocketServer 真正物理网络连接的socket工厂类,多平台使用。
Win32SocketServer Windows下的处理socket事件工厂类,只能在Windows下。
NullSocketServer 只有基础事件处理功能,没有socket功能,不能处理网络事件。
PhysicalSocket::Connect
支持域名和ip连接。
判断是否还没解析成ip,没有则创建一个线程AsncResolver来异步解析,解析成功后调用OnResolverResult,里面也会调用DonConnect来连接服务器。
AsyncResolver继承了AsyncResolverInterface,主要使用了 sigslot::signal1信号槽机制。
代码分析
BasicNetworkManager::UpdateNetworksOnce
在这里调用QueryDefaultLocalAddress获取本地默认的ip地址和端口,然后set_default_local_addresses来设置本地默认的ip地址和端口。
void BasicNetworkManager::UpdateNetworksOnce() {if (!start_count_)return;NetworkList list;if (!CreateNetworks(false, &list)) {SignalError();} else {bool changed;NetworkManager::Stats stats;MergeNetworkList(list, &changed, &stats);set_default_local_addresses(QueryDefaultLocalAddress(AF_INET),QueryDefaultLocalAddress(AF_INET6));if (changed || !sent_first_update_) {SignalNetworksChanged();sent_first_update_ = true;}}}
BasicNetworkManager::QueryDefaultLocalAddress
IPAddress BasicNetworkManager::QueryDefaultLocalAddress(int family) const {RTC_DCHECK(thread_->socketserver() != nullptr);RTC_DCHECK(family == AF_INET || family == AF_INET6);// 创建AsyncSocket对象std::unique_ptr<AsyncSocket> socket(thread_->socketserver()->CreateAsyncSocket(family, SOCK_DGRAM));if (!socket) {RTC_LOG_ERR(LERROR) << "Socket creation failed";return IPAddress();}// 连接服务器/* 宏定义是const char kPublicIPv4Host[] = "8.8.8.8";const char kPublicIPv6Host[] = "2001:4860:4860::8888";const int kPublicPort = 53; // DNS port.*/if (socket->Connect(SocketAddress(family == AF_INET ? kPublicIPv4Host : kPublicIPv6Host, kPublicPort)) <0) {if (socket->GetError() != ENETUNREACH &&socket->GetError() != EHOSTUNREACH) {// Ignore the expected case of "host/net unreachable" - which happens if// the network is V4- or V6-only.RTC_LOG(LS_INFO) << "Connect failed with " << socket->GetError();}return IPAddress();}return socket->GetLocalAddress().ipaddr();}
PhysicalSocketServer::CreateAsyncSocket
H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\rtc_base\physical_socket_server.cc
// 这里创建了socket分发器AsyncSocket* PhysicalSocketServer::CreateAsyncSocket(int family, int type) {SocketDispatcher* dispatcher = new SocketDispatcher(this);if (dispatcher->Create(family, type)) {return dispatcher;} else {delete dispatcher;return nullptr;}}--》bool SocketDispatcher::Create(int family, int type) {// Change the socket to be non-blocking.if (!PhysicalSocket::Create(family, type))return false;// 里面将socket弄成非阻塞if (!Initialize())return false;#if defined(WEBRTC_WIN)do {id_ = ++next_id_;} while (id_ == 0);#endifreturn true;}-》bool PhysicalSocket::Create(int family, int type) {Close();s_ = ::socket(family, type, 0);udp_ = (SOCK_DGRAM == type);family_ = family;UpdateLastError();if (udp_) { // 这里如果是udp类型,则允许读写事件SetEnabledEvents(DE_READ | DE_WRITE);}return s_ != INVALID_SOCKET;}bool SocketDispatcher::Initialize() {RTC_DCHECK(s_ != INVALID_SOCKET);// Must be a non-blocking#if defined(WEBRTC_WIN)u_long argp = 1;ioctlsocket(s_, FIONBIO, &argp);#elif defined(WEBRTC_POSIX)fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);#endif#if defined(WEBRTC_IOS)// iOS may kill sockets when the app is moved to the background// (specifically, if the app doesn't use the "voip" UIBackgroundMode). When// we attempt to write to such a socket, SIGPIPE will be raised, which by// default will terminate the process, which we don't want. By specifying// this socket option, SIGPIPE will be disabled for the socket.int value = 1;::setsockopt(s_, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));#endifss_->Add(this);return true;}
PhysicalSocket::Connect
int PhysicalSocket::Connect(const SocketAddress& addr) {// TODO(pthatcher): Implicit creation is required to reconnect...// ...but should we make it more explicit?if (state_ != CS_CLOSED) {SetError(EALREADY);return SOCKET_ERROR;}// 这里已经是ip地址了,就不会执行下面大括号里面的代码if (addr.IsUnresolvedIP()) {RTC_LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";resolver_ = new AsyncResolver();resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);resolver_->Start(addr);state_ = CS_CONNECTING;return 0;}return DoConnect(addr);}void PhysicalSocket::OnResolveResult(AsyncResolverInterface* resolver) {if (resolver != resolver_) {return;}int error = resolver_->GetError();if (error == 0) {error = DoConnect(resolver_->address());} else {Close();}if (error) {SetError(error);SignalCloseEvent(this, error);}}
PhysicalSocket::DoConnect
int PhysicalSocket::DoConnect(const SocketAddress& connect_addr) {if ((s_ == INVALID_SOCKET) && !Create(connect_addr.family(), SOCK_STREAM)) {return SOCKET_ERROR;}sockaddr_storage addr_storage;size_t len = connect_addr.ToSockAddrStorage(&addr_storage);sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);int err = ::connect(s_, addr, static_cast<int>(len));UpdateLastError();uint8_t events = DE_READ | DE_WRITE;if (err == 0) {state_ = CS_CONNECTED;} else if (IsBlockingError(GetError())) {state_ = CS_CONNECTING;events |= DE_CONNECT;} else {return SOCKET_ERROR;}EnableEvents(events);return 0;}
这里使用了新的结构sockaddr_storage,但是又强转为sockaddr,然后调用connect函数连接。连接成功后,调用BasicNetworkManager::QueryDefaultLocalAddress里面的socket->GetLocalAddress().ipaddr()返回连接后的ip地址。
//
