https://blog.csdn.net/luoti784600/article/details/12646405
Reprint please indicate the origin of the article: http://blog.csdn.net/luoti784600/article/details/12646405
TCP based network programming, data transmission is based on the connection, so when the network congestion or high frequency of transmission, there will be sticky packets.
Sticky package is not a receive corresponding to a send, there may be a receive corresponding to multiple send, or perhaps a receive less than one send.
Because we are in the network programming, often object as the unit to send, so the receiving end must handle the sticky package, restore the original object.
The following figure illustrates the various scenarios that receive data from the receiving end:
of course, the reception of the first situation is ideal and does not have to be addressed. This article deals with 2 3 4 cases.
Algorithm resolution:
First, there is an object that holds the last data that could not be processed, and the length of the last time the data was processed.
1. The data received is spliced to the last unhandled data, and the data is not processed.
2. Determine if the unhandled data is greater than the length of the header,
If less than Baotou, direct exit (Baotou save length information), otherwise turn 3.
3. According to the header to determine whether the object size is greater than the length of the unhandled data, if the Turn 3, otherwise save the unhandled data exit.
4. Cut out the first object for processing, the rest of the data to be saved to the unhandled object, continue to spin 2 loops.
[CPP] The view plain copy// tcpdatasplit.cpp : defines the entry point for the console application. // #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NETPACK_SIZE 10000 #define MAX_DATA_SIZE 4086 /* Data Header type */ struct netdataheader_t { int nDataType; //packet type, identifying the corresponding object type int nDataSize; The length of szdata real data in //packets }; /* Packet type */ struct netdatabase_t { NetDataHeader_t dataHeader; //Data Baotou char szdata[max_data_size]; // Real data }; /** actually netdatabase_t is the underlying type, so we can extend many subtypes , So we have to be clear that each type of length is not the same, not all sizeof (netdatabase_t), Is that each type of object has a different size, such as: in a derived structure, netdatapeople_t and netdataschool_t are two different structures, But they all have the associated header section indicating the structure type and length. */ struct netdatapeople_t { netdataheader_ t dataheader; int nAge; char szName[10]; }; struct NetDataSchool_t { NetDataHeader_t dataHeader; char szShoolName[20]; char szShoolAddress[30]; }; /** deal with the organized objects. */ Bool handlenetpack (netdataheader_t* pdataheader); Bool tcpdatasplit (const char* szrecnetdata, int nrecsize) { /** for szlastsavedata, nremainsize, for simplicity, this example only is used as a static variable, so it is limited to one socket for data reception, If you want to process multiple socket data at the same time, please keep it in the corresponding container */ static char szLastSaveData[MAX_NETPACK_SIZE]; static int nremainsize = 0; static bool bFirst = true; if (bfirst) { memset (szlastsavedata, 0, sizeof ( Szlastsavedata); bFirst = false; } /* This received data stitching to the last data */ memcpy ( (char*) (szlastsavedata+nremainsize), szrecnetdata, nrecsize ); nRemainSize = nRecSize + nRemainSize; /* forced conversion to netdatapack pointer */ netdataheader_t* pDataHead = (netdataheader_t*) szlastsavedata; / ** Core algorithm */ while ( nremainsize >sizeof (netdataheader_t) && nremainsize >= pdatahead->ndatasize +sizeof (netdataheader_t) ) { handlenetpack ( Pdatahead); int nrecobjectsize = sizeof (netdataheader_t) + pDataHead->nDataSize; //the size of the object received this time nremainsize -= nrecobjectsize ; pdatahead = (netdataheader_t*) ( (char*) pdatahead + nrecobjectsize ); //move Next Object header } /* remaining data failed to form an object, save first */ if (szlastsavedata != (char*) pdatahead) { &NBSP;&NBSP;&NBSP;&NBSP; memmove (szlastsavedata, (char*) pdatahead, nremainsize); memset ( (char*) ( szlastsavedata+nremainsize), 0, sizeof (szlastsavedata)-nremainsize ); } return true; } /** handle the objects. */ Bool handlenetpack (netdataheader_t* pdataheader) { //processing Packet if (pdataheader->ndatatype == 1) { netdatapeople_t* ppeople = (netdatapeople_t*) pdataheader; printf ("Received people object, age:%d, name:%s\n", Ppeople->nage, ppeople->szname); } else if (pdataheader->ndatatype == 2) { NetDataSchool_t* pSchool = (Netdataschool _t*) pdataheader; printf ("Received school object, SchoolName:%s, schooladdress:%s\n ", pschool->szshoolname, pschool->szshooladdress); } return true; } Int _tmain (int argc, _tchar* argv[]) { /* This example takes two objects as the received data */ NetDataPeople_t people; people.dataheader.ndatasize = sizeof (People) - sizeof (Netdataheader_t); people.dataHeader.nDataType = 1; people.nAge = 20; sprintf (People.szname, "Jim"); //real data NetDataSchool_t school; school.dataheader.ndatasize = sizeof (school) - sizeof (netdataheader_t); school.dataheader.ndatatype = 2; sprintf (School.szShoolName, "Tsinghua University"); //real data sprintf (school.szshooladdress, "Peking Road, Beijing"); //real data /* Merging two object data into one address to reproduce the sticky packet */ char szsenddaTa[sizeof (People) +sizeof (school)]; memcpy (szsenddata, ) &people, sizeof (people)); memcpy (szSendData+sizeof (people), (char*) &school, sizeof (school)); // Here to collect data operation, here omitted ... /** Deliberately set the sticky pack: 1. Send only 3 bytes for the first time, not enough to build Baotou 2. The second send 10 bytes, a total of 13, but the first object size is 8+14=18, so the first object people also confiscated 3. Send the rest of the third time, the rest of the first object is glued together with the second object, validating the processing */ tcpdatasplit ((char*) szsenddata, 3); Tcpdatasplit ((char*) szsenddata+3, 10); tcpdatasplit ((char*) SzsenddatA+13, sizeof (szsenddata) -13); getchar (); return 0; }