c语⾔解包封包函数,⼀个简单的SOCKET程序的数据包结
构和封解包函数...
练习写套接字通信程序时候写的⼀段代码,本来想写个聊天室但写来写去进度卡在界⾯上接节下来都是通信部分的代码
因为只是试验⽤所以都是⽤C写的,等界⾯部分完⼯后会⽤类来封装⼀下
因为本⼈E⽂很烂所以变量和函数的命名是具有中国特⾊的,求理解.不过我注释的很详细了
谨以此⽂纪念我那坑爹的编程⾃学⽣涯......................
#include "stdio.h"
#include
//数据包接构//
//数据包类型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; //命令标识
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)socket编程聊天室基本流程
{
sjb->tou.lxid=lxid; //填充数据包类型
sjb->tou.sxid=sxid; //填充数据包顺序标号
if(lxid==CTOS)
{
sjb->data.d=cmd; //填充命令标识
MoveMemory(sjb->data.msg_ctos.shuju,sjgd->sjgd,sjgd->sjcd); //填充附加数据
sjb->data.msg_ctos.sjbcd=sjgd->sjcd; //填充整个附加数据缓冲区的长度
}
if(lxid==STOC)
{
sjb->data.d=cmd; //填充命令标识
MoveMemory(sjb->data.msg_stoc.shuju,sjgd->sjgd,sjgd->sjcd); //填充附加数据
sjb->data.msg_stoc.sjbcd=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.d,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.d,4);//填充命令标识
MoveMemory(sjgd->sjgd+16,&sjb->data.msg_stoc.sjbcd,4);//填充整个附加数据缓冲区的长度MoveM
emory(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.d=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.d=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;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论