Advertisement

Design / Send-Recv

Started by January 03, 2005 07:41 PM
4 comments, last by Basiror 20 years, 1 month ago
Hi there, I have wondering how to do the best send, recv structure for my game. I have an structure to use all the time when I send/recv data.. let me explain, this is the structure.

struct sbtsWData
{
	short length, pointer;
	short opcode;
	short packetSize;
	char  *data;

	/// Constructor
	sbtsWData( ):data( 0 ), length( 0 ), opcode( 0 ), pointer( 0 ) { }

	 // Destructor
	~sbtsWData( ) {
		clear( );
	}

	void Initialise( unsigned short newLength, unsigned short newOpcode ) {
		
		packetSize = newLength;
		setLength( newLength );
		opcode = newOpcode;
	}	

	void clear( ) {
    if( data )
      delete [] data;
		data = 0;
		opcode = 0;
	}

	short GetPacketSize() { return packetSize; }

	void setLength( unsigned short newlength )
	{
	    if( (newlength > length) | (data==0) ) {
		clear( );
		data = new char[newlength];
		}else 
		{		
			pointer = 0; opcode = 0;
		}
		length=newlength;
	}

	template < class type > inline sbtsWData & operator<<( const type &newData  ) {
    writeData( newData );
    return *this;
	}
	  template < class type > inline sbtsWData & operator>>( type &newData ) {
		readData( newData );
		return *this;
	}
  
	inline sbtsWData & operator<<( const char * newData ) {
		writeData( newData );
		return *this;
	}
	inline sbtsWData & operator>>( char * newData ) {
		readData( newData );
		return *this;
	}
  
	inline short & writeData( const void * newData, const short datalength ) {
		return pointer = writeDataAt( pointer, newData, datalength );
	}
	inline short & readData( void * newData, const short datalength ) {
		return pointer = readDataAt( pointer, newData, datalength );
	}

	template < class type > inline short & writeData( const type &newData ) {
		return pointer = writeDataAt( pointer, newData );
	}
	template < class type > inline short & readData( type &newData ) {
		return pointer = readDataAt( pointer, newData );
	}

	inline short & writeData( const char * newData ) {
		return pointer = writeDataAt( pointer, newData );
	}
	inline short & readData( char * newData ) {
		return pointer = readDataAt( pointer, newData );
	}

	inline short writeDataAt( const short offset, const char * newData ) {
		short dlen = strlen( newData ) + 1;
		WPAssert( offset + dlen <= length );
		memcpy( data + offset, newData, dlen );
		return offset + dlen;
	}
	inline short readDataAt( const short offset, char * newData ) {
		short dlen = strlen( (char *)data + offset ) + 1; 
		WPAssert( offset + dlen <= length );
		memcpy( newData, data + offset, dlen );
		return offset + dlen;
	}

	template < class type > inline short writeDataAt( const short offset, const type &newData ) {
		WPAssert( offset + sizeof( type ) <= length );
		memcpy( data + offset, &newData, sizeof( type ) );
		return offset + sizeof( type );
	}
	template < class type > inline short readDataAt( const short offset, type &newData ) const {
		WPAssert( offset + sizeof( type ) <= length );
		memcpy( &newData, data + offset, sizeof( type ) );
		return offset + sizeof( type );
	}

	inline short writeDataAt( const short offset, const std::string &newData ) {
		short dlen = newData.length( ) + 1; // trailing zero is included
		WPAssert( offset + dlen <= length );
		memcpy( data + offset, newData.c_str( ), dlen );
		return offset + dlen;
	}

	inline short readDataAt( const short offset, std::string &newData ) {
		newData = (char *) data + offset;
		short dlen = newData.length( ) + 1;
		WPAssert( offset + dlen <= length );
		return offset + dlen;
	}
  
	inline short writeDataAt( const short offset, const void * newData, const short datalength ) {
		WPAssert( offset + datalength <= length );
		memcpy( data + offset, newData, datalength );
		return offset + datalength;
	}

	inline short readDataAt( const short offset, void * newData, const short datalength ) const {
		WPAssert( offset + datalength <= length );
		memcpy( newData, data + offset, datalength );
		return offset + datalength;
	}
};

Well this is how I use it. to build a packet to send a simple string I do this. sbtsWData data; char text[32]; strcpy(text, "test"); short lenght = strlen(text); short size = sizeof(char)+lenght; data.clear(); data.Initialise(size, CMSG_1); data.writeData( text ); m_connection->Send((char*)&data, sizeof(sbtsWData)); and it works just fine to send the packet, but on the recv side I got problem, I recv it like this. sbtsWData *data; recv(mySocket, (char*)&data, sizeof(sbtsWData)); dont think thats right way to do this. anyway, then to use the recv data. char text[32]; if(data->opcode == CMSG_1) data->SetLenght( data->lenght ); *data >> text; printf(text); data->clear(); and I get error, the *data >> text; do the error, can't see whats wrong : but if I do this I dont get any errors. if(data->opcode == CMSG_1) { printf(data->lenght); } it prints out the lenght of the packet just fine so it have recv the data, or not all of it? bahh, hope anyone know what I mean, and if you know a bettere way to send/recv plz tell :) thanks.
-[ thx ]-
I'm not sure if this is your problem, but it should definitely be fixed.

sbtsWData *data;
recv(mySocket, (char*)&data, sizeof(sbtsWData));

You declare data as a pointer, but when passing it to the recv function, you use &data, which creates a pointer to a pointer. What you should probably do is declare it like this instead.

sbtsWData data;
Advertisement
Yea, I saw that, but I think my problem is how to recv all the data.

like this,

char *recvq;

int recvqmax;
int templen;

templen = recv(mSocket, recvq + recvqlen, recvqmax + recvqlen, 0);

recvqlen += templen;

or something :S donw know.

[Edited by - X5-Programmer on January 5, 2005 7:31:29 AM]
-[ thx ]-
When you take the address of "data", the struct, you only get the struct, not the data pointed at by its "data" pointer. When writing, you need to either use scatter/gather (a la writev()), or you need to create a single byte buffer that contains your entire packet (by copying), and then sending that.

In my packet class, I say that I won't ever send a packet greater than 1500 bytes. Then, I make the actual data buffer be a member of the packet class (preceeded by length, read pointer, etc).
enum Bool { True, False, FileNotFound };

sbtsWData data;
recv(mySocket, (char*)&data, sizeof(sbtsWData));
i am terry.hu
Quote:
Original post by hplus0603
When you take the address of "data", the struct, you only get the struct, not the data pointed at by its "data" pointer. When writing, you need to either use scatter/gather (a la writev()), or you need to create a single byte buffer that contains your entire packet (by copying), and then sending that.

In my packet class, I say that I won't ever send a packet greater than 1500 bytes. Then, I make the actual data buffer be a member of the packet class (preceeded by length, read pointer, etc).



i do it a little bit different

my network engine collects outgoing messages sorts them by type e.g. UDP(reliable/unreliable) or TCP do some bit compressions

then i get the messages by priority and at it to the packet

once this is done i check if its more then 200 bytes if so i perform a huffman compression which usually reduces size by 12-30%

and then i send
http://www.8ung.at/basiror/theironcross.html

This topic is closed to new replies.

Advertisement