怎么打包啊!急(200分)

  • 主题发起人 主题发起人 truegary
  • 开始时间 开始时间
T

truegary

Unregistered / Unconfirmed
GUEST, unregistred user!
小弟正在编写一个发包收包的通讯程序,其中有一定包格式。
一个包有四部分组成,Code是一个字节,length是两个字节,
id是一个字节,value是8个字节。

我现在有一个byte类型的Code,shortint类型的length,
byte类型的id,char[8]的value。请问我如果把他们打到一个buff里发送
 
参考一下
///////////////////////////////////////
///数据包的定义
///采用TMCT 方式
///时间:2003/6/20
//////////////////////////
unit Unit2;

interface
uses
Windows, Messages, SysUtils, Classes, Controls,StdCtrls,Dialogs,forms,
IniFiles, Graphics;

procedure CRC_Check;


type
TSendStruct = Array[0..15] of Byte;
TPortStatus = (ptsClosed, ptsOpened, ptsFault, ptsNotExist);//分支分配器的端口状态

TMacAddr = packed record
wHigh :Word;
wMid :Word;
wLow :Word;
end;

// 系统时间命令
TTmctTimeCmd = packed record
bCmd :Byte;
bSubCmd :Byte;
Systime :Longword; //系统时间,为从2000年1月1日0时起的秒数
end;


TTmctTimePkt = packed record
bSynch :Byte; //同步头
bCtrl :Byte; //控制字段
Address :TMacAddr; //地址字段,TMCT地址
bPktID :Byte; //包序号
wDataLen :Word; //数据字段长度
CmdPkt :TTmctTimeCmd;//数据字段
wFcs :Word; //校验,采用CRC-X.25
end;



//TBin_开头的结构与传输的协议数据包的格式相同
PBin_SubStat = ^TBin_SubStat;
TBin_SubStat = packed record
SubAddr: Byte;
PortStat: Longword;
end;
// 分支器控制
PTmctSubCmd = ^TTmctSubCmd;
TTmctSubCmd = packed record
bCmd :Byte;
bSubCmd :Byte;
subStat :TBin_SubStat; //分支器控制数据
end;

//分支器控制包
TSockSubPkt = packed record
wIndex :Word;
mac :TMacAddr;
bCmd :Byte;
bSubCmd :Byte;
subStat :TBin_SubStat;
end;

TTmctSubPkt = packed record
bSynch :Byte; //同步头
bCtrl :Byte; //控制字段
Address :TMacAddr; //地址字段,TMCT地址
bPktID :Byte; //包序号
wDataLen :Word; //数据字段长度
CmdPkt :TTmctSubCmd;//数据字段,这里为分支器的控制指令包
wFcs :Word; //校验,采用CRC-X.25
end;
// 分支分配器状态
PSubStat = ^TSubStat;
TSubStat = record
SubAddr: Byte;
PortStat: array [0..15] of TPortStatus;
end;

var
SendStruct:TSendStruct;
tmctSubPkt :TTmctSubPkt;
tmctTimePkt :TTmctTimePkt ;
Const
CRC_Tab:Array[0..255] of WORD =
($0000,$1021,$2042,$3063,$4084,$50A5,$60C6,$70E7,$8108,$9129,$A14A,$B16B,$C18C,$D1AD,$E1CE,$F1EF,
$1231,$0210,$3273,$2252,$52B5,$4294,$72F7,$62D6,$9339,$8318,$B37B,$A35A,$D3BD,$C39C,$F3FF,$E3DE,
$2462,$3443,$0420,$1401,$64E6,$74C7,$44A4,$5485,$A56A,$B54B,$8528,$9509,$E5EE,$F5CF,$C5AC,$D58D,
$3653,$2672,$1611,$0630,$76D7,$66F6,$5695,$46B4,$B75B,$A77A,$9719,$8738,$F7DF,$E7FE,$D79D,$C7BC,
$48C4,$58E5,$6886,$78A7,$0840,$1861,$2802,$3823,$C9CC,$D9ED,$E98E,$F9AF,$8948,$9969,$A90A,$B92B,
$5AF5,$4AD4,$7AB7,$6A96,$1A71,$0A50,$3A33,$2A12,$DBFD,$CBDC,$FBBF,$EB9E,$9B79,$8B58,$BB3B,$AB1A,
$6CA6,$7C87,$4CE4,$5CC5,$2C22,$3C03,$0C60,$1C41,$EDAE,$FD8F,$CDEC,$DDCD,$AD2A,$BD0B,$8D68,$9D49,
$7E97,$6EB6,$5ED5,$4EF4,$3E13,$2E32,$1E51,$0E70,$FF9F,$EFBE,$DFDD,$CFFC,$BF1B,$AF3A,$9F59,$8F78,
$9188,$81A9,$B1CA,$A1EB,$D10C,$C12D,$F14E,$E16F,$1080,$00A1,$30C2,$20E3,$5004,$4025,$7046,$6067,
$83B9,$9398,$A3FB,$B3DA,$C33D,$D31C,$E37F,$F35E,$02B1,$1290,$22F3,$32D2,$4235,$5214,$6277,$7256,
$B5EA,$A5CB,$95A8,$8589,$F56E,$E54F,$D52C,$C50D,$34E2,$24C3,$14A0,$0481,$7466,$6447,$5424,$4405,
$A7DB,$B7FA,$8799,$97B8,$E75F,$F77E,$C71D,$D73C,$26D3,$36F2,$0691,$16B0,$6657,$7676,$4615,$5634,
$D94C,$C96D,$F90E,$E92F,$99C8,$89E9,$B98A,$A9AB,$5844,$4865,$7806,$6827,$18C0,$08E1,$3882,$28A3,
$CB7D,$DB5C,$EB3F,$FB1E,$8BF9,$9BD8,$ABBB,$BB9A,$4A75,$5A54,$6A37,$7A16,$0AF1,$1AD0,$2AB3,$3A92,
$FD2E,$ED0F,$DD6C,$CD4D,$BDAA,$AD8B,$9DE8,$8DC9,$7C26,$6C07,$5C64,$4C45,$3CA2,$2C83,$1CE0,$0CC1,
$EF1F,$FF3E,$CF5D,$DF7C,$AF9B,$BFBA,$8FD9,$9FF8,$6E17,$7E36,$4E55,$5E74,$2E93,$3EB2,$0ED1,$1EF0);

const
TMCT_SYNCH = $A5; //同步头
TMCT_CTRL = $00; //控制字,现为0
X25_CRC_Table : array[0..255] of WORD = //CRC X25方式的速查表
($0000, $1021, $2042, $3063, $4084, $50A5, $60C6, $70E7,
$8108, $9129, $A14A, $B16B, $C18C, $D1AD, $E1CE, $F1EF,
$1231, $0210, $3273, $2252, $52B5, $4294, $72F7, $62D6,
$9339, $8318, $B37B, $A35A, $D3BD, $C39C, $F3FF, $E3DE,
$2462, $3443, $0420, $1401, $64E6, $74C7, $44A4, $5485,
$A56A, $B54B, $8528, $9509, $E5EE, $F5CF, $C5AC, $D58D,
$3653, $2672, $1611, $0630, $76D7, $66F6, $5695, $46B4,
$B75B, $A77A, $9719, $8738, $F7DF, $E7FE, $D79D, $C7BC,
$48C4, $58E5, $6886, $78A7, $0840, $1861, $2802, $3823,
$C9CC, $D9ED, $E98E, $F9AF, $8948, $9969, $A90A, $B92B,
$5AF5, $4AD4, $7AB7, $6A96, $1A71, $0A50, $3A33, $2A12,
$DBFD, $CBDC, $FBBF, $EB9E, $9B79, $8B58, $BB3B, $AB1A,
$6CA6, $7C87, $4CE4, $5CC5, $2C22, $3C03, $0C60, $1C41,
$EDAE, $FD8F, $CDEC, $DDCD, $AD2A, $BD0B, $8D68, $9D49,
$7E97, $6EB6, $5ED5, $4EF4, $3E13, $2E32, $1E51, $0E70,
$FF9F, $EFBE, $DFDD, $CFFC, $BF1B, $AF3A, $9F59, $8F78,
$9188, $81A9, $B1CA, $A1EB, $D10C, $C12D, $F14E, $E16F,
$1080, $00A1, $30C2, $20E3, $5004, $4025, $7046, $6067,
$83B9, $9398, $A3FB, $B3DA, $C33D, $D31C, $E37F, $F35E,
$02B1, $1290, $22F3, $32D2, $4235, $5214, $6277, $7256,
$B5EA, $A5CB, $95A8, $8589, $F56E, $E54F, $D52C, $C50D,
$34E2, $24C3, $14A0, $0481, $7466, $6447, $5424, $4405,
$A7DB, $B7FA, $8799, $97B8, $E75F, $F77E, $C71D, $D73C,
$26D3, $36F2, $0691, $16B0, $6657, $7676, $4615, $5634,
$D94C, $C96D, $F90E, $E92F, $99C8, $89E9, $B98A, $A9AB,
$5844, $4865, $7806, $6827, $18C0, $08E1, $3882, $28A3,
$CB7D, $DB5C, $EB3F, $FB1E, $8BF9, $9BD8, $ABBB, $BB9A,
$4A75, $5A54, $6A37, $7A16, $0AF1, $1AD0, $2AB3, $3A92,
$FD2E, $ED0F, $DD6C, $CD4D, $BDAA, $AD8B, $9DE8, $8DC9,
$7C26, $6C07, $5C64, $4C45, $3CA2, $2C83, $1CE0, $0CC1,
$EF1F, $FF3E, $CF5D, $DF7C, $AF9B, $BFBA, $8FD9, $9FF8,
$6E17, $7E36, $4E55, $5E74, $2E93, $3EB2, $0ED1, $1EF0
);

const
CMD_TALK = $F5; //HMCU 指令
SUBCMD_TIME = $00; //SYSTIME
// SUBCMD_SUB = $07; //HMCU 开关控制指令

function PktSockSub(FskPkt :TSendStruct; var SockPkt:array of TSockSubPkt;
var CmdInfo:array of string) :Integer;
function GetDist(FskPkt :TSendStruct; var Dist :array of Byte) :Integer;
function Fsk2SockSub(FskPkt:TSendStruct; Dist:Byte; var strInfo:String) :TSubStat;
function SubStat2Bin(pd: PSubStat): TBin_SubStat;
procedure InvertByteOrder(pd: Pointer; dlen: Integer);
procedure PktTmctSub(sockPkt:TSockSubPkt; var tmctPkt:TTmctSubPkt);
function GetNextPktID:Byte;
function GetTmctCRC(tmctPkt:TTmctSubPkt):Word;
function X25_CRC(CrcAccum:Word; const Buf:PByte; nNum:Byte):Word;
procedure SendTmctPkt(tmctPkt :TTmctSubPkt);
procedure SendTmctBin(strTmp:string; nCount:integer);
procedure TimeDelay(ms :Dword);
procedure makeandsendFSKdata;
var
g_bPktID :Byte;
SUBCMD_SUB:Byte;
implementation
uses
unit1;

procedure CRC_Check;
var
i:integer;
CRC:word;
a:word;
b:word;
c:word;
begin
a:= SendStruct[0];
b:= SendStruct[1];
For i := 0 to 13 do
begin
CRC:= CRC_Tab[a];
c:= SendStruct[i+2];
a := (((CRC shr 8) and $00ff) xor b );
b := ((CRC and $00ff) xor c );
end;
SendStruct[14] := (a and $00ff);
SendStruct[15] := (b and $00ff);
end;

// 从FSK包中获取分支器的个数, 并在Dist中保存其中的分支器号
function GetDist(FskPkt :TSendStruct; var Dist :array of Byte) :Integer;
var
i, j, k, n :Integer;
DistTmp :array[0..4] of Byte;
begin
if FskPkt[4] = 0 then // 分支器号为0时为特殊指令
begin
Result := 0;
Exit;
end;

for i := 0 to 4 do
DistTmp := 0;

n := 0;
k := 4; // FSK 包第一个分支开关指令的起始位置
for i := 0 to 4 do
begin
for j := 0 to n do
begin
if DistTmp[j] = 0 then
begin
DistTmp[j] := FskPkt[k];
break;
end
else
begin
if DistTmp[j] = FskPkt[k] then
break;
end;
end;
k := k + 2;
n := n + 1;
if FskPkt[k] = 0 then
break;
end;

for i := 0 to n-1 do
Dist := DistTmp;

Result := n;
end;

// 转换FSK中的端口状态
function Fsk2SockSub(FskPkt:TSendStruct; Dist:Byte; var strInfo:String) :TSubStat;
var
nPortNO :Integer;
i, n :Integer;
sub :TSubStat;
strTmp :String ;
begin
for i := 0 to 15 do
sub.PortStat := ptsNotExist;

strTmp := '';
n := 4;
sub.SubAddr := Dist;
if (Dist and $80) = 0 then // 小分支
begin
for i := 0 to 4 do //FskPkt包中最多可能有5个端口控制指令
begin
if FskPkt[n] = Dist then
begin
nPortNo := (FskPkt[n+1] and $0C) shr 2;
sub.PortStat[nPortNo] := TPortStatus( FskPkt[n+1] and $01 );
strTmp := ' 端口' + IntToStr(nPortNO + 1) + ':';
if sub.PortStat[nPortNo] = ptsOpened then
strTmp := strTmp + '开 '
else
strTmp := strTmp + '关 ';
end;
n := n + 2;
end;
end
else // 大分支
begin
for i := 0 to 4 do
begin
if FskPkt[n] = Dist then
begin
nPortNo := (FskPkt[n+1] and $FE) shr 1;
nPortNo := nPortNo - 1; // 大分支号从1 开始,所以减1
sub.PortStat[nPortNo] := TPortStatus( FskPkt[n+1] and $01 );
strTmp := ' 端口' + IntToStr(nPortNO + 1) + ':';
if sub.PortStat[nPortNo] = ptsOpened then
strTmp := strTmp + '开 '
else
strTmp := strTmp + '关 ';
end;
end;
end;

strInfo := strTmp;
Result := sub;
end;

//将指定存储区的字节顺序颠倒过来
procedure InvertByteOrder(pd: Pointer; dlen: Integer);
var
i: Integer;
td: Char;
begin
for i:=0 to (dlen div 2) - 1 do
begin
td := (PChar(pd) + i)^;
(PChar(pd) + i)^ := (PChar(pd) + dlen - i - 1)^;
(PChar(pd) + dlen - i - 1)^ := td;
end;
end;

// 转换端口状态格式
function SubStat2Bin(pd: PSubStat): TBin_SubStat;
var
i: Integer;
stat: Longword;
bin: TBin_SubStat;
begin
bin.SubAddr := pd.SubAddr;
stat := 0;
for i:=15 downto 0 do
begin
stat := stat shl 2;
stat := stat + (Byte(pd.PortStat) and $03);
end;
InvertByteOrder(@stat, Sizeof(Longword));
bin.PortStat := stat;

Result := bin;
end;


function PktSockSub(FskPkt :TSendStruct; var SockPkt:array of TSockSubPkt;
var CmdInfo:array of string) :Integer;
var
i :Integer;
subStat :TSubStat;
DistNum :Integer;
arrDist :array[0..4] of Byte;
strTmp :string;
begin
DistNum := GetDist(FskPkt, arrDist);

for i := 0 to DistNum-1 do
begin
SockPkt.wIndex := $FFFF;

SockPkt.mac.wHigh := 0;
SockPkt.mac.wMid := FskPkt[0];
SockPkt.mac.wMid := SockPkt.mac.wMid shl 8;
SockPkt.mac.wLow := FskPkt[2];
SockPkt.mac.wLow := (SockPkt.mac.wLow shl 8) + FskPkt[1];

SockPkt.bCmd := CMD_TALK;
SockPkt.bSubCmd := SUBCMD_SUB;

subStat := Fsk2SockSub(FskPkt, arrDist, strTmp);
SockPkt.subStat := SubStat2Bin(@subStat);
end;

Result := DistNum;
end;

function GetNextPktID:Byte;
begin
g_bPktID := (g_bPktID + 1) mod $C0;
Result := g_bPktID + $C0;
end;

// CRC-X25 速算法
function X25_CRC(CrcAccum:Word; const Buf:PByte; nNum:Byte):Word;
var
p :PByte;
bPos :Byte;
begin
p := Buf;
while (nNum > 0) do
begin
bPos := Byte(CrcAccum shr 8) xor p^;
CrcAccum := (CrcAccum shl 8) xor X25_CRC_Table[bPos];
Inc(p);
Dec(nNum);
end;
Result := CrcAccum;
end;

function GetTmctCRC(tmctPkt:TTmctSubPkt):Word;
begin
Result :=not X25_CRC($FFFF, @tmctPkt.bCtrl, sizeof(TTmctSubPkt)-3);
end;

// 将网络格式的分支器控制包转换为TMCT协议下的分支器控制包
procedure PktTmctSub(sockPkt:TSockSubPkt; var tmctPkt:TTmctSubPkt);
begin
tmctPkt.bSynch := TMCT_SYNCH;
tmctPkt.bCtrl := TMCT_CTRL;
tmctPkt.Address := sockPkt.mac;
tmctPkt.bPktID := GetNextPktID;
tmctPkt.wDataLen := sizeof(TTmctSubCmd);
InvertByteOrder(@tmctPkt.wDataLen, sizeof(Word));

tmctPkt.CmdPkt.bCmd := sockPkt.bCmd;
tmctPkt.CmdPkt.bSubCmd := sockPkt.bSubCmd;
tmctPkt.CmdPkt.subStat := sockPkt.subStat;

tmctPkt.wFcs := GetTmctCRC(tmctPkt);
end;

//时间延迟
procedure TimeDelay(ms :Dword);
var
t :Dword;
begin
t := GetTickCount;
while (GetTickCount - t) < ms do
Application.ProcessMessages;
end;

procedure SendTmctBin(strTmp:string; nCount:integer);

var
strSend :string;
bSend :array of Byte;
i :integer;
begin
strSend := strTmp[1];
for i := 2 to Length(strTmp) do
begin
if strTmp = #$A5 then
strSend := strSend + strTmp + strTmp
else
strSend := strSend + strTmp;
end;

SetLength(bSend, Length(strSend));
Move(PChar(strSend)^, bSend[0], Length(strSend));
for i := 1 to nCount do
begin
Form1.MSComm1.Output := bSend;
TimeDelay(200);
end;
// TimeDelay(400);
end;


procedure SendTmctPkt(tmctPkt :TTmctSubPkt);
var
strPkt :string;
begin
SetString(strPkt, PChar(@tmctPkt), sizeof(TTmctSubPkt));
SendTmctBin(strPkt, 3);
end;

procedure makeandsendFSKdata;
var
i:integer;
tmctSubPkt :TTmctSubPkt;
sockSubPkt :array[0..4] of TSockSubPkt; //一个FSK包中最多可能有5个分支器的开关指令
strCmdInfo :array[0..4] of string;
nPktNum :Integer;
begin
nPktNum := PktSockSub(SendStruct, sockSubPkt, strCmdInfo); //生成Sock包
if nPktNum > 0 then
begin
for i := 0 to nPktNum-1 do
begin
PktTmctSub(sockSubPkt, tmctSubPkt); //转换Sock包为Tmct包
SendTmctPkt(tmctSubPkt); //发送
end;
end;
end;


end.
 
不会吧,这么多,晕
 
kao,成员,长度固定,这都不会?

packet=record
code:byte;
length:shortint;
id:byte;
value:array[1..8] of char;

发送时发送整个record,接收时接收整个record不就完了?
 
定义一个Record就可以了,初学者哦,呵呵
 
后退
顶部