• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Kalkulator sieciowy C++

VPS Starter Arubacloud
0 głosów
509 wizyt
pytanie zadane 12 stycznia 2020 w Nasze projekty przez krupier Nowicjusz (120 p.)
edycja 12 stycznia 2020 przez krupier

Witam.

Chciałbym w tym poście pochwalić się moim projektem kalkulatora sieci napisanego w C++. Ciekaw jestem opinii oraz sugestii co poprawić, dodać lub zmienić w kodzie.

Link: Repozytorium Github

komentarz 12 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
Dlaczego mieszasz stringi z tablicami charów? Dlaczego stringi przez wartość?
komentarz 12 stycznia 2020 przez krupier Nowicjusz (120 p.)
Nie rozumiem, o jaki konkretnie fragment kodu chodzi?
komentarz 12 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
komentarz 12 stycznia 2020 przez krupier Nowicjusz (120 p.)
edycja 13 stycznia 2020 przez krupier

Funkcja "strtok" znajuduje się w "string.h". Wcześniej chciałem dać tam tablice, ale funkcja modyfikuje wartość zmiennej i zwraca tylko pierwszy oktet adresu.

Przykład:

bool is_valid_ip(char *ip_input)
{
    int num, dots = 0;
    char *ptr, *buffer = ip_input;

    if (buffer == NULL) return false;
    ptr = strtok(buffer, DELIM);

    //...
}

Takie rozwiązanie próbowałem zastosować, ale modyfikacji ulega zmienna "buffer" jak i "ip_input".

Nie wiem czemu, ale tylko jeśli mam zadeklarowany string to nie ma problemu i adres IP pozostaje nienaruszony.

Nie wiem, czy dobrze wyjaśniłem, ale jak jest tak jak obecnie w repozytorium to zmienna "ip_input" cały czas ma wartość "192.168.0.1", a jak był "char *" to wartość byłaby tylko "192"

Jeśli jest lepsze rozwiązanie, to chętnie je poznam.

komentarz 13 stycznia 2020 przez tkz Nałogowiec (42,000 p.)

Do dzielenia stringa https://www.fluentcpp.com/2017/04/21/how-to-split-a-string-in-c/ Zawsze możesz wysłać const & by nie uległa zmianie wartość stringa, albo string_view. Co do walidacji ip, o ile chcesz możesz użyć boost'a i moduł asio. 

// Example program
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
#include <string_view>
#include <sstream>
std::vector<std::string> split(const std::string& s, char delimiter)
{
   std::vector<std::string> tokens;
   std::string token;
   std::istringstream tokenStream(s);
   while (std::getline(tokenStream, token, delimiter))
   {
      tokens.push_back(token);
   }
   return tokens;
}

bool valid(std::string_view string)
{
    for(auto const& i :string)
    {
        if(!isdigit(i))
            return false;
    }
    return true;
}
int main()
{
    for(const auto& i : split(std::string("192.168.0.1"), '.'))
        std::cout<<valid(i)<<'\n';
}

http://quick-bench.com/85oXgTKD-yaCY8JO1V7h9EQdQOI

Twoje jest szybsze, o dziwo. Pewnie zrobiłem coś głupiego, poprawie jak przyjdę do domu. 

komentarz 13 stycznia 2020 przez mokrowski Mędrzec (155,460 p.)
Ja bym się zastanawiał czy warto tak komplikować.Nie widzę powodów by aż tak "śrubować wydajność". Nie wystarcza scanf(...) ?

http://quick-bench.com/qUw3A30O-ZTUScY4R7uvXhCYtrA

A co do strtok(...). Od tego jest by być szybki :) Ale jak się dokładniej przyjrzeć, bywa że jego efekty uboczne (w jego przypadku pamięć stanu parsowania), dyskwalifikują go w wielu przypadkach.

Czy można jeszcze szybciej.... no można. Tylko czy taki jest cel ?
komentarz 13 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
W tym przypadku pewnie nie, ale chęć, przynajmniej moja, na zagłębienie się w branżę "low-latency" sprawia, że uczę się tych małych detali, które mają wpływ na wydajność, nawet tą najmniejszą. Teraz patrzę na mój kod i użycie "ciężkich" typów danych kompletnie mija się z moim założeniem.

1 odpowiedź

0 głosów
odpowiedź 13 stycznia 2020 przez mokrowski Mędrzec (155,460 p.)

Narzędzie ipcalc, jest dostępne w dystrybucjach z rodziny debian (co do innych także wiem że jest ale już nie będę szukał czy to samo). Tu masz witrynę domową: http://jodies.de/ipcalc

Możesz pomyśleć o notacji CIDR, dopuszczalnych "rutowalnych sieciach" (polskie słowo trasowalnych jest jednak trochę.. dziwne :) ), sieciach specjalnych (np. multicast)

Co do kodu... sugestie a nie prawdy objawione i nie ukrywam że tylko przeglądam:

1. W CMakeLists.txt dodał bym hurtem wszystkie *.cpp. Chyba że masz jakieś powody by je wydzielać.

2. Nie chciałeś wykorzystać getopt(..) przy parsowaniu przełączników? Jakiś powód?

man 3 getopt

3. Stosuj nawiasy przy większej ilości argumentów w if. Dobra praktyka i często wymaganie metodyk wytwarzania dla systemów krytycznych.

4. W przypadku braku różnicy pomiędzy prze i post inkrementacją, preferuj pre.

5. W przypadku posiadania wiedzy ile jest elementów (np. w std::vector), dobrze jest zrobić vec.reserve(..) i stosować emplace_back(...). Nawet lepiej często zastosować std::array. Alokuje na stosie (więc może choć niekoniecznie być nieco szybciej) i ma sztywną ilość elementów.

6. Nie wiem co to za "kwiatek" jest w netmask.cpp w 10 linii. std::string przecież ma konstruktor wypełniający znakiem.

7. Jeśli nie modyfikujesz kontenera lub string'a, prześlij go jako const referencję lub dla string'a string_view.

8. get_network_addresses.cpp okolice 37. Jeśli nie modyfikujesz danych a tylko trzymasz wskaźnik, to raczej powinien być:

const void * tmpAddrPtr = nullptr;

czyli modyfikowalny wskaźnik na stałe dane. Inną sprawą jest ... czy to ma być aż takie ostre. void * to brzmi groźnie.

9. W tym samym pliku: 78 i 79 linia.. z jakiego powodu tam jest struct? To przecież C++ a nie C.

10. Nagłówki bez strażników lub pragma once to bardzo słaby pomysł.

11. Masz trochę nieporządku w nagłówkach. Np. w check_ip.h, nie wiem z jakiego powodu występuje coś czego nie ma ani jako argumentów w funkcji ani jako wywołania.

12. W get_network_addresses.h masz nawciąganych stado nagłówków które powinny być w pliku implementacji.

To tak na pierwszy rzut..

komentarz 13 stycznia 2020 przez krupier Nowicjusz (120 p.)

1. W CMakeLists mam wydzielone ponieważ strypt nie wykrywał plików.

set(SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp)

Ale znalazłem rozwiązanie:

file(GLOB SOURCES src/*.cpp)

W tym przypadku działa.

2. Wcześniej poprostu nie znałem tej funkcji.

6. Zakładam, że chodzi o zmienną "bin_netmask", chodzi o to, że programie wartość binarna adresu musi mieć stałą wartość 32 bitów (znaków). Wcześniej miałem dwie pętle, jedna dodawała jedynki, a potem druga pętla uzupełniała zerami, aż string osiągnie liczbę 32 bitów. Uznałem, że dwie pętle są niepotrzebne i lepiej dać szablon, który jest potem tylko modyfikowany przez funkcje.

Do reszty punktów mogę się odnieść w ten sposób, że po prostu zdaje sobie sprawę z tego, że jestem amatorem i programując, jestem dopiero na początku drogi i o niektórych rzeczach po prostu nie mam jeszcze pojęcia jak zrobić coś w dobry i optymalny sposób. Nadal się uczę i chcę poszerzać wiedzę z programowania.

komentarz 13 stycznia 2020 przez mokrowski Mędrzec (155,460 p.)

W tym zawodzie każdy i cały czas się uczy :-) Pobieżnie przeglądałem kod i z całą pewnością coś jeszcze można zauważyć.

Co do 6...

Zamiast tego...

std::string bin_netmask = "00000000000000000000000000000000";

Lepiej tak:

std::string bin_netmask{32, '1'};

Tym bardziej że kilka linii niżej właśnie wypełniasz jedynkami.

PS. Chociaż gdybym miał to napisać, pewnie coś na arytmetyce bitów bym robił.

komentarz 13 stycznia 2020 przez krupier Nowicjusz (120 p.)
Dzięki, też się myślałem nad tym, ale w internecie nie mogłem dostateczne dużo znaleźć na temat przechowywania wartości binarnych, próbowałem z "intem" ale jak początkowa cyfra była zerem, to całkiem inne wartości wychodziły. Szukałem rozwiązania, ale doszedłem do wniosku, że jak na razie to "string" najłatwiej się implementuje.

Podobne pytania

0 głosów
2 odpowiedzi 368 wizyt
+2 głosów
1 odpowiedź 238 wizyt

92,453 zapytań

141,262 odpowiedzi

319,087 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...