Wielowątkowi klienci, połączenie z serwerem. Wysyłanie i odbieranie danych (Sockets)

0

Ostatnimi czasy głowię się nad połączeniem między klientami a serwerem. Problem polega w logice, której nie mogę rozpracować, albo po stronie kodu, którego nie mogę naprawić. Na chwilę obecną działam na localhoscie z dwoma klientami.

Gdy kllient się łączy do serwera, serwer tworzy nową klasę podając ID użytkownika, jego pozycję (x,y) oraz przesyła mu połączenie w postaci clientSocket.

User[] user = new User[2];
// Polaczenie...
user[kolejny] = new User(ID, 0, 0, clientSocket);

Problem polega teraz na wysyłaniu i odbieraniu danych. Dane te po prostu wariują - gracze, albo nie mogą ruszyć się z miejsca, albo niespodziewanie "lagują się", czyli po prostu ruch gracza wyświetla się u innego po np. 10 sekundach, lub dziwnie skaczą (ruch np. o 20 kratek, a potem powrót do miejsca startu, czyli (0,0)), a nawet była sytuacja, że gracz pierwszy działał poprawnie, ale drugi wariował. Zdarzyło się nawet tak, że działała tylko jedna oś np. X, nie było "lagów", nic z tych rzeczy, ale oś Y zachowywała się dość szokująco.

Każda gracz ma osobny wątek Receiver oraz Sender, a także tablice graczy, odpowiadającyca za ich wyswietlanie na ekranie:

User[] user = new User[2];

public class User{
    int ID, x, y;
}

public void sender(){
    while(senderThread.isAlive){
        data = "playerdata/"+x+"/"+y+"/";
        socket.Send(data);  // W bardzo uproszczonym przykładzie (w rzeczywistości używam try/catch, tablic byte[], kodowania)
    }
}

public void receiver(){
    while(receiverThread.isAlive){
        data = socket.Receive();  // Znow bardzo uproszczony przykład, żeby zobrazować odbieranie danych.
        string[] message = data.Split('/');
        if(message[0] == "playerdata"){
            id = int.Parse(message[1]);  // id odpowiada za doslowne: "O ktorego gracza chodzi"
            user[id].x = int.Parse(message[2]);
            user[id].y = int.Parse(message[3]);
        }
    }
}

Sender sluzy do wysylania swojej pozycji do serwera (probowalem tez z ruchem, czyli po nacisnieciu klawisza, wysyla sie informacja o przesunieciu, ale równiez dziwnie dzialalo), a Receiver sluzy do odbierania danych o poszczegolnych graczach.

Po stronie serwera jest to bardzo podobne. Gdy klient się połaczy, serwer wysyła informację "connection" do pozostałych klientów, tamci po odebraniu informacji tworzą nową klasę gracza. Serwer wysyła do każdego gracza informację o pozycjach pozostałych graczy i wygląda to mniej więcej tak:

for(int us = 0; us < 2; us++){
    if(user[us] != null){ // Sprawdza czy uzytkownik istnieje (jest polaczony) - Uzytkownik do ktorego ma byc wyslana informacja
        // Wysyla dane o wszystkich uzytkownikach
        for(int all = 0; all < 2; all++){
            if(user[all] != null){ // Sprawdza czy uzytkownik istnieje (jest polaczony) - Uzytkownik ktorego dane maja byc wyslane
                data = "playerdata/"+all+"/"+user[all].x+"/"+user[all].y+"/";
                user[us].socket.Send(data);
            }
        }
    }
}

Każda klasa gracza po stronie serwera zawiera również swoją metodę Receiver, która odbiera dane o nim samym (jak klient się ruszy wysyła informację do serwera o swojej pozycji, a serwer to zapisuje u siebie). Metoda ta jest bardzo podobna do metody Receiver z klasy gracza, dlatego nie będę tego kopiował.

Próbowałem wiele sposobów, ale za każdym razem coś szło nie tak. Nie wiem co na to poradzić, aby gracze normalnie się poruszali i widzieli się nawzajem.

0

Niestety aby pomóc musisz przesłać kod.

0

Już wyjaśnione :) Kilka dni ciężkiego rozmyślania i w sumie samo wyszło...
Trzeba zrezygnować z sendera i podczas otrzymywania danych w klasie User po stronie serwera, wysłać je równoczesnie do wszystkich procz siebie

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