/*練習寫套接字通信程序時候寫的一段代碼,本來想寫個聊天室但寫來寫去進度卡在界面上接節下來都是通信部分的代碼 因為只是試驗用所以都是用C寫的,等界面部分完工后會用類來封裝一下 因為本人E文很爛所以變量和函數的命名是具有中國特色的,求理解.不過我注釋的很詳細了 謹以此文紀念我那坑爹的編程自學生涯......................**/ #include "stdio.h" #include <windows.h> //////////////////////////////數據包接構////////////////////////////////////// //數據包類型CTOS為客戶端使用的數據包,STOC為服務端使用的數據包 #define CTOS 1 #define STOC 2 //數據包存儲管道每個包最大為2000字節,其中數據載荷為最大1800字節,其余留着擴展數據包頭 struct SJGD { BYTE sjgd[2000]; //數據緩沖區 DWORD sjcd; //數據長度 }; //數據包頭大小為8字節 struct MSG_TOU { DWORD lxid; //數據包類型 DWORD sxid; //數據包順序標號 DWORD sjbcd; //數據包長度 }; //服務端-》客戶端包 struct MSG_STOC { DWORD cmd; //命令標識 DWORD sjbcd; //整個MSG_STOC數據包緩沖區的長度 BYTE shuju[1000]; //附加數據緩沖區 }; //客戶端-》服務器包 struct MSG_CTOS { DWORD cmd; //命令標識 DWORD sjbcd; //整個MSG_CTOS數據包緩沖區的長度 BYTE shuju[1800]; //附加數據緩沖區 }; //共用體 union MSG_DATA { struct MSG_STOC msg_stoc; struct MSG_CTOS msg_ctos; }; //完整數據包 struct SJB { struct MSG_TOU tou; //數據包頭 union MSG_DATA data; //數據緩沖區 }; ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// //封包函數第一個參數為數據包類型,第二個為命令標識,這是數據包的重點遠控命令會轉換成數字在這里傳輸 //第三個為數據包順序標號,第四個參數為附加數據緩沖區,第五個參數為打包數據緩沖區 //作用是把數據填充成一個標准的遠控數據包為下面的發包做准備 int Fengbao(DWORD lxid,DWORD cmd,DWORD sxid,struct SJGD*sjgd,struct SJB*sjb) { sjb->tou.lxid=lxid; //填充數據包類型 sjb->tou.sxid=sxid; //填充數據包順序標號 if(lxid==CTOS) { sjb->data.msg_ctos.cmd=cmd; //填充命令標識 MoveMemory(sjb->data.msg_ctos.shuju,sjgd->sjgd,sjgd->sjcd); //填充附加數據 sjb->data.msg_ctos.sjbcd=sjgd->sjcd; //填充整個附加數據緩沖區的長度 } if(lxid==STOC) { sjb->data.msg_stoc.cmd=cmd; //填充命令標識 MoveMemory(sjb->data.msg_stoc.shuju,sjgd->sjgd,sjgd->sjcd); //填充附加數據 sjb->data.msg_stoc.sjbcd=sjgd->sjcd; //填充整個附加數據緩沖區的長度 } sjb->tou.sjbcd=20+sjgd->sjcd; //填充數據包長度 if((lxid!=CTOS)&&(lxid!=STOC)) return 0; return 1; } /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// //發包函數第一個參數為待發數據包,第二個參數為數據管道緩沖區 //作用是把一個標准數據包以二進制的形式發送到數據管道緩沖區 int Fabao(struct SJB*sjb,struct SJGD*sjgd) { MoveMemory(sjgd->sjgd,&sjb->tou.lxid,4); //填充數據包類型 MoveMemory(sjgd->sjgd+4,&sjb->tou.sxid,4);//填充數據包順序標號 if(sjb->tou.lxid==CTOS) { MoveMemory(sjgd->sjgd+8,&sjb->tou.sjbcd,4); //填充數據包長度 MoveMemory(sjgd->sjgd+12,&sjb->data.msg_ctos.cmd,4);//填充命令標識 MoveMemory(sjgd->sjgd+16,&sjb->data.msg_ctos.sjbcd,4);//填充整個附加數據緩沖區的長度 MoveMemory(sjgd->sjgd+20,sjb->data.msg_ctos.shuju,sjb->data.msg_ctos.sjbcd); //填充附加數據 sjgd->sjcd=sjb->tou.sjbcd; //更新數據管道長度數據 return 1; } if(sjb->tou.lxid==STOC) { MoveMemory(sjgd->sjgd+8,&sjb->tou.sjbcd,4);//填充數據包長度 MoveMemory(sjgd->sjgd+12,&sjb->data.msg_stoc.cmd,4);//填充命令標識 MoveMemory(sjgd->sjgd+16,&sjb->data.msg_stoc.sjbcd,4);//填充整個附加數據緩沖區的長度 MoveMemory(sjgd->sjgd+20,sjb->data.msg_ctos.shuju,sjb->data.msg_stoc.sjbcd); //填充附加數據 sjgd->sjcd=sjb->tou.sjbcd; //更新數據管道長度數據 return 1; } return 0; } //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //函數作用是直接從內存讀取一個4字節的整數,為下面的解包做准備 int hex_int(char c) //從內存讀取一個1字節的整數 { if((c>='A')&&(c<='F')) { return (int)(c-'A'+10); } if((c>='0')&&(c<='9')) { return (int)(c-'0'); } return 0; } DWORD hex_dw(BYTE*hex) //從內存讀取一個4節的整數 { DWORD D=0; char x[2]; sprintf(x,"%.2X",hex[0]); D+=hex_int(x[1]); D+=hex_int(x[0])*16; sprintf(x,"%.2X",hex[1]); D+=hex_int(x[1])*16*16; D+=hex_int(x[0])*16*16*16; sprintf(x,"%.2X",hex[2]); D+=hex_int(x[1])*16*16*16*16; D+=hex_int(x[0])*16*16*16*16*16; sprintf(x,"%.2X",hex[3]); D+=hex_int(x[1])*16*16*16*16*16*16; D+=hex_int(x[0])*16*16*16*16*16*16*16; return D; } /////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// //解包函數第一個參數是待解包的數據管道緩沖區,第二個參數為解包數據存儲結構 //函數作用是把數據管道中的數據解封為一個標准的遠控數據包,用以控制程序流程 int Jiebao(struct SJGD*sjgd,struct SJB*sjb) { sjb->tou.lxid=hex_dw(sjgd->sjgd); //解封數據包類型 sjb->tou.sxid=hex_dw(sjgd->sjgd+4); //解封數據包順序標號 sjb->tou.sjbcd=hex_dw(sjgd->sjgd+8); //解封數據包長度 if(sjb->tou.lxid==CTOS) { sjb->data.msg_ctos.cmd=hex_dw(sjgd->sjgd+12); //解封命令標識 sjb->data.msg_ctos.sjbcd=hex_dw(sjgd->sjgd+16); //解封整個附加數據緩沖區的長度 MoveMemory(sjb->data.msg_ctos.shuju,sjgd->sjgd+20,sjb->data.msg_ctos.sjbcd); //解封附加數據 return 1; } if(sjb->tou.lxid==STOC) { sjb->data.msg_stoc.cmd=hex_dw(sjgd->sjgd+12); //解封命令標識 sjb->data.msg_stoc.sjbcd=hex_dw(sjgd->sjgd+16); //解封整個附加數據緩沖區的長度 MoveMemory(sjb->data.msg_stoc.shuju,sjgd->sjgd+20,sjb->data.msg_ctos.sjbcd); //解封附加數據 return 1; } return 0; } ////////////////////////////////////////////////////////////////////////////////////////
