⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 network.cc

📁 本人收集整理的一份c/c++跨平台网络库
💻 CC
字号:
#include <algorithm>#include <cassert>#include <cfloat>#include <cmath>#include <sstream>#ifdef POSIXextern "C" {#include <sys/socket.h>#include <sys/utsname.h>#include <sys/ioctl.h>#include <net/if.h>#include <unistd.h>#include <errno.h>}#endif // POSIX#ifdef WIN32#include "win32.h"#include <Iphlpapi.h>#endif#include "host.h"#include "logging.h"#include "network.h"#include "socket.h" // this includes something that makes windows happy#include "stringencode.h"#include "time.h"#include "basicdefs.h"namespace {const double kAlpha = 0.5; // weight for data infinitely far in the pastconst double kHalfLife = 2000; // half life of exponential decay (in ms)const double kLog2 = 0.693147180559945309417;const double kLambda = kLog2 / kHalfLife;// assume so-so quality unless data says otherwiseconst double kDefaultQuality = utils_base::QUALITY_FAIR;typedef std::map<std::string,std::string> StrMap;void BuildMap(const StrMap& map, std::string& str) {  str.append("{");  bool first = true;  for (StrMap::const_iterator i = map.begin(); i != map.end(); ++i) {    if (!first) str.append(",");    str.append(i->first);    str.append("=");    str.append(i->second);    first = false;  }  str.append("}");}void ParseCheck(std::istringstream& ist, char ch) {  if (ist.get() != ch)    LOG(LERROR) << "Expecting '" << ch << "'";}std::string ParseString(std::istringstream& ist) {  std::string str;  int count = 0;  while (ist) {    char ch = ist.peek();    if ((count == 0) && ((ch == '=') || (ch == ',') || (ch == '}'))) {      break;    } else if (ch == '{') {      count += 1;    } else if (ch == '}') {      count -= 1;      if (count < 0)        LOG(LERROR) << "mismatched '{' and '}'";    }    str.append(1, static_cast<char>(ist.get()));  }  return str;}void ParseMap(const std::string& str, StrMap& map) {  if (str.size() == 0)    return;  std::istringstream ist(str);  ParseCheck(ist, '{');  for (;;) {    std::string key = ParseString(ist);    ParseCheck(ist, '=');    std::string val = ParseString(ist);    map[key] = val;    if (ist.peek() == ',')      ist.get();    else      break;  }  ParseCheck(ist, '}');  if (ist.rdbuf()->in_avail() != 0)    LOG(LERROR) << "Unexpected characters at end";}#if 0const std::string TEST_MAP0_IN = "";const std::string TEST_MAP0_OUT = "{}";const std::string TEST_MAP1 = "{a=12345}";const std::string TEST_MAP2 = "{a=12345,b=67890}";const std::string TEST_MAP3 = "{a=12345,b=67890,c=13579}";const std::string TEST_MAP4 = "{a={d=12345,e=67890}}";const std::string TEST_MAP5 = "{a={d=12345,e=67890},b=67890}";const std::string TEST_MAP6 = "{a=12345,b={d=12345,e=67890}}";const std::string TEST_MAP7 = "{a=12345,b={d=12345,e=67890},c=13579}";class MyTest {public:  MyTest() {    test(TEST_MAP0_IN, TEST_MAP0_OUT);    test(TEST_MAP1, TEST_MAP1);    test(TEST_MAP2, TEST_MAP2);    test(TEST_MAP3, TEST_MAP3);    test(TEST_MAP4, TEST_MAP4);    test(TEST_MAP5, TEST_MAP5);    test(TEST_MAP6, TEST_MAP6);    test(TEST_MAP7, TEST_MAP7);  }  void test(const std::string& input, const std::string& exp_output) {    StrMap map;    ParseMap(input, map);    std::string output;    BuildMap(map, output);    LOG(INFO) << "  ********  " << (output == exp_output);  }};static MyTest myTest;#endif} // namespacenamespace utils_base {#ifdef POSIXvoid NetworkManager::CreateNetworks(std::vector<Network*>& networks) {  int fd;  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {    PLOG(LERROR, errno) << "socket";    return;  }  struct ifconf ifc;  ifc.ifc_len = 64 * sizeof(struct ifreq);  ifc.ifc_buf = new char[ifc.ifc_len];  if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {    PLOG(LERROR, errno) << "ioctl";    return;  }  assert(ifc.ifc_len < static_cast<int>(64 * sizeof(struct ifreq)));  struct ifreq* ptr = reinterpret_cast<struct ifreq*>(ifc.ifc_buf);  struct ifreq* end =      reinterpret_cast<struct ifreq*>(ifc.ifc_buf + ifc.ifc_len);  while (ptr < end) {    if (strcmp(ptr->ifr_name, "lo")) { // Ignore the loopback device      struct sockaddr_in* inaddr =          reinterpret_cast<struct sockaddr_in*>(&ptr->ifr_ifru.ifru_addr);      if (inaddr->sin_family == AF_INET) {        uint32 ip = ntohl(inaddr->sin_addr.s_addr);        networks.push_back(new Network(std::string(ptr->ifr_name), ip));      }    }#ifdef _SIZEOF_ADDR_IFREQ    ptr = reinterpret_cast<struct ifreq*>(        reinterpret_cast<char*>(ptr) + _SIZEOF_ADDR_IFREQ(*ptr));#else    ptr++;#endif  }  delete [] ifc.ifc_buf;  close(fd);}#endif#ifdef WIN32void NetworkManager::CreateNetworks(std::vector<Network*>& networks) {  IP_ADAPTER_INFO info_temp;  ULONG len = 0;    if (GetAdaptersInfo(&info_temp, &len) != ERROR_BUFFER_OVERFLOW)    return;  IP_ADAPTER_INFO *infos = new IP_ADAPTER_INFO[len];  if (GetAdaptersInfo(infos, &len) != NO_ERROR)    return;  int count = 0;  for (IP_ADAPTER_INFO *info = infos; info != NULL; info = info->Next) {    if (info->Type == MIB_IF_TYPE_LOOPBACK)      continue;    if (strcmp(info->IpAddressList.IpAddress.String, "0.0.0.0") == 0)      continue;    // In production, don't transmit the network name because of    // privacy concerns. Transmit a number instead.    std::string name;#if defined(PRODUCTION)    std::ostringstream ost;    ost << count;    name = ost.str();    count++;#else    name = info->Description;#endif    networks.push_back(new Network(name,        SocketAddress::StringToIP(info->IpAddressList.IpAddress.String)));  }  delete infos;}#endifvoid NetworkManager::GetNetworks(std::vector<Network*>& result) {  std::vector<Network*> list;  CreateNetworks(list);  for (uint32 i = 0; i < list.size(); ++i) {    NetworkMap::iterator iter = networks_.find(list[i]->name());    Network* network;    if (iter == networks_.end()) {      network = list[i];    } else {      network = iter->second;      network->set_ip(list[i]->ip());      delete list[i];    }    networks_[network->name()] = network;    result.push_back(network);  }}std::string NetworkManager::GetState() {  StrMap map;  for (NetworkMap::iterator i = networks_.begin(); i != networks_.end(); ++i)    map[i->first] = i->second->GetState();  std::string str;  BuildMap(map, str);  return str;}void NetworkManager::SetState(std::string str) {  StrMap map;  ParseMap(str, map);  for (StrMap::iterator i = map.begin(); i != map.end(); ++i) {    std::string name = i->first;    std::string state = i->second;    Network* network = new Network(name, 0);    network->SetState(state);    networks_[name] = network;  }}Network::Network(const std::string& name, uint32 ip)  : name_(name), ip_(ip), uniform_numerator_(0), uniform_denominator_(0),    exponential_numerator_(0), exponential_denominator_(0),    quality_(kDefaultQuality) {  last_data_time_ = Time();  // TODO: seed the historical data with one data point based on the link speed  //       metric from XP (4.0 if < 50, 3.0 otherwise).}void Network::StartSession(NetworkSession* session) {  assert(std::find(sessions_.begin(), sessions_.end(), session) == sessions_.end());  sessions_.push_back(session);}void Network::StopSession(NetworkSession* session) {  SessionList::iterator iter = std::find(sessions_.begin(), sessions_.end(), session);  if (iter != sessions_.end())    sessions_.erase(iter);}void Network::EstimateQuality() {  uint32 now = Time();  // Add new data points for the current time.  for (uint32 i = 0; i < sessions_.size(); ++i) {    if (sessions_[i]->HasQuality())      AddDataPoint(now, sessions_[i]->GetCurrentQuality());  }  // Construct the weighted average using both uniform and exponential weights.  double exp_shift = exp(-kLambda * (now - last_data_time_));  double numerator = uniform_numerator_ + exp_shift * exponential_numerator_;  double denominator = uniform_denominator_ + exp_shift * exponential_denominator_;  if (denominator < DBL_EPSILON)    quality_ = kDefaultQuality;  else    quality_ = numerator / denominator;}std::string Network::ToString() const {  std::stringstream ss;  // Print out the first space-terminated token of the network name, plus  // the IP address.  ss << "Net[" << name_.substr(0, name_.find(' '))      << ":" << SocketAddress::IPToString(ip_) << "]";  return ss.str();}void Network::AddDataPoint(uint32 time, double quality) {  uniform_numerator_ += kAlpha * quality;  uniform_denominator_ += kAlpha;  double exp_shift = exp(-kLambda * (time - last_data_time_));  exponential_numerator_ = (1 - kAlpha) * quality + exp_shift * exponential_numerator_;  exponential_denominator_ = (1 - kAlpha) + exp_shift * exponential_denominator_;  last_data_time_ = time;}std::string Network::GetState() {  StrMap map;  map["lt"] = utils_base::ToString<uint32>(last_data_time_);  map["un"] = utils_base::ToString<double>(uniform_numerator_);  map["ud"] = utils_base::ToString<double>(uniform_denominator_);  map["en"] = utils_base::ToString<double>(exponential_numerator_);  map["ed"] = utils_base::ToString<double>(exponential_denominator_);  std::string str;  BuildMap(map, str);  return str;}void Network::SetState(std::string str) {  StrMap map;  ParseMap(str, map);  last_data_time_ = FromString<uint32>(map["lt"]);  uniform_numerator_ = FromString<double>(map["un"]);  uniform_denominator_ = FromString<double>(map["ud"]);  exponential_numerator_ = FromString<double>(map["en"]);  exponential_denominator_ = FromString<double>(map["ed"]);}} // namespace utils_base

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -