socket dziwny problem

0

Witam,

ostatnio piszę program do obsługi protokołu pewnej gry, i trafiłem an cholerny problem po za jej protokołem, a mianowicie na sockecie:

Jest taki problem, że gdy dostanę lagga (dajmy na to chwilowe zamulenie neta) recv odbiera tylko jeden lub żaden pakiet z których powinien być kilka dodatkowych (gubie pakiety) i wszystko szlak trafia, bo program zaczyna się mylić.

Sprawdzałem to na samej grze i snifferze pakietów, gdy zamuliłem neta i odmuliłem po chwili dostał wszystkie pakiety które w czasie zamulenia wystąpiły a mój program w takiej chwili odbierze jeden (pierwszy - algo w ogóle).

Całe odbieranie mam na wątku z boosta, a tworzenie połączenia wygląda tak:

     if (WSAStartup(MAKEWORD(2,0), &wsaData)==0)
    {
         LoginSocket = INVALID_SOCKET;
         sockAddr.sin_family = AF_INET;
   	     sockAddr.sin_port = htons(port);
         sockAddr.sin_addr.s_addr = inet_addr(host.c_str());
  		 LoginSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  		 
  		 
         if(connect(LoginSocket, (struct sockaddr*)&sockAddr, sizeof(sockAddr))!=SOCKET_ERROR)
         {
//tutaj bleble zrob cos.
         }
    }   

Odbieranie to funkcja void na wątku razem z parsowaniem:

boost::thread thrd1(boost::bind(&Network::onReceive,this)); 
void Network::onReceive()
{
 unsigned char recvBuffer[8096];
 while(true)
 {
  packet_size = 0;
  int iResult = recv(LoginSocket, (char*)recvBuffer, sizeof(recvBuffer), 0);
  if (iResult > 0)
   {
  //bleble
 }
}
}

Nie wiem naprawdę co jest, a dobry z winsocka nie jestem.

0

Może chodzi o to, że za każdym razem wczytujesz dane na początek bufora, zamiast na koniec (poprzednio odebranych danych)?
Gdy chcesz odebrać jakiś większy pakiet, a wszystkie pakiety mają nagłówek mówiący o typie i wielkości, to musisz dodać zmienną określającą ile bajtów pakietu już skompletowałeś, i użyć jej w runkcji recv:
recvBuffer+bytesCompleted, min(siezofPacket, sizeof(recvBuffer)-bytesCompleted)

Napisz inteligentną pętlę która będzie wiedziała czy odebrano kompletny pakiet, czy jeszcze trzeba dociągnąć kilka bajtów.

0

Chyba znalazłem problem dzięki Tobie, ale muszę mieć potwierdzenie:

Czy recv odbiera wszystkie pakiety skumulowane w czasie dajmy na to. lagga? Tj. popatrzmy tak, że dostałem od serwera 5 różnych pakietów, które trzeba osobno zdekodować, ale akurat wtedy lagga miałem, i czy recv je wszystkie pakuje do bufora z socketa? Wszystkie 5 na raz? Jeśli tak, to wiem co za problem.

0

Oczywiście, jeden recv może zwrócić kilka pakietów. Winsock ma prawo skleić kilka pakietów w jeden, jeśli przyjdą w krótkim czasie - np. gdy manager wątków nie zdąży przelecieć wszystkich wątków z listy aktywnych.

Musisz to jakoś rozwiązać, np. odbierz najpierw tyle bajtów pakietu, by wiedzieć jaki jest rozmiar pakietu, a potem w pętli skompletuj pakiet, nie pobierając więcej bajtów niż trzeba. Inną drogą możesz pobrać więcej niż trzeba, ale nadmiarowe bajty przesuń na początek bufora i potraktuj je jak początek kolejnego pakietu.

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