Jump to content

  • Log In with Google      Sign In   
  • Create Account


[SOLVED] C++ Sockets - Bytes Left


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
4 replies to this topic

#1 RoundPotato   Members   -  Reputation: 93

Like
0Likes
Like

Posted 19 September 2013 - 10:19 AM

Hey guys.

 

This "getBytesLeft()" somehow appears in my mind, no idea where is it from or why. So my thoughts are...

 

I believe "recv" returns the number of bytes received from the socket connection. Is there such a thing to show bytes that are left to receive or do you implement that yourself (with some headers of data to be sent and calculating with number of bytes returned by the "recv" against that?)  ?

 

Thanks.


Edited by RoundPotato, 19 September 2013 - 11:32 AM.


Sponsor:

#2 Vortez   Crossbones+   -  Reputation: 2688

Like
2Likes
Like

Posted 19 September 2013 - 10:58 AM

You usually prefix the lenght of the data you want to send with an int, so yea, you have to do it yourself. The "how" is up to you.

 

However... with a lot of work, you can automate all this process, like i did in my networking class. For example, to send data i do something like this:

struct CNetworkMsg {
	DWORD MsgSize;
	DWORD MsgID;
	BYTE* pData;
};

...

BYTE SomeBuffer[1000];
...

CNetworkMsg Msg;
Msg.MsgID   = 1; // <-- Whatever you want...
Msg.MsgSize = 1000;
Msg.pData   = (BYTE*)&SomeBuffer[0];

Client.SendMsg(&Msg);

On the other side, the read is automated inside the network class, when it's done reading it, this virtual funciton is called automatically, and do what i want with the message received

void CVortezNetworkClientExt::OnCustomNetworkMsgRecv(SOCKET s, CNetworkMsg *pMsg)
{
	//AddListboxMessageArg(MainForm->ListBox, "Custom Message Received: MsgID: 0x%8.8X MsgSize: %d (Socket: 0x%8.8X)", pMsg->MsgID, pMsg->MsgSize, (UINT)s);

	switch(pMsg->MsgID)
	{
	case 1:
		{
                    BYTE SomeBuffer[1000];

                    // useless memory copy, just an example...
                    memcpy(&SomeBuffer[0], pMsg->pData, pMsg->MsgSize);

                    // ... do something with the data
		}
		break;
	}
}

Im remaking one of my networked application right now with it and it work like a charm. So much easier (and faster) than my previous code that was polling the socket manually each time too (i now use windows messages to handle my sockets)

 

 

You probably won't understand the code im going to post, but here's how i do my read (just to give you an idea) As you can see, i start by reading the header, which is always 8 bytes long (2 x UINT), then i read as much bytes as Msg.MsgSize value.

//-----------------------------------------------------------------------------
// Read data
//-----------------------------------------------------------------------------
CReadResult CMsgReader::Read(SOCKET *pSock, UINT Source, DWORD BufSize)
{
	BYTE  *pBuf = NULL; 
	DWORD *pBufIndx = NULL;

	if(Source == MSG_HEADER_BUFFER){
		pBuf     = MsgBuffer.pHeader;
		pBufIndx = MsgBuffer.GetHeaderIndxPtr();
		BufSize  = PACKET_HEADER_SIZE;
	} else {
		pBuf     = MsgBuffer.pData;
		pBufIndx = MsgBuffer.GetDataIndxPtr();

	}

	// Find how many bytes we have to read, in chunk of MAX_PACKET_SIZE
	DWORD MaxBytesToProcess = (BufSize - *pBufIndx);
	if(MaxBytesToProcess > MAX_PACKET_SIZE)
		MaxBytesToProcess = MAX_PACKET_SIZE;

	/////////////////////////////////////////////////

	// Read/Write data
	DWORD NumBytesProcessed = recv(*pSock, (char*)&pBuf[*pBufIndx], MaxBytesToProcess, 0);
	
	/////////////////////////////////////////////////

	CReadResult Res;
	ZeroMemory(&Res, sizeof(CReadResult));

	/////////////////////////////////////////////////

	if(NumBytesProcessed != 0 && NumBytesProcessed != 0xFFFFFFFF){
		// Inc. our counters
		*pBufIndx += NumBytesProcessed;
		// Store how many bytes we've read
		Res.BytesReaden = NumBytesProcessed; 
		// Have we finished reading/writing data?   
		Res.IsBufferLimitReach = *pBufIndx == BufSize;
		// Have we hit M or Size limit?
		Res.IsPacketLimitReach = NumBytesProcessed == MAX_PACKET_SIZE;
		// Return sucess...
		Res.Succes = TRUE;
	}

	return Res;
}

/////////////////////////////////////////////////////////////////////////////////////////////////

BOOL CMsgReader::ReadMsg(SOCKET *pSock, HWND hHostWnd)
{
	// Read the Header of the message
	if(!MsgBuffer.IsHeaderDoneProcessing()){
		
		// Begin or resume reading the message header
		CReadResult Res = Read(pSock, MSG_HEADER_BUFFER, PACKET_HEADER_SIZE);
		if(!Res.Succes)
			return FALSE;

		// Are we done reading the msg header?
		if(MsgBuffer.IsHeaderDoneProcessing()){

			// Do we have some msg data left or available to read?
			if(MsgBuffer.IsDataDoneProcessing()){
			
				CNetworkMsg Msg;
				Msg.MsgID = MsgBuffer.Header.MsgID;
				Msg.MsgSize = MsgBuffer.Header.MsgSize;
				Msg.pData = MsgBuffer.pData;
				
				//ProcessMsg(&Msg);
				SendMessage(hHostWnd, ON_NETWORK_MESSAGE, (WPARAM)*pSock, (LPARAM)&Msg);
				
				MsgBuffer.Init();
				return TRUE;
			} else {
				MsgBuffer.AllocateDataBuffer();
			}				
		}
	} else if(!MsgBuffer.IsDataDoneProcessing()){   // The header is completely readen, 
			                                        // but not the data
		// Begin or resume reading the message data
		CReadResult Res = Read(pSock, MSG_DATA_BUFFER, MsgBuffer.Header.MsgSize);
		if(!Res.Succes)
			return FALSE;

		// Do we have some msg data left or available to read?
		if(MsgBuffer.IsDataDoneProcessing()){
			
			CNetworkMsg Msg;
			Msg.MsgID = MsgBuffer.Header.MsgID;
			Msg.MsgSize = MsgBuffer.Header.MsgSize;
			Msg.pData = MsgBuffer.pData;
			
			// This cause a call the virtual function OnCustomNetworkMsgRecv() shown above
			SendMessage(hHostWnd, ON_NETWORK_MESSAGE, (WPARAM)*pSock, (LPARAM)&Msg);

			MsgBuffer.Init();
			return TRUE;
		}
	}

	return 0;
}


Edited by Vortez, 19 September 2013 - 11:31 AM.


#3 RoundPotato   Members   -  Reputation: 93

Like
0Likes
Like

Posted 19 September 2013 - 11:31 AM

Thank you very much.

 

I always appreciate the additional information you have provided, this actually made me think about re-usability of structures and how they are stored in memory, their size etc. smile.png



#4 farmdve   Members   -  Reputation: 194

Like
2Likes
Like

Posted 19 September 2013 - 12:08 PM

The size of a structure can actually be reduced by just swapping some variables around, you can try to align them too.



#5 Vortez   Crossbones+   -  Reputation: 2688

Like
1Likes
Like

Posted 19 September 2013 - 12:23 PM

#pragma pack(1) can be usefull for this too.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS