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);
#endif
return 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));
#endif
ss_->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地址。