Portál AbcLinuxu, 19. dubna 2024 21:05


Dotaz: C++ a síťový provoz

David Watzke avatar 10.8.2006 23:39 David Watzke | skóre: 74 | blog: Blog... | Praha
C++ a síťový provoz
Přečteno: 92×
Odpovědět | Admin
Ahoj,

dal jsem dohromady (z mrtgutils a ještě jednoho prográmku) tenhle kód v C++, který by měl změřit síťový provoz za jednu sekundu. Hodnoty čte ze souboru /proc/net/dev, ale to není podstatný, protože tam mám spíš nějakou chybu, jenže nevím jakou... Ukazuje mi nesmysl:
dl 18014261070691488 kB/s
up 0 kB/s
Není na tohle třeba nějaká knihovna? Pokud ne, co tam mám špatně? Díky...
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
Nástroje: Začni sledovat (1) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

10.8.2006 23:49 VícNežNic | skóre: 42 | blog: Spáleniště | Ne dost daleko
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Odpovědět | | Sbalit | Link | Blokovat | Admin
No, já třeba u sebe spatřuji jistý problém v tom, že se neotevře soubor /proc/net/iface (který to otevírá), což sice program pozná (je tam return z funkce), jenže to vede k tomu, že to počítá s čísly co v té paměti jsou a proto mi z toho lezou výsledky, které jsou sice pěkně náhodné, ale taky pěkně k ničemu :-)

Pro začátek zkus program v případě že se nepovede otevřít ten soubor rovnou zabít :-)
Copak toho není dost?
NbS avatar 10.8.2006 23:49 NbS | skóre: 26 | blog: Linux jako Linux ... vsude je neco jako /etc | Prague
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Odpovědět | | Sbalit | Link | Blokovat | Admin
asi sem blbej, ale proc ten kanon kdyz staci toto :
cat /proc/net/dev | grep eth0 | awk '{print $1}'
(za predpokladu ze si zmenis eth0 :)
Pan Bily byli bily strop, aby byl bily ... (Opravdu si myslite, ze je to spravne) ?
David Watzke avatar 10.8.2006 23:51 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
1. zbytečnej cat :-D
2. v Bashi je mi to k ničemu Přesto dík za snahu.
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
NbS avatar 10.8.2006 23:54 NbS | skóre: 26 | blog: Linux jako Linux ... vsude je neco jako /etc | Prague
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Kdyz muzu rad neco podelam :)
Pan Bily byli bily strop, aby byl bily ... (Opravdu si myslite, ze je to spravne) ?
David Watzke avatar 10.8.2006 23:54 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Btw
awk '/eth0/ {print $1}' /proc/net/dev
:-)
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
NbS avatar 10.8.2006 23:59 NbS | skóre: 26 | blog: Linux jako Linux ... vsude je neco jako /etc | Prague
Rozbalit Rozbalit vše Re: C++ a síťový provoz
37,44 a 7, prave o tech 7 znaku se lisime, ale vysledek to hazi stejnej, tak co :))
Pan Bily byli bily strop, aby byl bily ... (Opravdu si myslite, ze je to spravne) ?
David Watzke avatar 11.8.2006 00:14 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Tak co?
$ time for ((i=0; i<999; i++))
do
  awk '/eth0/ {print $1}' /proc/net/dev
done > /dev/null

real    0m2.008s
user    0m0.908s
sys     0m1.092s

$ time for ((i=0; i<999; i++))
do
  cat /proc/net/dev | grep eth0 | awk '{print $1}'
done > /dev/null

real    0m5.584s
user    0m2.261s
sys     0m3.295s
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
NbS avatar 11.8.2006 00:41 NbS | skóre: 26 | blog: Linux jako Linux ... vsude je neco jako /etc | Prague
Rozbalit Rozbalit vše Re: C++ a síťový provoz
pan je detailista ? :) zivot se prece pocita na desitky let :))
Pan Bily byli bily strop, aby byl bily ... (Opravdu si myslite, ze je to spravne) ?
10.8.2006 23:51 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Odpovědět | | Sbalit | Link | Blokovat | Admin
IMHO je problém v tom, že se snažíte otevírat neexistující soubor. Budiž to ponaučením, že ignorovat chybové stavy se nevyplácí…
David Watzke avatar 10.8.2006 23:52 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Jo, nahrazoval jsem hromadně dev za iface a... sakra :-( No, vyřešeno, dík...
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
10.8.2006 23:57 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Ještě obvyklá připomínka: když už člověk používá C++, stojí za to ho používat skutečně jako C++, ne jako trochu obohacené C. S využitím standardní C++ knihovny by se to dalo napsat mnohem elegantněji.
David Watzke avatar 11.8.2006 00:00 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
S využitím standardní C++ knihovny by se to dalo napsat mnohem elegantněji.
Věřím. Zatím nemám peníze na Mistrovství v C++, takže to asi nevymyslím :-(
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
11.8.2006 00:05 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Tak zkuste Thinking in C++ od Eckela. To není špatná kniha a jak by řekl Béda Trávníček: "A máte to zadarmo!" :-)
David Watzke avatar 11.8.2006 02:18 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
No, já bych raději česky. V češtině to sotva chápu, natož to luštit anglicky :-) Zatím zkusím najít nějaký program v C++, ve kterém se se soubory z /proc pracuje, abych viděl jak to z nich dolují :-)
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
11.8.2006 00:01 VícNežNic | skóre: 42 | blog: Spáleniště | Ne dost daleko
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Ano, tenhle příklad by s takovým ifstreamem mohl nefungovat o dost elegantněji než teď :-)
Copak toho není dost?
11.8.2006 00:12 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Jest tu jistá naděje, že by autor místo return vyhodil exception, takže by zjistil, co se děje… :-)
David Watzke avatar 16.8.2006 03:21 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
ifstream f("/proc/net/dev");
string s;
while(getline(f, s))
	if (s.find("eth0") != -1)
		cout << s << endl;
Tohle vypíše řádek obsahující "eth0", jenže jak z toho dostat ty dvě hodnoty (počet přijatých a odeslaných bajtů) aby to bylo mnohem elegantnější?
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
16.8.2006 11:13 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: C++ a síťový provoz

Např. takhle:

class Netload {
public:
  typedef unsigned long long count_t;
  std::string name;
  count_t d;
  count_t u;

  Netload(count_t id = 0, count_t iu = 0) { d = id; u = iu; }
  ~Netload() {}

  const Netload operator - (const Netload& x);
};

inline const Netload Netload::operator - (const Netload& x)
{
  return Netload(d - x.d, u - x.u);
}

std::istream& operator >> (std::istream& s, Netload& x)
{
  std::string buff;
  getline(s, buff, ':');
  if (!s) return s;
  s >> x.d;
  Netload::count_t tmp;
  for (int i=0; i<7; i++)
    s >> x;
  s >> x.u;
  s.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  return s;
}

bool GetStat(const std::string& ifname, Netload& stat)
{
  std::ifstream s("/proc/net/dev");
  if (!s) throw std::runtime_error("cannot open /proc/net/dev");

  s.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  s.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  while (s >> stat) {
    if (stat.name == ifname) return true;
  }

  return false;
}
David Watzke avatar 16.8.2006 15:26 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Wow... díky moc. Nejsem si úplně jistý, zda je to elegantnější než v C, rozhodně to IMHO není jednodušší :-D

Btw, budu to ještě muset ověřit, ale když použiju tenhle main(), tak se zdá že neměří upload, ukáže vždy nulu...
int main(int argc, char** argv) {
	if (argc != 2) {
		cout << "Usage: " << argv[0] << " eth0\n";
		return 1;
	}

	Netload before, now, diff;

	GetStat(argv[1], before);
	sleep(1);
	GetStat(argv[1], now);

	diff.d = now.d - before.d;
	diff.u = now.u - before.u;

	cout << "dl " << diff.d / 1024 << " kB/s\nup " << diff.u / 1024 << " kB/s\n";
}
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
16.8.2006 16:06 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: C++ a síťový provoz

To bude tím, že jsem to nezkoušel. :-) Jinak by tento jednoúčelový prográmek šel samozřejmě napsat jednodušeji, ale předpokládám, že s těmi hodnotami budete chtít pracovat nějak soustavněji, takže spíš než na jednoduchost implementace té třídy jsem se zaměřil na jednoduchost použití. Zrovna tak místo konstanty 'std::numeric_limits<std::streamsize>::max()' jsem mohl napsat třeba 256, ale IMHO je lepší si na podobné bulharské konstanty nezvykat a psát všude to, co tam logicky patří. Takže druhý pokus:

#include <iostream>
#include <fstream>
#include <stdexcept>
#include <unistd.h> // sleep

class Netload {
public:
  typedef unsigned long long count_t;
  std::string name;
  count_t d;
  count_t u;

  Netload() { d = u = 0; }
  Netload(std::string& iname, count_t id = 0, count_t iu = 0)
    : name(iname) { d = id; u = iu; }
  ~Netload() {}

  const Netload operator - (const Netload& x);
};

inline const Netload Netload::operator - (const Netload& x)
{
  return Netload(name, d - x.d, u - x.u);
}

inline void trimleft(std::string& s)
{
  unsigned i = 0;
  unsigned L = s.length();
  while (i<L && s[i]==' ') i++;
  s.erase(0, i);
}

std::istream& operator >> (std::istream& s, Netload& x)
{
  getline(s, x.name, ':');
  if (!s) return s;
  trimleft(x.name);
  s >> x.d;
  Netload::count_t tmp;
  for (int i=0; i<7; i++)
    s >> tmp;
  s >> x.u;
  s.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  return s;
}

std::ostream& operator << (std::ostream& s, const Netload& x)
{
  s << x.name << ": dn " << x.d/1024 << " KB, up " << x.u/1024 << " KB\n";
  return s;
}


void GetStat(const std::string& ifname, Netload& stat)
{
  std::ifstream s("/proc/net/dev");
  if (!s) throw std::runtime_error("cannot open /proc/net/dev");

  s.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  s.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  while (s >> stat) {
    if (stat.name == ifname) return;
  }

  throw std::runtime_error("cannot read statistics for selected interface");
}


int main(int argc, char** argv)
{
  try {
    if (argc != 2)
      throw std::runtime_error("Usage: transfer <ifname>");

    Netload before, now;

    GetStat(argv[1], before);
    sleep(1);
    GetStat(argv[1], now);

    std::cout << (now - before);
    return 0;
  }
  catch(std::exception& e) {
    std::cerr << "transfer: " << e.what() << std::endl;
    return 1;
  }
}

Tou elegancí jsem myslel hlavně to, jak se vám zpřehlední právě main() a zejména zpracování chyb. Díky použití nástrojů jazyka C++ můžete totiž oddělit reakci na chybu od její detekce.

David Watzke avatar 16.8.2006 16:15 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Aha, díky. Tohle už funguje pěkně. Mám se ještě co učit...
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
Josef Kufner avatar 16.8.2006 16:06 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Odpovědět | | Sbalit | Link | Blokovat | Admin
$ mrtg-ip-acct eth0
236054352
240845652
  4:05pm  up 199 days, 12:11,  1 user,  load average: 0.00, 0.02, 0.00
localhost
Hello world ! Segmentation fault (core dumped)
David Watzke avatar 16.8.2006 16:11 David Watzke | skóre: 74 | blog: Blog... | Praha
Rozbalit Rozbalit vše Re: C++ a síťový provoz
Já vím :-)
“Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.