Aplikacja sieciowa serwer - wielu klientów, JAVA

0

Witam,

Tworzę aplikację, umożliwiającą komunikację pomiędzy jednym serwerem, a wieloma klientami.

Założenia:

  1. Wszyscy klienci widzą to samo, jeżeli jeden z nich zmieni wartość zmiennej x, to pozostali również widzą to w czasie rzeczywistym (za pośrednictwem serwera).

  2. Serwer komunikuje się ze wszystkimi klientami jednocześnie, odbierając i wysyłając wartości jakichś zmiennych (typu boolean, int, itp).

  3. Grupa klientów, którzy mają prawo połączyć się z serwerem ma być ograniczona, w sensie: nie każdy kto chce może się połączyć, tylko np. z góry ustaleni użytkownicy, lub konkretne urządzenia, np o znanym wcześniej adresie MAC (to byłoby najbezpieczniejsze dla mnie rozwiązanie).

Z czym mam problem:

  1. Zastanawiam się za pomocą czego najlepiej przesyłać zmienne, myślałem nad stream sockets, bo protokół TCP zapewnia kontrolę kolejności, w jakiej wysłałem komunikaty. I zrobić to jako aplikację wielowątkową (choć nigdy takiej nie robiłem) - to dobry pomysł?

Zastanawiałem się też nad wykorzystaniem Multicast (byłoby wygodnie), tyle że nie wiem, czy jest bezpieczna - mógłby się ktoś wypowiedzieć na ten temat? Czy Multicast pozwala mi wybrać, do których użytkowników chce wysłać dane (w sensie, żeby tych niepożądanych ominąć)? I czy w ogóle to działa ze stream sockets? Bo wydaje mi się, że to jest zabawa z data gram socket, czy nie tak?

Czytałem też coś o możliwości zastosowania XMPP, ale nie mam zielonego pojęcia jak to ugryźć i czy w ogóle jest sens się w to bawić - w końcu to nie ma być komunikator :/

  1. Nie wiem w jaki sposób zrealizować przesyłanie danych. To będą przede wszystkim wartości boolowskie, oraz liczbowe. Kiedyś zrobiłem grę w statki, w której wysyłałem zmienne w postaci komunikatów tekstowych (oparłem się na zwykłym komunikatorze internetowym, to było w C++) i serwer odbierając te dane używał specjalnego parsera - ta metoda nie jest ani szybka, ani zgrabna. Jak to powinno wyglądać, tak profesjonalnie?

  2. Znalazłem sposób na odczytanie własnego MAC adresu:

try{
            InetAddress numerIp;
            numerIp = InetAddress.getLocalHost();
            NetworkInterface network = NetworkInterface.getByInetAddress(numerIp);
	 
            byte[] macAdres = network.getHardwareAddress();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < macAdres.length; i++) {
                sb.append(String.format("%02X%s", macAdres[i], (i < macAdres.length - 1) ? "-" : ""));		
            }
            return sb.toString();
        }
         catch (UnknownHostException e) {
             return "UnknownHostException: "+e;
         }
        catch(SocketException e){
            return "SocketException: "+e;
        }

Teraz jak odczytać MAC adres klienta, a nie swój? Chciałbym po prostu go sprawdzić, czy to urządzenie faktycznie jest na mojej liście zaufanych użytkowników, jeżeli nie, to nie prześlę mu danych. Czytałem, że najpierw trzeba go spingować, ale nie wiem jak to zrealizować w Javie :/

Jestem początkujący,
z góry dziękuję za pomoc :)

1

To co piszesz przypomina zwykły czat - poszukaj jak się takie coś pisze

  1. Wielowątkowy serwer z wieloma połączeniami TCP będzie działał. Multicast to tylko UDP i wymaga specjalnej konfiguracji urządzeń sieciowych (a więc zadziała tylko w pewnej lokalnej, skonfigurowanej sieci)
  2. Jeśli klienty i serwery pisane są w tym samym języku to możesz po prostu serializować obiekty i je przesyłać.
  3. Aplikacja kliencka może MAC odczytać i wysłać przecież. Przy czym tak samo jak z odczytywaniem IP to nie takie proste - zauważ że możesz mieć wiele kart sieciowych (w tym wirtualnych, loopbacki itd).
1

Z tego co wiem komunikacja przez sockety daje radę natomiast jest to programowanie na niskim poziomie.Oczywiście nie chodzi o poziom programisty ;) a o używane sposoby. Tak więc to o czym mówisz powinno składać się z dwóch części.Po pierwsze aplikacji serwerowej ,po drugie klienckiej. Na dobry początek zajmij się tą serwerową ,a za klienta póki co może posłużyć Ci telnet. Łączysz się poprzez:
telnet localhost 5000
Jeżeli aplikację masz wgraną na inny serwer zamiast "localhost" podajesz adres ip serwera.
5000 to numer portu na którym nasłuchuje aplikacja.Ustawiasz ją ręcznie w swojej aplikacji.
Z pewnością warto zajrzeć na tą stronę : http://pirate.shu.edu/~wachsmut/Teaching/CSAS2214/Virtual/Lectures/chat-client-server.html
Masz tu opisane wszystko krok po kroku.Jak mniej więcej zrozumiesz cały sens takiego połączenia będziesz mógł napisać sam własną aplikację lub przerobić tą do własnych potrzeb.

0

Dziękuję tazit, bardzo interesujący przykład, wygląda ładnie :) Od rana dzisiaj siedzę i usiłuję go uruchomić, tak żeby nawiązać jakąś komunikację - bez powodzenia :/ Nie mam pojęcia gdzie tutaj ustawić adres IP, a gdzie numer portu, tak żeby zaskoczyło, wersja okienkowa wywala mi błędy i wcale się nie łączy, ale mniejsza o nią. Oczywiście przepisując kod zauważyłem te informacje typu /bez zmian/ itp.

Z tego co zrozumiałem, to tam trzeba wywołać metodę, podając numer portu i adres IP. I rozumiem, że to tylko fragment aplikacji. Jedno czego nie potrafię zrozumieć w podanym przykładzie, to dlaczego metoda wewnątrz klasy jest z dużej litery? Przykładowo jest:
public class ChatClient
A zaraz po tym:
public ChatClient(String serverName, int serverPort)
Nie rozumiem, pewnie nie istotne ;)

Przez weekend na spokojnie sobie o tym poczytam, tam więcej przykładów jest, zacznę od jakiegoś mniej złożonego i krok po kroczku go sobie rozbuduję... Także dziękuję i do poniedziałku ;)

1

Zacznij od pierwszego przykładu servera. Tylko punkt pierwszy to wystarczy na początek
Pierwsze czyli public class ChatServer to nazwa klasy. public ChatServer(int port) to konstruktor. W nawiasie pisze int port tak więc to jest konstruktor który przyjmuje jeden argument typu int i jest to numer portu na którym server nasłuchuje.To jest bardzo istotne.
W funkcji main znajdziesz tworzenie obiektu klasy ChatServer z wywołaniem ** args[0] ** czyli pobierze ono przy tworzeniu pierwszy parametr wywołania.Jeżeli nie wiesz jak uruchomić aplikację z parametrami zamiast args[0] wpisz zwyczajnie numer portu.Przykładowo 5000.

0

A widzisz. Nie wiedziałem co to jest konstruktor :) Że w ogóle jest coś takiego. Teraz wszystko stało się jasne, kod faktycznie zaczął działać, wystarczyło użyć konstruktora i wywołać metodę run(). Zrobiłem to w innej klasie. Faktycznie śmiga :)

Teraz usiłuję ogarnąć temat tak, żeby z tego zrobić aplikację w 100% okienkową. Później pobawię się w serializowanie obiektów. Dziękuję uprzejmie kolegom za pomoc!
P.S.

Jak teraz chcę połączyć się z tym serwerem z innego komputera (W domu mam tylko jeden), to skąd znam jego nazwę - wystarczy tylko adres IP? W sieci lokalnej pewnie tak, a poza siecią lokalną, czy też wystarczy podać IP docelowego komputera, żeby połączyć się z serwerem?

0

IP oraz port wystarcz do identyfikacji aplikacji. IP identyfikuje komputer a port identyfikuje aplikacje.
BTW powaznie chcesz cos takiego pisac nie majac zielonego pojecia o javie? o_O
A z tym serwerem to zgaduje ze powinienes wywolac metode start() jesli to jest klasa dziedziczaca po Thread albo zrobic new Thread(obiekt).start() jesli to Runnable, a nie wywolywac run()

0

Poważnie, chcę coś takiego napisać. Z czego to jest tylko jeden z elementów tego programu. Nie bardzo mam wybór (potrzebny mi ten program), a po drugie kiedyś trzeba się nauczyć :D Nauczę się, będę siedział aż ogarnę.

Edit: faktycznie start() jest znacznie lepsze w użyciu niż run(), w dodatku nie wiesza mi całego programu, gdy używam okienek ;) Dzięki.

0

Dziękuję wszystkim, problem rozwiązany, serwer - klient działa na okienkach. W końcu to ogarnąłem :D
Teraz bawię się w serializację tego.

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