Aplikacja Server i Client

problemy z tworzeniem programów do obsługi sieci, internetu, e-mail itp..

Aplikacja Server i Client

Nowy postprzez Bert1223 » wtorek, 23 lutego 2010, 22:30

Witam, chciałbym napisać dwie aplikacje, jedną Serwer i drugą Client.
Za zadanie mam stworzyć Serwer który będzie przetrzymywał dane użytkowników i dane produktów oraz Clienta który będzie pobierał login i hasło sprawdzał czy taki użytkownik istnieje, a następnie udostępni dane dotyczące produktów. Udało mi się stworzyć Clienta który łączy się z Serwerem, Serwer w zdażeniu OnConnect dałe zwykły ShowMessage, przez co widać, że działa Serwer jak i Client. Mam zainstalowanego CodeGrea 2007 nie wiem jak sprawdzić wersję Indy.
Chciałbym zapytać jak mogę przesłać text z polu edit i jak odebrać go przez Serwer? Kolejnym pytaniem będzie jak sprawdzić który Client wysyła dane do logowania tak aby Serwer wiedział komu udzielić dostępu do danych o produktach?
Avatar użytkownika
Bert1223
Bladawiec
Bladawiec
 
Posty: 45
Dołączył(a): czwartek, 15 października 2009, 02:41
Podziękował : 6
Otrzymał podziękowań: 0
    Windows 7Chrome

Re: Aplikacja Server i Client

Nowy postprzez Bert1223 » środa, 24 lutego 2010, 08:37

Dołożyłem button i zdarzenie click a w nim:
Kod: Zaznacz cały
TCPClient->Socket->WriteLn(...)
oraz w serwerze w zdarzeniu Execute
Kod: Zaznacz cały
   
String command = AContext->Connection->Socket->ReadLn();
    ShowMessage(command);

Teraz po prostu sprawdzić czy przesłane dane użytkownika zgadzają się w bazie i odesłać do klienta 0 lub 1. Tylko jak wysłać do tego clienta który wysłał login i hasło i jak odebrać dane na aplikacji klienta.
Chciałbym zapytać jak jest różnica między WriteLn, a WriteBuffer i jak używać tego bufora.
Avatar użytkownika
Bert1223
Bladawiec
Bladawiec
 
Posty: 45
Dołączył(a): czwartek, 15 października 2009, 02:41
Podziękował : 6
Otrzymał podziękowań: 0
    Windows 7Chrome

Re: Aplikacja Server i Client

Nowy postprzez Cyfrowy Baron » środa, 24 lutego 2010, 12:05

Klienta możesz identyfikować po jego IP. Niech po podłączeniu do Serwera, Klient wraz z loginem i hasłem wysyła mu swój IP, lub też po prostu niech Serwer sprawdza IP klienta. Powiąż login z IP, jeżeli po sprawdzeniu w bazie danych hasło zgadza się z loginem, wtedy Serwer wysyła komunikat do klienta pod konkretny IP powiązany z loginem. Nie możesz stworzyć powiązania IP z loginem na stałe, gdyż IP może się zmieniać podczas każdej sesji, więc Serwer musi tworzyć powiązanie przy każdym podłączeniu się klienta i trzymać to powiązanie do czasu zakończenia sesji z Klientem, w jakiejś bazie tymczasowej.



Wersję Indy można sprawdzić umieszczając na formularzu dowolny komponent z pakietu INDY, a następnie klikając na nim prawym klawiszem myszy należy wybrać polecenie About Internet Direct (Indy)...

W CodeGear C++Builder 2007 pakiet INDY występuje w wersji 10.1.5
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Aplikacja Server i Client

Nowy postprzez polymorphism » środa, 24 lutego 2010, 13:25

Klienta możesz identyfikować po jego IP.

Hmm, problem w tym, że nie wszyscy klienci mogą mieć zewnętrzne IP (vide brama sieciowa, NAT). Lepiej login powiązać z aktualnym połączeniem (socketem), jeśli jest podtrzymywane przez całą sesję.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Aplikacja Server i Client

Nowy postprzez Cyfrowy Baron » środa, 24 lutego 2010, 14:20

Przecież, by serwer mógł się komunikować z konkretnym klientem musi mieć jego IP, zewnętrzne lub lokalne. Jak wielu klientów może mieć to samo IP w tej samej sieci?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Aplikacja Server i Client

Nowy postprzez polymorphism » środa, 24 lutego 2010, 15:00

Przecież, by serwer mógł się komunikować z konkretnym klientem musi mieć jego IP (...)

No nie musi, tzn. to nie jest ten poziom w modelu sieciowym, w którym aplikacja typu serwer działa (a działa w warstwie aplikacji). Dla niego łącznikiem z klientem jest połączenie, gniazdo (socket).

(...) zewnętrzne lub lokalne

A co mu po lokalnym IP?

Jak wielu klientów może mieć to samo IP w tej samej sieci?

W tej samej sieci nie może mieć - to oczywiste. Ale wszyscy klienci podsieci komunikują się ze światem zewnętrznym przez bramę (gateway), która ma konkretny IP widziany na zewnątrz. Dlatego nie jesteś wstanie, o ile nie przekierujesz portów, połączyć się przez gateway z konkretnym komputerem sieci wewnętrznej. Taki router działa na niższej warstwie, podajże warstwie sieciowej, dzięki czemu jest w stanie rozpoznać, do którego komputera sieci wewn. powinien trafić dany pakiet.

Ogólnie temat sieci jest złożony, a ja nie jestem specjalistą w tym temacie, więc po więcej szczegółów odsyłam do jakiejś literatury.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Aplikacja Server i Client

Nowy postprzez Bert1223 » środa, 24 lutego 2010, 22:57

Tak wygląda aplikacja CLIENT:
Kod: Zaznacz cały
//---------------------------------------------------------------------------
AnsiString TForm3::GetLocalIP(void)
{
AnsiString retVal;
WSAData wsaData;

if(!WSAStartup(MAKEWORD(1, 1),&wsaData))
{
  char BufHost[80];
  if(gethostname(BufHost, sizeof(BufHost)) != SOCKET_ERROR)

  {
   hostent *phe = gethostbyname(BufHost);
   if(phe)
   {
    in_addr addr;
    for(int i = 0; phe->h_addr_list[i] != 0; i++)
    {
     CopyMemory(&addr, phe->h_addr_list[i], sizeof(in_addr));
     if(i > 0) AppendStr(retVal, ".");
     AppendStr(retVal, inet_ntoa(addr));
    }
   }
  }
}
WSACleanup();

return retVal;
}
//---------------------------------------------------------------------------


void __fastcall TForm3::Button1Click(TObject *Sender)
{
   TCPClient->Host = IPSerwer->Text ;

   TCPClient->Connect();
   TCPClient->Socket->WriteLn("ConnectUser;" + Login->Text +";" + Pass->Text + ";" + GetLocalIP());
}
//---------------------------------------------------------------------------

Użyłem kodu do sprawdzania adresu IP ze strony Cyfrowego Barona.

Tak wygląda aplikacja SERWER
Kod: Zaznacz cały
void __fastcall TForm3::TCPServerConnect(TIdContext *AContext)
{
   MemoZdarzenia->Lines->Add("Podłączono clienta");
}
//---------------------------------------------------------------------------


void __fastcall TForm3::TCPServerDisconnect(TIdContext *AContext)
{
   MemoZdarzenia->Lines->Add("Rozłączono clienta");
}
//---------------------------------------------------------------------------

void __fastcall TForm3::TCPServerExecute(TIdContext *AContext)
{
   TCPServer->Active = true;

   String line = AContext->Connection->Socket->ReadLn();
   String ip, login, pass;

   int b = 0;
   b = line.LastDelimiter("ConnectUser");

   if(b != 0)
   {
      int a = 0;
      line.Delete(1,12); // Usuwanie polecenia z lini

      a = line.LastDelimiter(";"); // zwraca pozycje ostatniego ';'
      ip = line;
      ip.Delete(1, a); // otrzymujemy adres ip

      line.Delete(a, line.Length()); // usuwa ostatni ';' i adres ip

      a = line.LastDelimiter(";"); // zwraca pozycje ostatniego ';'
      pass = line;
      pass.Delete(1, a); // otrzymujemy haslo

      line.Delete(a, line.Length()); // usuwa ostatni ';' i haslo

      login = line;

      int i = 0;
      while(Uzytkownik[i].get_id())
      {
         if(login == Uzytkownik[i].get_login() && pass == Uzytkownik[i].get_pass())
         {
            // Jak zwrócić użytkownikowi dane o udanym logowaniu ??
            MemoZdarzenia->Lines->Add("Zalogowano: " + Uzytkownik[i].get_name() + ", adres ip: " + ip);
            break;
         }
         i++;
      }
   }
}
//---------------------------------------------------------------------------


Chciałbym zapytać o:
1. Czy zdarzenie TCPServerExecute dotyczny sytuacji gdy serwer otrzymuje jakieś dane?
2. Do czego służą inne zdarzenia (Exception, OnAfterBind i OnBeforeListenerRun)?
3. Czy dobrze umiejscowione jest polecenie 'TCPServer->Active = true;'?
4. Jak zakomunikować poprawne logowanie do serwera tylko konkretnemu clientowi?
5. W jakim zdarzeniu i jakimi poleceniami odebrać dane wysyłane przez serwer na aplikacji clienta?
Ostatnio edytowano środa, 24 lutego 2010, 23:03 przez Bert1223, łącznie edytowano 1 raz
Avatar użytkownika
Bert1223
Bladawiec
Bladawiec
 
Posty: 45
Dołączył(a): czwartek, 15 października 2009, 02:41
Podziękował : 6
Otrzymał podziękowań: 0
    Windows 7Chrome

Re: Aplikacja Server i Client

Nowy postprzez Bert1223 » środa, 24 lutego 2010, 23:02

Co do bramy i adresów IP, zgadza się pod jednym adresem zewnętrznym może być ukrytych wiele komputerów tak zwany (NAT) czyli translacja adresów IP, ale z tego co jest mi wiadome po kursach Cisco, za NAT urządzenie i tak wie komu dalej wysłać pakiet bo jest coś takiego jak (MAC) adres fizyczny który również znajduje się obok adres IP.
Wracając do tematu, zadbam o to aby każda aplikacja miała adres zewnętrzny.
Proszę o odpowiedź na pytania.
Avatar użytkownika
Bert1223
Bladawiec
Bladawiec
 
Posty: 45
Dołączył(a): czwartek, 15 października 2009, 02:41
Podziękował : 6
Otrzymał podziękowań: 0
    Windows 7Chrome

Re: Aplikacja Server i Client

Nowy postprzez polymorphism » czwartek, 25 lutego 2010, 11:39

1. Czy zdarzenie TCPServerExecute dotyczny sytuacji gdy serwer otrzymuje jakieś dane?

Z dokumentacji tak wynika.

4. Jak zakomunikować poprawne logowanie do serwera tylko konkretnemu clientowi

Wysyłając odpowiedni komunikat? Wprawdzie nie znam tych klas, ale coś w ten deseń:
Kod: Zaznacz cały
// w TCPServerExecute po akceptacji loginu i hasła
AContext->Connection->Socket->WriteLn("LOGGED IN");

Czyli po stronie klienta:
Kod: Zaznacz cały
TCPClient->Connect();
TCPClient->Socket->WriteLn("ConnectUser;" + Login->Text +";" + Pass->Text + ";" + GetLocalIP());

String line = TCPClient->Socket->ReadLn();
if(line != "LOGGED IN")
{
    /* FUCK! */
}


(...) ale z tego co jest mi wiadome po kursach Cisco, za NAT urządzenie i tak wie komu dalej wysłać pakiet bo jest coś takiego jak (MAC) adres fizyczny który również znajduje się obok adres IP.

Tak, ale jak pisałem, serwer na tym poziomie nie działa, to jest poziom sprzętowy.

Wracając do tematu, zadbam o to aby każda aplikacja miała adres zewnętrzny.

Zamiast kojarzyć klienta z IP, spróbuj skojarzyć go z AContext, wtedy zniknie sztuczny, niepraktyczny i niebezpieczny wymóg posiadania zewnętrznego IP.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Aplikacja Server i Client

Nowy postprzez Bert1223 » czwartek, 25 lutego 2010, 21:34

Całość działa dodam jeszcze kilka funkcje i wrzucę kod na forum, może ktoś coś tam podpatrzy dla siebie.
Mam jeszcze sporo pytań. Zacznę może jednak od przybliżenia założeń programu.
Dwie aplikacje Client i Server. Zadaniem Servera jest zarządzanie danymi oraz udostępnianie ich użytkownikom.
Użytkownicy korzystają z aplikacji Client.
System ma przechowywać dane dotyczące artykułów zakupionych w różnych hurtowniach, na chwilę obecną jest to około 300 sztuk.
Czyli nie wiele, ale produktów cały czas przybywa. Chcę użyć tablicy klas. Zastanawiam się nad najlepszym sposobem przesyłania tych danych?
Co będzie bardziej efektywne przesyłanie Stringów czy binarnie? Widziałem opcję WriteFile(...), czy brać pod uwagę takie rozwiązanie jak utworzenie pliku i przesłanie go do aplikacji?
Czytałem o wielowątkowości aplikacji, czy takie rozwiązanie powinno znaleźć się w tej aplikacji?
Avatar użytkownika
Bert1223
Bladawiec
Bladawiec
 
Posty: 45
Dołączył(a): czwartek, 15 października 2009, 02:41
Podziękował : 6
Otrzymał podziękowań: 0
    Windows 7Chrome

Re: Aplikacja Server i Client

Nowy postprzez polymorphism » czwartek, 25 lutego 2010, 23:08

Co będzie bardziej efektywne przesyłanie Stringów czy binarnie?

Binarny jest (prawie) zawsze efektywniejszy, tyle że poziom efektywności będzie zależał od danych, które będziesz przekazywał. Jak domyślam się, w tym przypadku będą to w większości dane tekstowe, więc niewiele zyskasz jeśli chodzi o łącza. Przy protokole tekstowym dochodzi sprawa parsowania tekstu. Choć z drugiej strony, kto powiedział, że czytanie danych binarnych jest prostsze?

Zbyt ogólne pytanie, by konkretnie na nie odpowiedzieć.

Czytałem o wielowątkowości aplikacji, czy takie rozwiązanie powinno znaleźć się w tej aplikacji?

Dziwne pytania zadajesz. Wątków nie dodaje się bo powinno, tylko jeśli jest to konieczne. W trakcie pisania aplikacji będziesz wiedział, kiedy będzie to konieczne.

TIdTCPServer tworzy (chyba) dla każdego połączenia oddzielny wątek.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Aplikacja Server i Client

Nowy postprzez Cyfrowy Baron » piątek, 26 lutego 2010, 10:45

Co do wątków. Jeżeli będziesz wysyłał dane w głównym wątku aplikacji, czyli bez dodatkowych wątków ( :? ) to aplikacja będzie zablokowana do czasu zakończenia transferu. Jeżeli jednak będziesz je wysyłał w odrębnym wątku to aplikacja nie będzie zablokowana i możliwe stanie się wykonywanie innych operacji.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Aplikacja Server i Client

Nowy postprzez Bert1223 » niedziela, 28 lutego 2010, 23:04

Do tej porty to klient komunikował się z serwerm czy to przy logowaniu czy przy pobraniu danych.
Ale zakładając, że jeden z klientów dodaje pozycję, wysyła to do serwera, a następnie to serwer ma wysłać dane do wszystkich podłączonych clientów.
Jak w aplikacji clienta zrobić nasłuchiwanie jakiego zdarzenia użyć?
Avatar użytkownika
Bert1223
Bladawiec
Bladawiec
 
Posty: 45
Dołączył(a): czwartek, 15 października 2009, 02:41
Podziękował : 6
Otrzymał podziękowań: 0
    Windows 7Chrome

Re: Aplikacja Server i Client

Nowy postprzez Cyfrowy Baron » poniedziałek, 1 marca 2010, 09:26

Możesz wykorzystać zdarzenie OnIdle aplikacji, czyli wykorzystujące proces bezczynności systemu. To zdarzenie to taki zegar, ale działa tylko gdy procesor nie jest zajęty w 100%. Zaletą tego zegara jest to, że nie obciąża dodatkowo procesora, ale jeżeli procesor będzie zajęty w 100% to zdarzenie się zatrzyma. Proces bezczynności systemu możesz podejrzeć w Menadżerze zadań na zakładce Procesy.

plik nagłówkowy:
Kod: Zaznacz cały
private:
    void __fastcall ApplicationIdle(TObject *Sender, bool &Done);


plik źródłowy:
Kod: Zaznacz cały
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
Application->OnIdle = ApplicationIdle;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ApplicationIdle(TObject *Sender, bool &Done)
{
// zadania;
}




Możesz też wykorzystać zdarzenie OnTimer obiektu typu TTimer.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Aplikacja Server i Client

Nowy postprzez Witold » poniedziałek, 1 marca 2010, 12:43

Cyfrowy Baron napisał(a):Możesz wykorzystać zdarzenie OnIdle aplikacji, czyli wykorzystujące proces bezczynności systemu.


help napisał(a):TApplication::OnIdle

Occurs when an application becomes idle. /.../ Write an OnIdle event handler to perform special processing when an application is idle. An application is idle when it is not processing code. For example, an application is idle when it is waiting for input from the user.
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    AmigaAWeb

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Aplikacje sieciowe

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 10 gości

cron