Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[Winsock] Wysyłanie pakietów

Ostatnio zmodyfikowano 2016-10-13 19:50
Autor Wiadomość
marcolo2307
Temat założony przez niniejszego użytkownika
[Winsock] Wysyłanie pakietów
» 2016-10-13 19:50:54
Cześć!

Stworzyłem własną klasę pakietu (wzorowaną na sf::Packet z SFML2).

C/C++
class Packet
{
public:
    Packet();
    virtual ~Packet();
   
    const void * getData() const; // return &data[0];
    int getSize() const; // return data.size();
   
    void clear(); // data.clear(); currPos=0;
protected:
    std::vector < char > data; // dane
    unsigned int currPos; // pozycja czytania dla operatorów >>
    void addData( const void * data, std::size_t ); // wywoływane w każdym operatorze <<
};
Przykładowe operatory:
C/C++
Packet & Packet::operator <<( const Int32 & theData )
{
    Int32 tmp = htons( theData );
    addData( & tmp, sizeof( theData ) );
    return * this;
}
C/C++
Packet & Packet::operator >>( Int32 & theData )
{
    if( currPos + sizeof( theData ) <= data.size() )
    {
        theData = * reinterpret_cast < const Int32 *>( & data[ currPos ] ); // zawsze zwraca 0, chociaż data posiada dane
        theData = ntohs( theData );
        currPos += sizeof( theData );
    }
    return * this;
}

C/C++
void Packet::addData( const void * theData, std::size_t size )
{
    if( theData != nullptr && size > 0 )
    {
        std::size_t startPos = data.size();
        data.resize( data.size() + size );
        std::memcpy( & data[ startPos ], theData, size );
    }
}

Wysyłanie:
C/C++
for( unsigned int sent = 0; sent < toSend.size(); )
{
    int bytesSent =::send( socket, & toSend[ 0 ] + sent * sizeof( char ), toSend.size() - sent * sizeof( char ), 0 );
    // toSend to vector<char> zawierajacy int z wielkoscia pakietu + sam pakiet
    sent += bytesSent;
}

Odbieranie:
C/C++
received = 0;
char buffer[ 1024 ];
std::vector < char > toRecv; // zapisuje odebrane dane
while( received < packetSize ) // packetSize to wielkosc pakietu, prawidlowo odebrana wczesniej
{
    int bytesRecv =::recv( socket, buffer, std::min( packetSize - received, sizeof( buffer ) ), 0 );
    if( bytesRecv > 0 )
    {
        toRecv.resize( toRecv.size() + bytesRecv );
        std::memcpy(( & toRecv[ 0 ] + toRecv.size() - received ), buffer, received );
    }
    received += bytesRecv;
}
if( !toRecv.empty() )
{
    packet.data.resize( toRecv.size() );
    std::memcpy( & packet.data[ 0 ], & toRecv[ 0 ], toRecv.size() );
}

Mam także obsługę błędów (zwrócona wielkość send/recv ==0/INVALID_SOCKET), ale te nie występują.

C/C++
Packet p;
p << 1 << 2 << 3;
p >> i1 >> i2 >> i3;
To działa. Po wysłaniu i odebraniu pakiet jest pusty (zerowany na początku funkcji odbierania i wypełniany pustymi danymi z recv).

Błąd prawdopodobnie leży gdzieś przy wysyłaniu lub rzutowaniu z const void* na int. Pakiety działają tak samo jak w SFML2 (z pominięciem (nie)blokujących gniazd).[/code]

Edit:
Zakładam, że już nikt nie pomoże, więc zamykam temat, a jak tylko będę miał trochę czasu napiszę klasę Packet, z którą jest problem od nowa.
P-152532
« 1 »
  Strona 1 z 1