Pakiety docierające w złej kolejności powodują nieoczekiwane zachowanie.

0

Piszę program sieciowy który ma symulować ruch obiektów fizycznych (sandbox w którym można ustawiać obiekty a potem uruchomić symulację i śledzić trajektorie ich ruchu oraz siły jakie na nie działają). Do jednej symulacji przez sieć może być podłączonych kilku klientów. Już opisuję co jest nie tak, ale najpierw powiem jak wszystko działa.

Server:

  1. Ogarnia podłączenia się klientów
  2. 100 razy na sekundę wykonuje jeden step symulacji (co 10ms).
  3. Kiedy server dostanie command od klienta (np rusz tą piłkę w bok) to:
  • bierze lock do symulacji żeby wykonać command (np ruszyć tą piłkę) oraz zeby sprawdzić poprawność danych, na chwile stopuję symulację ale na pewno nie na 10ms (bo ile może trwać przypisanie czegoś? :D)
  • czeka na następny step symulacji (jeżeli pakiet przyszedł zaraz przed to czeka 1ms, jeżeli w połowie to 5ms, etc) (jest to zrobione tak że wątek nasłuchujący robi .wait(); a symulacja robi .notify(); kiedy jest wykonywana).
  • znowu zabiera lock do symulacji, robi kopię świata
  • odsyła info o pozycjach do klienta.

Klient:

  1. Przeprowadza swoją symulację u siebie
  2. Kiedy coś jest zmieniane wysyła command do servera
  3. Kiedy pakiet wraca symulacja jest updatowana tak żeby zgadzała się z serverem.

Nie jest to idealne wyjście ponieważ tworzy to ten sztuczny lag 10ms (myślałem że mogę to zignorować), początkowy plan jednak był taki że pakiet od razu wraca do klienta (trzeba jednak czekać na ten jeden step symulacji because of spójność danych i czasu (symulacja jest fixed timestep)).

Normalne zachowanie jest wtedy gdy

  1. Klient wyślę komand 1
  2. Server odeślę odpowiedź na komand 1

Nieoczekiwane zachowanie pojawia się gdy

  1. Klient wyślę komand 1
  2. Klient wyślę komand 2
  3. Server odeślę odpowiedź na komand 1
  4. Server odeślę odpowiedź na komand 2

Wtedy pojawia się taki "przeskok do tyłu", nie wiem jak to opisać więc sugeruję wyobrazić sobie zegarek w tej symulacji, zachowuje się on wtedy tak:
0:00, 0:01, 0:02, 0:00, 0:01, 0:02, 0:06, 0:07, 0:08
Progres symulacji u klienta wygląda wtedy tak:
f2c5a60d5b.png

Według mnie powodowane jest to tym że pakiet leci w jedną stronę np 30ms, 10ms czekania na step i wraca kolejne 30ms. Czyli stary pakiet jest te 70ms starszy (chyba?).

Moim rozwiązanie byłoby takie że:

  • Klient nie pozwoliłby użytkownikowi wysłać nowego pakietu zanim odpowiedź na stary nie dotrze (co jak pakiet zginie w sieci?)
  • Klient ignorowałby odpowiedź na stary pakiet, jeżeli nowy został wysłany.

Czy ktoś się wypowie o tym sposobie? Nie wiem czy ktoś z niego korzysta, napisałem to sam i chyba jest warte tyle co nic? :c

0

Jeśli dobrze rozumiem problem polega na odbieraniu pakietów w nieodpowieniej kolejności, tzn. w twoim przykładzie w pkt.3 serwer oczekuje odebrania komand1 a odbiera komand2? Nie wiem jakich technologi i protokołów używasz, ale jeśli pod spodem jest TCP, to kolejność bajtów odebranych przez recievera powinna odpowiadać kolejności bajtów wysłanych przez sendera.

0

Ignorowanie starych danych i walka z różnym opóźnieniem pakietów to kwestie dość dobrze przebadane w protokołach do multimediów (buzzwordy do googlowania: DCCP, RTP + RTCP, TCP UREL).
Mam wrażenie, że sam nie wiesz, co właściwie się dzieje i dlaczego. Co dokładnie jest odpowiedzi od serwera? Pozycje wszystkich klientów + znacznik czasowy? Co oznacza ten przeskok z 0:02 na 0:06? Po prostu licznik czasu skacze, czy też w jednym kroku jest robiona symulacja dla czterech sekund i stan jest w miarę poprawny? Za mało danych podałeś, aby można było wskazać najsensowniejsze rozwiązanie. Niemniej wydaje mi się, że Twój problem jest tożsamy problemowi pozycji zawodników w grze online, więc poszukałbym opisów, jak ludzie radzą sobie z tym na przykład w strzelankach.
No i najważniejsze: nie zgaduj, co powoduje problem, tylko udowodnij, że jest to kwestia pakietów w złej kolejności. Zamockuj interfejsy sieciowe i odtwórz sytuację - wróżenie jest średnim pomysłem.

0

Nie jest przesyłany żaden wskaźnik czasu (podałem go żeby lepiej zobrazować wszystko). Przesyłane są tylko pozycje obiektów.

Ten przeskok oznacza to że klient dostał już te "poprawne" dane.

Ogólnie symulacja i na serverze i na kliencie powinna być prostą linią (czyli dostajemy jeden punkt i server przeprowadza symulację a klient próbuje interpolować na podstawie danych które ma).

Przeskok w dół pojawia się gdy klient dostaje stare dane (sprzed tam 1 sekundy), wtedy "czas symulacji/interpolacji" u klienta się cofa na chwilę.

Jak drugi pakiet przychodzi to naprawia symulację i idzie nadal tak jak powinna.

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