Jak zrobić identyfikatory klientów w prostym chacie na socketach.

Jak zrobić identyfikatory klientów w prostym chacie na socketach.
IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

Witam. Robię prosty chat który w założeniu ma działać tak, że wysłana wiadomość wysyłana jest do serwera który wyśle ją do odpowiedniego klienta. Problem jest taki, że nie wiem jak nadać jakieś identyfikatory dla klientów. Chat programuje na socketach.

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 4 godziny
  • Lokalizacja:Laska, z Polski
  • Postów:10056
0

Kiedy klient się łączy do servera, albo zakłada konto możesz mu nadać identyfikator, jakąś liczbę porządkową.

Podejdź do tego z biznesowego punktu widzenia, skąd użytkownik będzie wiedział do jakiego innego użytkownika będzie wysyłał wiadomość? Po mailu? Nicku? Jakimś identyfikatorze liczbowym?

piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:dzień
  • Postów:3277
0

Jeżeli robisz serwer na socketach, to i tak musisz otwierać nowe gniazdko dla każdego klienta, więc wystarczy po stronie serwera powiązać obiekt socketa z klientem.

IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

A mógłbym prosić jakiś konkretny przykład?
Tak ze dwie linijki kodu. ;-)

???

edytowany 2x, ostatnio: Ktos
Kandif
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 4 lata
  • Postów:231
0

Ja bym zrobił osobną klasę np.Klient w której jest pole Socket (te klienckie) oraz identyfikator. I przyjmijmy że parametrem konstruktora jest Socket. A listę klientów trzymasz w tablicy dynamicznej (ArrayList) o nazwie np. klienci. Wewnątrz konstruktora możesz generować id.

Kopiuj
Socket client = server.accept();
klienci.add(client);

"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'
IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

A czy taki server...

Kopiuj
import java.io.*;
import java.net.*;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import static java.time.LocalDate.now;

public class Server
{

    public static void main(String[] args) throws IOException
    {
        String name = "Server";

        LocalTime minutes = LocalTime.now();
        minutes = minutes.truncatedTo(ChronoUnit.MINUTES);


        try {

            ServerSocket s = new ServerSocket(3001);
            System.out.println("Czekamy na połączenie...");
            Socket server = s.accept();


            DataOutputStream dos2 = new DataOutputStream(server.getOutputStream());
            dos2.writeUTF(String.valueOf(minutes) + " | " + name + "| " + "Klient został podłączony " + server.getInetAddress().getHostName());

            System.out.println(("Klient został podłączony " + server.getInetAddress().getHostName()));



        }
        catch (Exception e)
        {

        }
    }
}

..da radę obsłużyć wielu klientów na raz? Gdzie dokładnie te identyfikatory zrobić?

Burdzi0
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Futurama
  • Postów:887
0
Kopiuj
 catch (Exception e)
        {

        }

Będzie lanie...


Bite my shiny metal ass!
Life throws you an error code like that, you don't have the luxury of a ZnVja2luZw== pop-up explanation *Robię projekty studenckie, pisz priv ;) *
IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

A coś bardziej na temat? ;)

Burdzi0
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 miesięcy
  • Lokalizacja:Futurama
  • Postów:887
0

Jeżeli chcesz mieć wielu klientów to musisz się bawić w wielowątkowość.
Za to co podkreśliłem w poprzednim poście powinno być srogie lanie i 4 dni bez obiadu. Nie dość, że łapiesz Exception, czyli może wpaść tam wszystko to na dodatek wyciszasz to. Wyjątki należy obsługiwać.


Bite my shiny metal ass!
Life throws you an error code like that, you don't have the luxury of a ZnVja2luZw== pop-up explanation *Robię projekty studenckie, pisz priv ;) *
WeiXiao
main() { try { whole_application_logic; } catch (){} }
Burdzi0
@WeiXiao: I jeszcze komentarz: żodyn błond siem nie wyświetla, help!!!111one1one
WeiXiao
@Burdzi0: haha, pół biedy jak jeszcze wrzuci kod z tym try catchem :D
IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

To dopiero zaczątek aplikacji, poprawie to. Zabawa w wielowątkowość jest jest bardzo skomplikowana?, początkujący programista ogranie? 😊

IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

Jak zainstalować SQLite? Są jakieś programy po których instalacji SQLite się zainstaluje? Próbowałem z plikami z głównej strony SQLite z jakimś tutorialem ale nie znalazłem u siebie takiego pliku jak gość miał na filmie.

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:dzień
  • Postów:216
0
Kopiuj
public class ClientComponent extends Thread {
    final static Logger LOGGER = Logger.getLogger(ClientComponent.class);
    private final Socket clientSocket;
    private final Server server;
    private OutputStream outputStream;

    public ClientComponent(Server server, Socket socket) {
        this.server = server;
        this.clientSocket = socket;
        LOGGER.info("Created ClientComponent for new client\n");
    }

    @Override
    public void run() {
        try {
            handleNewClient();
        } catch (IOException e) {
            LOGGER.error("Error while handling new client\n" + e.toString());
        }
    }

    private void handleNewClient() throws IOException {
        InputStream inputStream = clientSocket.getInputStream();
        this.outputStream = clientSocket.getOutputStream();        

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line;

        while((line = bufferedReader.readLine()) != null) {           
            Message message = new Message(line);
            MessageController.getInstance().sendToAll(message);
        }
        clientSocket.close();
        server.getClientComponentSet().remove(this);
        LOGGER.info("Client disconnected, current connections count: " + server.getClientComponentSet().size() + "\n");        
    }    
}
Kopiuj
public class Server extends Thread {
    final static Logger LOGGER = Logger.getLogger(Server.class);
    private int port;
    private ServerSocket serverSocket;
    private volatile boolean shutdown;
    private Set<ClientComponent> clientComponentSet;    

    public Server(int port) {
        this.shutdown = false;
        this.port = port;
        this.clientComponentSet = new HashSet<>();
        LOGGER.info("Starting the server...\n");    
    }

    @Override
    public void run() {
        try {
            serverSocket = new ServerSocket(port);
            LOGGER.info("Server started\n");

            while(!serverSocket.isClosed() && !shutdown) {
                Socket clientSocket = serverSocket.accept();
                ClientComponent clientComponent = new ClientComponent(this, clientSocket);
                clientComponentSet.add(clientComponent);
                clientComponent.start();
            }
        } catch (IOException e) {
            if(!shutdown) {
                LOGGER.error("Failed to start the server\n" + e.toString() + "\n");
            }
        }
    }    
}
IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

A jak mam to uruchomić? Intelij pokazuje milion błędów w kodzie po zaimportowaniu klas które podpowiadał. Muszę poszukać w internecie zaimportować sam czy, co?

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:dzień
  • Postów:216
0

To kawałek mojego programu który kiedyś napisałem, nie 100% gotowiec. Pokazuje Ci milion błędów bo w tym kodzie nie ma importów. Poza tym kawałek z MessageController jest również do wywalenia, zapomniałem go wyrzucić a to inna część mojego programu, której tutaj nie wrzuciłem. Wzorując się jednak na moim sposobie możesz osiągnąć to co chciałeś.

IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

@Emdzej93:

Kopiuj
import java.io.*;
import java.net.Socket;
import java.util.logging.Logger;

Tyle importów podpowiedział IneliJ. ClientComponent i Server nadal świecą się na czerwono. To też kwestia importów? Jak tak to mógłbyś podesłać odpowiednie?

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:dzień
  • Postów:216
0

Przecież Server i ClientComponent to klasy które sam zrobiłem i Ci wysłałem. Logger możesz całkowicie pominąć i zamienić na Println(), ponieważ nie zaciągnie Ci go automatycznie IntelliJ (musiałbyś dorzucić dependency do tego Loggera którego ja użyłem). Generalnie ten kod to nie jest opcja kopiuj wklej. Przeczytaj go, postaraj się zrozumieć co się tam dzieje i samemu zaimplementuj od 0. W skrócie na lekko uproszczonym przykładzie:

  • masz klasę Server która w sobie ma Set czy Listę czy jakąkolwiek kolekcję Clientów, dodatkowo klasa Server dziedziczy po Thread i nadpisuje metodę run() w której:

@Override
public void run() {
try {
serverSocket = new ServerSocket(port); // stworzenie instancji ServerSocket'u na danym porcie

        while(!serverSocket.isClosed()) {
            Socket clientSocket = serverSocket.accept(); //akceptuje przychodzące połączenie
            ClientComponent clientComponent = new ClientComponent(this, clientSocket); //tworzy nową instancję klasy reprezentującej klienta 
            clientComponentSet.add(clientComponent); // dodaje utworzoną instancję klienta do zbioru klientów
            clientComponent.start();
        }
    } catch (IOException e) {
       
    }

Teraz spójrz na klasę ClientComponent, każda z jej instancji jest po prostu nowym klientem połączonym z Serverem, każda z nich ma dostęp do Output/InputStream'u Servera i może pobierać i wysyłać dane. Teraz chciałeś jakoś zidentyfikować każdego połączonego klienta - wystarczy że dorzucisz sobie jakieś ID w postaci

String username;

IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

Ale co mam zrobić z takim ID?

Kopiuj
String "1637623";

Jak pokazać serwerowi, że to jest ten klient? Chodzi mi o mniej więcej coś takiego:

Kopiuj
class Client
{
    String ID = "Jacek";
    //wysyłanie wiadomości X o treści "cześć" do klienta o ID "Andrzej"
}
Kopiuj
class Server
{
   //przyjście wiadomości X na serwer
   //wysłanie wiadomości X do klienta o ID "Andrzej"

}
Kopiuj
class Client
{
   String ID = "Andrzej";
   //przyjście wiadomości X z serwera
   System.out.println(X.FromServer(od: Jacek);
}
Kandif
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 4 lata
  • Postów:231
0

Nie wiem jak masz zrobioną listę Clientów u Serwera, ale ja widzę dwa sposoby. Podczas wysyłania wiadomości kodujesz ją o parametry "autorID" i "adresatID". Potem albo Serwer przeszukuje pętlą z listy klientów i porównuje id, jeśli jest poprawne to wysyła do danego, bądź wysyłasz tą odpowiedź do każdego z klientów i to po ich stronie przechodzi filtracja czy wiadomość jest do nich, jeśli tak to ją wyświetlasz. Pamiętaj że socketami można wysyłać cały obiekt, więc warto stworzyć prostą klasę wiadomość której polami będą właśnie idAdresata, idNadawcy oraz treść wiadomości.


"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'"-._,-'"-.,-'
IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

Zrobiłem ArrayList i mam metodę:

Kopiuj
 lista.add (parametr)

Co mam wstawić jako parametr aby wyszło coś typu:

Kopiuj
clientName = "Jacek", ID = 61727, (gniazdo lub coś do komunikowania się)

Czy lepiej do clientName, ID i gniazda zrobić osobne listy?

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:dzień
  • Postów:216
0

Jedna lista w zupełności wystarczy. Zawierać ona powinna obiekty klasy reprezentującej klienta (w moim przypadku był to ten ClientComponent). Wewnątrz tej klasy możesz stworzyć pola jak ID, username, sockety, itp, itd.

IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

Ale jak to ma wyglądać? Z socketami trzeba nowy port utworzyć? ID to tylko ID = 123? Chodzi mi o takie podstawy podstaw.

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:dzień
  • Postów:216
0

Klasa reprezentująca Client'a

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client extends Thread{
private int id;
private Socket socket;
private OutputStream outputStream;
private InputStream inputStream;

public Client(int id, Socket socket){
    this.id = id;
    this.socket = socket;
}

@Override
public void run(){
    try {
        outputStream = socket.getOutputStream();
        inputStream = socket.getInputStream();
        String greetingMessage = "Hello I'm new client with id: " + id;
        outputStream.write(greetingMessage.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

Oraz klasa reprezentująca Server wraz z komentarzem

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server extends Thread {
private ServerSocket serverSocket;
private List<Client> clientList;

public Server(int port) throws IOException {
    serverSocket = new ServerSocket(port); //tworzysz ServerSocket na wskazanym porcie
    clientList = new ArrayList<>(); //a tutaj liste w ktorej bedziesz trzymac klientow
}
@Override
public void run() {
    while(true) {
        try {
            Socket clientSocket = serverSocket.accept(); //akcpetujesz przychodzące połączenie i przypisujesz je do nowego Socketu
            int id = clientList.size(); //generujesz jakieś id
            Client newClient = new Client(id, clientSocket); //tworzysz nowego clienta i nadajesz mu wygenerowane ID oraz Socket ktorzy wczesniej utworzyles
            clientList.add(newClient); //dodajesz obiekt tego clienta do listy
            newClient.start(); //startujesz metodę run() co spowoduje wyslanie powitalnej wiadomosci
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

}

A nawet klasa Main

import java.io.IOException;

public class Main {
public static void main(String args[]) throws IOException {
Server server = new Server(9999);
server.start();
}
}

https://imgur.com/a/gNlU4

Przeanalizuj to co się tam dzieje i radziłbym douczyć się podstaw najpierw bo nie bardzo wiem nawet jak odpowiedzieć na Twoje pytania...

edit#
ja za to nie potrafię skleić kodu tak by się nie rozjeżdżał, sry, próbowałem

edytowany 9x, ostatnio: Emdzej93
IJ
  • Rejestracja:około 7 lat
  • Ostatnio:prawie 6 lat
  • Postów:139
0

Wszystko fajnie ale dlaczego w 25 linii Client, (newClient) i .start świecą się na czerwono?

E9
  • Rejestracja:ponad 8 lat
  • Ostatnio:dzień
  • Postów:216
1

Naprawdę nie mam już siły próbować. Nic się nie świeci na czerwono. Jak chcesz być pewien że wszystko działa - napisz to od 0, wzorując się na tym co wysłałem. Dostałeś praktycznie 100% gotowca, jeżeli nie potrafisz go przekopiować to naprawdę nie potrafię pomóc.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)