Adam Cich

Adam Cich Student,
Politechnika
Warszawska

Temat: Komunikator sieciowy, połączenia między użytkownikami

Witam,

Mój komunikator obecnie funkcjonuje jako chat- wiadomościami wymieniają się wszyscy podłączeni do serwera użytkownicy.

Całość oparta jest na socketach. Serwer tworzy wątek dla każdego nowo podłączonego klienta, a ten z kolei odpowiada za odbieranie oraz wysyłanie wiadomości. Wątki umieszczane są w tablicy.

Klient wyposażony jest w dwa wątki- odbieranie/wysyłanie wiadomości

Docelowo komunikator ma umożliwić rozmowę z wybranym użytkownikiem, a nie ze wszystkimi. I tutaj mam problem z koncepcją.
Domyślam się, że klient musi być wyposażony w metodę w której wpisuje minimum adresata i treść wiadomości.
Serwer musi gromadzić informacje na temat podłączonych użytkowników- nadawać im jakiś numer identyfikacyjny, zapamiętać ich socket, następnie wysłać wiadomość do odpowiedniego odbiorcy...

Prosiłbym o jakieś wskazówki jak rozwiązać problem komunikacji między użytkownikami :)

Pozdrawiam,
Adam

konto usunięte

Temat: Komunikator sieciowy, połączenia między użytkownikami

Adam Cich:
Prosiłbym o jakieś wskazówki jak rozwiązać problem komunikacji między użytkownikami :)

Dość standardowy problem. Ech, te uczelniane projekty...

Bezpośrednia komunikacja:
1) Klient przy połączeniu musi się rejestrować z nickiem
2) To, co uruchamiane jest w wątkach per klient nie może być anonimową klasą
3) Gdy oba powyższe będą spełnione, serwer będzie mógł w Map<String, Klient> przechowywać referencje do obiektów potrzebnych do realizacji rozmowy bezpośredniej
4) Po otrzymaniu wiadomości do konkretnego usera klient pobiera z mapy klienta docelowego i wywołuje na nim metody wysyłającej do niego tekst.

Inne uwagi:
1) Przy punkcie 4 musisz pamiętać, że są to wywołania asynchroniczne. Nie możesz (==naprawdę nie powinieneś) wysyłać czegokolwiek z wątku innego klienta. Powinieneś dodawać obiekt klasy WiadomośćDoWysłania do jakiejś synchronizowanej kolejki, z której druga instancja serwera będzie pobierała wiadomości do wysłania.
2) Umieszczenie wątków w tablicy zdaje się być dziwne. Niepotrzebnie limitujesz ich ilość. Ogólnie, jeśli nie jesteś pewien, że chcesz tablicę, używaj ArrayList. A w tym konkretnym przypadku, jak pisałem, sugeruję mapę.
3) Dostęp do wszystkich klientów masz poprzez map.values()

Powodzenia!

konto usunięte

Temat: Komunikator sieciowy, połączenia między użytkownikami

Może jestem w błędzie, ale jeśli wykorzystujesz TCP/IP to nie prościej gromadzić IP (w np. ArrayList)użytkowników po podłączeniu do serwera i wtedy przy połączeniu między 2 osobami każdej z nich przekazać IP i port (pewnie standardowy dla wszystkich) drugiej strony? Wtedy połączenie między osobami będzie bezpośrednie i serwer zostanie praktycznie całkowicie odciążony, pozwoli to na przesyłanie większych paczek danych, a na serwerze będzie tylko czat i obsługa nowo podłączonych userów. No chyba że musi to przechodzić przez serwer, wtedy tylko metoda podana wyżej.
Szymon Biliński

Szymon Biliński Programista Java

Temat: Komunikator sieciowy, połączenia między użytkownikami

Adam Cich:
Całość oparta jest na socketach. Serwer tworzy wątek dla każdego nowo podłączonego klienta, a ten z kolei odpowiada za odbieranie oraz wysyłanie wiadomości. Wątki umieszczane są w tablicy.

Lepszym podejściem byłoby wykorzystanie wzorca do współdzielenia wątków na serwerze (reactor pattern). Są nawet do tego gotowe biblioteki (np. xSocket).
Tomasz Baranowicz:
Może jestem w błędzie, ale jeśli wykorzystujesz TCP/IP to nie prościej gromadzić IP (w np. ArrayList)użytkowników po podłączeniu do serwera i wtedy przy połączeniu między 2 osobami każdej z nich przekazać IP i port (pewnie standardowy dla wszystkich) drugiej strony?

Sprawa dosyć mocno się komplikuje jeżeli uwzględnisz obecność NAT/firewall'a. Zobacz jak to wygląda w przypadku protokołu Skype.

Jeżeli chodzi o podejście z centralnym serwerem:
1. Musisz gdzieś pamiętać wszystkie otwarte sesje. Można to zrobić tak jak napisał Dariusz - w współdzielonej instancji Map (np. wzorzec Singleton/zmienna statyczna). Pamiętaj tylko o synchronizacji wątków, które będą z tego korzystały.
2. Uważałbym przy rozpoznawaniu klienta na podstawie samej ksywki (przypuszczam, że taki był zamysł Map<String,Klient>?). Jeżeli chcesz żeby rozwiązanie było w miarę bezpieczne, to powinieneś też uwzględnić jakiś element losowy (id sesji - np. skrót z IP, ksywy i jakiejś wartości losowej). W przeciwnym wypadku łatwo będzie się podszyć pod innego użytkownika.



Wyślij zaproszenie do