程序的入口點(想讓其后臺默認.exe進程運行)
也可以不通過vs設置也可以通過定義預處理設置
第三種就是沒有窗口的
變成后臺運行的了
處理client傳來的數據包
第一步:咱們怎么設計一種包呢?
FEFF在網絡環境里面出現的概率低所以就采用這個
自己數據包截斷了,運行在公網時候有很多嗅探包,其他應用的誤發
class CPacket
{public:WORD sHead; //FEFFDWORD nLength; //包長度(從控制命令開始到和校驗結束)WORD sCmd; //控制命令,為了對齊習慣用WORDstd::string strData; //要發的包數據WORD sSum;//和校驗public:CPacket() :sHead(0), nLength(0), sCmd(0), sSum(0) {}//無參構造函數CPacket(const CPacket& pack) {sHead = pack.sHead;nLength = pack.nLength;sCmd = pack.sCmd;strData = pack.strData;sSum = pack.sSum;}CPacket(WORD nCmd, const BYTE* pData, size_t nSize) { //常量指針,指向的內容不能改變sHead = 0xFEFF; //頭nLength = nSize + 2 + 2; //數據的長度加上命令長度加上校驗的長度sCmd = nCmd; //命令if (nSize > 0) { //有數據strData.resize(nSize); //給包data容器重新設置長度memcpy((void*)strData.c_str(), pData, nSize); //給包打他字段設置上}else { //沒有數據了,頭字段和命令字段要清空strData.clear();}sSum = 0; //校驗和for (size_t j = 0; j < strData.size(); j++) {sSum += BYTE(strData[j]) & 0xFF;}}CPacket(const BYTE* pData, size_t& nSize) { //一開始傳入的這個nSize是傳入的一個包總大小size_t i = 0;for (; i < nSize; i++) {if (*(WORD*)(pData + i) == 0xFEFF) {sHead = *(WORD*)(pData + i);i += 2; //解析成功后,給解析失敗那里加邏輯break;}} //有沒有一種可能性,就是前面雜音數據是不是字節整數倍的情況if (i + 4 + 2 + 2 > nSize) { //解析失敗,怕越界呀,數據可能不全,或者包頭未能全部接收到嗎,這個前提是找到頭了nSize = 0; //用掉了0個字節return;}nLength = *(DWORD*)(pData + i); i += 4;if (nLength + i > nSize) { //包未完全接收到,就返回,解析失敗,半個包nSize = 0;//用掉了0個字節return;}sCmd = *(WORD*)(pData + i); i += 2;if (nLength > 4) { //這是構成包的前提strData.resize(nLength - 2 - 2);//命令和校驗位,長度不包含自身memcpy((void*)strData.c_str(), pData + i, nLength - 4); //將pData + i起始地址的nLength - 4個連續的字節復制到包的data區i += nLength - 4;}sSum = *(WORD*)(pData + i); i += 2;//下面就是和校驗的內容了WORD sum = 0;for (size_t j = 0; j < strData.size(); j++) {sum += BYTE(strData[j]) & 0xFF;}if (sum == sSum) {nSize = i;//nLength + 2 + 4;//head length datareturn;}nSize = 0;//解析失敗了}~CPacket(){}CPacket& operator=(const CPacket& pack) {if (this != &pack) {sHead = pack.sHead;nLength = pack.nLength;sCmd = pack.sCmd;strData = pack.strData;sSum = pack.sSum;}return *this;}
};
注意nSize是地址傳過來的,所以nSize全局跟隨,為什么這里不用Length呢?因為前面可能有廢數據,所以用nSize(程序里面的i)
接下來繼續寫上一章沒有完成的DealCmd了
int DealCommand() { //無限循環if (m_client == -1) return -1; //斷開連接了//char buffer[1024] = "";char* buffer = new char[4096]; //緩沖區memset(buffer, 0, 4096); //緩沖區置0size_t index = 0; //一開始從0開始的while (true) {size_t len = recv(m_client, buffer + index, 4096 - index, 0); //index是用掉的if (len <= 0) {return -1;}index += len; //可能收到2000個字節的包len = index;m_packet = CPacket((BYTE*)buffer, index); //將緩沖區包化//這個地方出來的index就是處理包獲得一段有效包用掉的大小if (len > 0) { //其實這段是廢話,能到這里len已經大于0了memmove(buffer, buffer + len, 4096 - len);//從buffer + len復制4096-len個字節到buffer,將下一個包數據往前挪index -= len; //可能只用1000個return m_packet.sCmd;}}return -1;}
index表示整個緩沖區當前剩余的字節(可能用掉了一個包,可能用掉了多個包)
len在包處理以前(CPacket)表示包的長度,在包處理以后(CPacket)表示這個完整的包用掉了多少字節
本質就是客戶端丟一坨數據(一般不超過4KB),自己想辦法解析