przeszukiwanie LAN'a za serverem

0

Witam wszystkich :) (1st post),

otoz, mam niebanalny (chyba) problem. Chodzi o to, ze mam klienta i serwera opartego na protokole TCP. Chcialbym, aby w programie klienta wykonywala sie nastepujaca operacja:klient zaczyna szukac w calej sieci (LAN) serwera, jezeli go nie znajdzie, sam staje sie serwerem :) Chodzi przede wszystkim o wlasnie to przeszukiwanie calej sieci. Jest wazne SZYBKIE jakby s'ping'owanie wszystkich komputerow i odbior odp. gdzie jest tak naprawde na danym porcie serwer (ktory komputer).
Prawie do tego doszedlem, ograniczylem czas wyszukiwania, ale wyglada to w ten sposob ze uzyskuje komunikaty lookup i connecting, a jak juz dojdzie do IP na ktorym serwer jest faktycznie postawioony, to go po prostu omija... chyba, ze jest mniejszy zakres adresow IP do przeszukania.
(dajmy na to mam serwer na 192.168.0.80 i jak zaczne z .79 to tylko wtedy wchodzi poprawnie, gdy jednak zaczynam od .1 to kompletna kasza -> nic nie znajduje, "omija" ten .80).
Czy potrafi mi ktos pomoc? Jak w ciagu paru sekund przejrzec siec za serwerem na TCP? (nonblocking)

PS. Uzywam komponentow Internet->ClientSocket/ServerSocket

z gory dziekuje za kazde odpowiedzi

0

heh, nikt nie wie czy nikt nie zrozumial? :<
chodzi mi tylko o znalezienie servera w sieci LAN :D na danym porcie i protokole TCP... helpnie ktos?
PS. C++ Builder uzywam... (jak widac pisze w C++ :D)

0

ja wiem :)
X to liczba kompów w sieci

stwórz X struktu typu

TYPE _SZUKACZ
 UINT Socket
 UINT Msg   // wystarczy WORD, ale windows i tak zużywa 8 bajtów
 sockaddr_in sk
ENDTYPE

_SZUKACZ SZUKACZ[X] <--- X struktur _szukacz

zrób pętlę z (n=0; n<X; n++)
wypełnij standardowo SZUKACZ[n].sk za każdym razem z inym IP
zażądaj socketa dla każdego SZUKACZ[n].Socket
zrób jakiś string inny dla każdego n i wsadź go do funkcji msg=RegisterWindowMessageA(string)
teraz (potrzebne okno!) robisz

WSAAsyncSelect(SZUKACZ[n].Socket, okno.hwnd, msg, FD_CLOSE | FD_CONNECT)
SZUKACZ[n].msg = msg
connect(SZUKACZ[n].Socket, SZUKACZ[n].sk, len(SZUKACZ[n].sk)
//zamykasz pętlę n

uruchamiasz jakiś timer dla owego okna np. 1000ms i zbierasz wiadomości od socketów w zakresie {0xC000 - 0xFFFF}
jeśli dostaniesz message {0xC000 - 0xFFFF} i jednocześnie lParam = FD_CONNECT to zatrzymujesz timer bo już masz jakiegoś serwera. Który to?
znowu pętla

for (n=0; n<X; n++)  if (SZUKACZ[n].msg == Message_z_Okna) then socket do tego serwera jest w SZUKACZ[n].Socket
a ip serwera zwróci funkcja getpeername(SZUKACZ[n].Socket, sk, sizeof(sk))
//sk to dodatkowa struktura sockaddr_in

i już jesteś połączony. Ale jeśli złapiesz wiadomość od timera to też go musisz zatrzymać i sam stać się serwerem

0

przepraszam za taka POZNOSC... dopiero dzis przeczytalem Twojego posta... chyba w sumie zrozumialem, tylko szczerze nie umiem odebrac tej wiadomosci z okna, ze jest polaczenie (FD_CONNECT?)

no wiec mam Button:

Timer1->Enabled = true;
 for (ip = 1; ip < 256; ip ++)
 {
  SZUKACZ[ip].sk.sin_family = AF_INET;
  SZUKACZ[ip].sk.sin_addr.S_un.S_addr = inet_addr( ("192.168.0." + IntToStr(ip)).c_str() );
  SZUKACZ[ip].sk.sin_port = 8888;
  msg = RegisterWindowMessageA( ("msg" + IntToStr(ip)).c_str() );
  SZUKACZ[ip].msg = msg;
  connect(SZUKACZ[ip].Socket, (const sockaddr*)&SZUKACZ[ip].sk, sizeof(SZUKACZ[ip].sk));
 }

i Timer:

niby cus wpisane, ale to nic nie pomoze :P

wlasnie, nie umiem napisac Timera... tzn. nie umiem odebrac tego Msg'a, ze jest polaczenie od serwera... a szuka raczej prawidlowo. i nie wiem do czego mam to msg = ...

next help? :)
(PS. googlowalem i searchowalem, ale nie moge tego poskladac =/)

0

RegisterWindowMessage rejestruje prywatne messages (podobnie działa do RegisterClassEx) - takie których nie ma w innych oknach, a zarazem nasza aplikacja może sobie posyłać do jakiegoś okna.

256 socketów naraz? hehe może być jeśli system wydoli... na xp można na spokojnie

to 'msg=' jest potrzebne osobno dla każdego socketu aby każdy socket wysyłał do okna inną wiadomość (potrzebne aż tyle tego jeśli chcesz szybko wyodrębnić jeden socket z X), choć można użyć tylko jednego message = WM_USER dla wszystkich socketów, ale dochodzi nowa pętla dla wszystkich socketów z

if (send(SZUKACZ[ip].Socket, adres_jakiegoś_bufora, 0, 0)==0) //then ten socket jest połączony (nie połączone kopiesz od razu)

'messagi' od socketów odbierasz tak samo jak WM_USER, WM_*** czyli bezpośrednio w Msg okna

Chyba wydzę byka z tym portem !!! jeśli 8888 to port na którym się łączysz to zmień to na htons(8888)

SetTimer(hwnd, id<nonzero>, intervall<ms>, opt FunctionAdress=NULL)
KillTimer(hwnd, id)

i okno dostaje message WM_TIMER z wParam=timerID

wyczytałem że hwnd może być NULL, więc chyba okna nie potrzeba wcale :]

dziwi mnie SZUKACZ[ip].sk.sin_addr.S_un.S_addr
sk jest zdefiniowane jako sockaddr_in, a sockaddr_in to

WORD sin_family
WORD sin_port
DWORD sin_addr
BYTE sin_zero[8]

oraz: inet_addr( ("192.168.0." + IntToStr(ip)).c_str() );
jestem za: inet_addr( ("192.168.0." + IntToStr(ip) ) );


gdzie tu jest pstryczek do @powiadomień :/

0

eh, juz nie moge... kombinuje na kazdy sposob ktory mi przychodzi do glowy...
poddaje sie :( czy mozesz mi napisac mniej wiecej gotowy kod?
chodzi tylko o to (na pewno to wiesz), ze chce wyslac zapytania do wszystkich kompow i czekac az OBOJETNIE KTORY mi cos zwroci... nie daje sobie rady z tym =/ widocznie dlatego, ze kod podstawowego pliku mam standardowy z Buildera:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM("lan_unit1.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
        try
        {
                 Application->Initialize();
                 Application->CreateForm(__classid(TForm1), &Form1);
                 Application->Run();
        }
        catch (Exception &exception)
        {
                 Application->ShowException(&exception);
        }
        catch (...)
        {
                 try
                 {
                         throw Exception("");
                 }
                 catch (Exception &exception)
                 {
                         Application->ShowException(&exception);
                 }
        }
        return 0;
}
//---------------------------------------------------------------------------

czy moglbys mi napisac all? :<

0

czemu nie, już gotowe, tyle że w ibasic pro (ulepszony C;) )

nie zamieszczam tego tu bo to troszkę długie i nie wygodne do czytania jak jest połamane

click

aktualnie 'finder' szuka włączonych GG w powyższym zakresie IP; na standardowym porcie plików 1550

0

dzieki, pobawie sie w konwersje na C++.
Lecz jest jeden bug "maly" w Twoim skompilowanym programie. Jak przeszukasz siec raz, to za drugim razem nic nie znajdzie. W moim WinXP trzeba wylaczac polaczenie z netem i wlaczyc jeszcze raz, aby znow znajdywalo server.

0

ano nie działa, pomimo zamknięcia socketu (bez sprawdzenia skuteczności) - w tabeli połączeń widzę że socket jest w stanie SYN_SENT i pÓÓÓÓki tego ręcznie nie zamknę (albo poczekam minutkę) to się dopiero zamyka.

connect() zwraca tylko jeden błąd: WSAEWOULDBLOCK - czyli nic ciekawego,
Pewnie znasz AngryIPscanner? on też ma taki problem, ale rozwiązali go czekając na całkowite zamknięcie socketów

Co ciekawsze: nawet WSACleanup() nie działa; tak jakby sockety się rozdwoiły :/

btw. nowsza wersja jest na serwerze

za drugim razem nic nie znajdzie

bo jeśli znajdzie serwer to się nie rozłącza :)

0

to moze bedzie lepsze UDP? zreszta, gdzies chyba slyszalem/czytalem, ze taki Windows wysyla cos do 255.255.255.255 i ma np. liste kompow z sieci wlaczonych =asd (o ile mu zwroca pakiety). Ale to w sumie bez sensu, bo mi zalezy na szybkosci wyszukiwania... cos typu pol sekundy, do paru... (Twoj program nawet dobrze to robi). Faktycznie zauwazylem, o czym nie napisalem, iz jak sie odczeka chwile to wtedy znow odnajduje... dziwne, czyzby to nie umialo sie czyscic od razu? :\

1 użytkowników online, w tym zalogowanych: 0, gości: 1