jimmye Temat założony przez niniejszego użytkownika |
Winsock - problem z pakietami » 2009-05-14 10:09:52 Tak więc piszę od kilku dni proxy do gry Endless Online i mam jakiś problem z pakietami, niby program je przesyła (serwer-klient, klient-serwer), ale czasami zmienia sie ich długość, tzn. odbiera pakiet od klienta, który ma 11 bajtów, a wysyła ten sam, tyle, że on ma juz 22 bajty(już jeden pakiet tyle miał) i na końcu jakieś bajty z innego pakietu, przesłanego jako pierwszy. Oto moja pętla do odbierania/wysyłania pakietów: for(;; ) { bytesRecv_c = recv( sClient, recvbuff_c, DEFAULT_BUFFER, 0 ); if( bytesRecv_c > 0 ) { if( server_work == false ) { client_work = true; strRecv_c = recvbuff_c; length = strRecv_c.size(); output = strRecv_c.substr( 0, bytesRecv_s ); cout << "[RECV C]: " << "[" << pID << "]" << endl; strSend = strRecv_c; send( sServer, strSend.c_str(), length, 0 ); client_work = false; _sleep( 10 ); } } bytesRecv_s = recv( sServer, recvbuff_s, DEFAULT_BUFFER, 0 ); if( bytesRecv_s > 0 ) { if( client_work == false ) { server_work = true; strRecv_s = recvbuff_s; length = strRecv_s.size() - 1; output = strRecv_s.substr( 0, bytesRecv_s ); cout << "[RECV S]: " << "[" << pID << "]" << endl; strSend = strRecv_s; send( sClient, strSend.c_str(), length, 0 ); server_work = false; _sleep( 10 ); } } bytesRecv_c / _s - integer recvbuff_c / _s - character[ 1024 ] |
|
DejaVu |
» 2009-05-14 11:37:22 Niespecjalnie zrozumiałem treść Twojej wypowiedzi (konkretnie opisu problemu). Wiem, że robisz coś z siecią i pakiety, które są wysyłane mają (chyba) 11 bajtów. Ty otrzymujesz w pewnym momencie rozmiar pakietu 22 bajty, który Twoim zdaniem jest nieporządany. Jeśli każdy pakiet ma 11 bajtów, to powinno być oczywiste, że w przypadku 22 bajtów otrzymaleś odrazu dwa pakiety. Trochę teorii: 1. TCP (sockstream): komunikacja zapewnia dostarczenie pakietu w kolejności w jakiej został wysłany. Protokół ten generuje dodatkowy narzut ruchu sieci, który z punktu widzenia programisty nie ma znaczenia (poza tym, że powinien on sobie zdawać z niego sprawę). Drugą sprawą jest to, iż protokół ten jest wolniejszy. Spowodowane jest to faktem, iż jeśli pakiet nie dojdzie do klienta to zostanie on wysłany ponownie przez serwer bez pisania dodatkowego kodu. Taką funkcjonalność zapewnia protokół TCP. 2. UDP (datagram): umożliwia komunikację bezpołączeniową. Jest to wysyłanie pakietu bez nawiązywania połączenia z serwerem. Klient nie wie czy pakiet dojdzie. Nic nie wiadomo również o tym w jakiej kolejności pakiety dojdą. Zaletą tego protokołu jest generowanie mniejszego ruchu na sieci niż TCP oraz jest znacznie szybszy od protokołu TCP. Trochę o strumieniu danych: Największym problemem w pisaniu komunikacji sieciowej jest postać strumienia przychodzących danych. Nie dostajemy w nim informacji w takiej postaci w jakiej wysyłamy, tj. pakiet po pakiecie. W rzeczywistości otrzymujemy ciąg danych binarnych, które zostały już dostarczone do serwera. Przykładowo: Klient: wyslij(serwer,'napis1'); wyslij(serwer,'napis2'); wyslij(serwer,'napis3');
Serwer: czekaj(3000);//czeka 3 sek odbierz(klient,napis,odebranaDlugosc);
W powyższym przypadku serwer z dużym prawdopodobieństwem otrzyma odrazu napis ze wszystkich 3 pakietów, tj wartość zmiennej napis po stronie serwera będzie następująca: napis = 'napis1napis2napis3'; Powyższy przykład ilustruje jaki problem sprawia najwięcej trudności przy pisaniu komunikacji sieciowych w grach. Konkretniej: nie jesteśmy w stanie odróżnić na serwerze gdzie się kończy lub zaczyna pakiet. Takie informacje powinny być zawarte w każdym pakiecie, jeśli chcemy mieć różne rozmiary paczek z danymi. |
|
jimmye Temat założony przez niniejszego użytkownika |
hmm » 2009-05-14 11:58:48 Proxy to ma zadanie odbierać pakiety od klienta i dostarczać je do serwera i na odwrót, przy czym moge je edytować "w locie" :P W grze tej przy łączeniu przechodzą 3 pakiety: 1. żądanie połączenia od klienta, 2. odpowiedź na rządanie, 3. dziwny pakiet(jakiś hash) sprawdza autentyczność serwera.
1-szy pakiet zawsze ma długość 22, drugi trochę inną 3-ci zywkle ma 11 bajtów
Dwa pierwsze pakiety przechodzą bez problemu, prawidłowa długość. Problem polega na tym, że ten trzeci odbierany jest normalnie(11 bajtów), a wysyłany jest o długości 22 bajty, po 11 bajcie reszta informacji, to informacje z pierwszego pakietu, czyli żądanie połączenia.
Dodałem też sobie dodatkowe zmienne: server_work i client_work, które mają zapobiec w pewnym sensie mieszaniu się pakietów, ale w tym przypadku nie skutkuje. |
|
DejaVu |
» 2009-05-14 23:05:49 Jakoś niejasno problem opisujesz :) Zrozumiałem: 1) odbierasz pakiet 1: 22 bajty 2) odbierasz pakiet 2: ileś bajtów 3) odbierasz pakiet 3: 11 bajtów 4) wysyłasz 3 pakiet o rozmiarze 11 bajtów 5) 'coś' odbiera ten trzeci pakiet, ale ma on 22 bajty Dobrze zrozumiałem? |
|
« 1 » |