我根据联通短信协议编写的短信接口程序,共享出来,请大家观摩一下,多提宝贵意见!谢谢!
有兴趣的留下联系方式交流交流!
//*********发送短信的线程
unit UnitClient;interface
uses
Classes,ScktComp,sysutils,sockets,windows,activex,UnitSgipProtocol,winsock,DB,
UnitConstant,adodb;
type
TClientThread = class(TThread)
private
{ Private declarations }
socket:TClientwinsocket;
procedure GenerateSequenceNo(var sn1:longword;var sn2:longword;var sn3:longword);
function SendBind(sStream:TWinsocketStream):boolean;
procedure SendUnBind(sStream:TWinsocketStream);
procedure SendSubmit(sStream:TWinsocketStream;TmpQuery:TADOQuery);
protected
procedure Execute; override; public
constructor creat(socket:TClientwinsocket);
end;implementationuses UnitMain;
var
SN:longword=0;
{ TClientThread }constructor TClientThread.creat(socket: TClientwinsocket);
begin
inherited create(true);
self.socket:=socket;
Resume;
end;procedure TClientThread.Execute;
var
sStream:TWinsocketStream;
TMpQuery:TADOQuery;
begin
FreeOnTerminate:=true;
activex.CoInitialize(nil);
sStream:=TWinSocketStream.Create(self.socket,WaitTimeOut);//连路无数据超时时间,联通的长连接参数还没有
//***********Bind和bind_resp成功之后开始进入线程循环***************//
if not sendbind(sStream) then
begin
sStream.Free;
activex.CoUninitialize;
exit;
end;
//****************线程循环操作**********************//
TMPQuery:=TADOQuery.Create(nil);
TmpQuery.ConnectionString:=SMSCenter;
try
while (not self.Terminated) and (socket.Connected) do
begin
sleep(20);
if GetSubmit(TMpQuery) then//获得要发送数据
begin
Sendsubmit(sStream,TMpQuery) ;//发送短信
end
else
begin
SendUnBind(sStream);//没有则拆除连接
end;
end;
finally
TmpQuery.Free;
clientrunning:=false;
activex.CoUninitialize;
end;
//*********************线程终止********************//
end;procedure TClientThread.GenerateSequenceNo(var sn1, sn2, sn3: longword);
begin
//*************产生消息顺序号,依据SGIP协议
sn1:=htonl(Sequence1);
sn2:=htonl(strtoint(formatdatetime('mmddhhmmss',now())));
if sn=4294967295 then sn:=0
else inc(sn);
sn3:=htonl(sn);
end;
function TClientThread.SendBind(sStream: TWinsocketStream):boolean;
var
b:_Bind;
BR:_Bind_resp;
brsize:integer;
begin
//****************发送Bind包
Result:=false;
fillchar(b,sizeof(b),0);
b.header.MsgLen:=htonl(sizeof(_bind));
b.header.CmdID :=htonl(cmd_bind);
GenerateSequenceNo(b.header.Sequence_number1,b.header.Sequence_number2,
b.header.Sequence_number3);
b.body.login_type:=1;
strpcopy(@b.body.Login_name,Username);
strpcopy(@b.body.login_password,password);
//Move('',b.body.Reserve, )********Bind的reserve字段,保留
if sStream.Write(b,sizeof(b))<>sizeof(b) then
begin
socket.Close;
exit;
end;
brsize:=0;
repeat
if sStream.WaitForData(WaitTimeOut) then
begin
fillchar(br,sizeof(br),0);
brsize:=sStream.Read(br,sizeof(br));
end
else
socket.Close;
until brsize=sizeof(br);
if (br.header.Sequence_number2=b.header.Sequence_number2)
and (br.header.Sequence_number3=b.header.Sequence_number3)
and (br.body.Result=0) then
begin
result:=true;
end;end;
有兴趣的留下联系方式交流交流!
//*********发送短信的线程
unit UnitClient;interface
uses
Classes,ScktComp,sysutils,sockets,windows,activex,UnitSgipProtocol,winsock,DB,
UnitConstant,adodb;
type
TClientThread = class(TThread)
private
{ Private declarations }
socket:TClientwinsocket;
procedure GenerateSequenceNo(var sn1:longword;var sn2:longword;var sn3:longword);
function SendBind(sStream:TWinsocketStream):boolean;
procedure SendUnBind(sStream:TWinsocketStream);
procedure SendSubmit(sStream:TWinsocketStream;TmpQuery:TADOQuery);
protected
procedure Execute; override; public
constructor creat(socket:TClientwinsocket);
end;implementationuses UnitMain;
var
SN:longword=0;
{ TClientThread }constructor TClientThread.creat(socket: TClientwinsocket);
begin
inherited create(true);
self.socket:=socket;
Resume;
end;procedure TClientThread.Execute;
var
sStream:TWinsocketStream;
TMpQuery:TADOQuery;
begin
FreeOnTerminate:=true;
activex.CoInitialize(nil);
sStream:=TWinSocketStream.Create(self.socket,WaitTimeOut);//连路无数据超时时间,联通的长连接参数还没有
//***********Bind和bind_resp成功之后开始进入线程循环***************//
if not sendbind(sStream) then
begin
sStream.Free;
activex.CoUninitialize;
exit;
end;
//****************线程循环操作**********************//
TMPQuery:=TADOQuery.Create(nil);
TmpQuery.ConnectionString:=SMSCenter;
try
while (not self.Terminated) and (socket.Connected) do
begin
sleep(20);
if GetSubmit(TMpQuery) then//获得要发送数据
begin
Sendsubmit(sStream,TMpQuery) ;//发送短信
end
else
begin
SendUnBind(sStream);//没有则拆除连接
end;
end;
finally
TmpQuery.Free;
clientrunning:=false;
activex.CoUninitialize;
end;
//*********************线程终止********************//
end;procedure TClientThread.GenerateSequenceNo(var sn1, sn2, sn3: longword);
begin
//*************产生消息顺序号,依据SGIP协议
sn1:=htonl(Sequence1);
sn2:=htonl(strtoint(formatdatetime('mmddhhmmss',now())));
if sn=4294967295 then sn:=0
else inc(sn);
sn3:=htonl(sn);
end;
function TClientThread.SendBind(sStream: TWinsocketStream):boolean;
var
b:_Bind;
BR:_Bind_resp;
brsize:integer;
begin
//****************发送Bind包
Result:=false;
fillchar(b,sizeof(b),0);
b.header.MsgLen:=htonl(sizeof(_bind));
b.header.CmdID :=htonl(cmd_bind);
GenerateSequenceNo(b.header.Sequence_number1,b.header.Sequence_number2,
b.header.Sequence_number3);
b.body.login_type:=1;
strpcopy(@b.body.Login_name,Username);
strpcopy(@b.body.login_password,password);
//Move('',b.body.Reserve, )********Bind的reserve字段,保留
if sStream.Write(b,sizeof(b))<>sizeof(b) then
begin
socket.Close;
exit;
end;
brsize:=0;
repeat
if sStream.WaitForData(WaitTimeOut) then
begin
fillchar(br,sizeof(br),0);
brsize:=sStream.Read(br,sizeof(br));
end
else
socket.Close;
until brsize=sizeof(br);
if (br.header.Sequence_number2=b.header.Sequence_number2)
and (br.header.Sequence_number3=b.header.Sequence_number3)
and (br.body.Result=0) then
begin
result:=true;
end;end;
解决方案 »
- 如何将16进制字符串转为整数
- 同一系列的软件有公共数据,数据库该如何设计好?
- 调用DLL中的函数.之前问了没有答.
- delphi中 for 语句有没有类试于vb中step的步长?
- Delphi 里有和c++中的fscanf相似的函数吗?
- 我只想把ImageList(或Image)中的图片的一部分画到窗体上,应该怎么样做
- 关于SelectObject()的问题?
- 有一个Image1控件,当鼠标进入时显示一幅图片,鼠标离开时显示另一幅图片。
- 小问题,分数先来先得
- 请问:如何把一个过程赋给一个动态创建的控件的事件(例如要处理动态控件activeimage的click事件具体该怎么做)?
- 多个表数据打印到一张纸上,解决问题在加100分
- 两个查询有什么区别?
procedure TClientThread.SendUnBind(sStream: TWinsocketStream);
var
ub:_Unbind;
ur:_Unbind_Resp;
ursize:integer;//发送unbind 包
begin
fillchar(ub,sizeof(ub),0);
ub.header.MsgLen:=htonl(sizeof(_Unbind));
ub.header.CmdID :=htonl(cmd_UNBIND);
GenerateSequenceNo(ub.header.Sequence_number1,ub.header.Sequence_number2,
ub.header.Sequence_number3);
if sStream.Write(ub,sizeof(ub))<>sizeof(ub) then
begin
socket.Close;
exit;
end;
ursize:=0;
repeat
if sStream.WaitForData(WaitTimeOut) then
begin
fillchar(ur,sizeof(ur),0);
ursize:=sStream.Read(ur,sizeof(ur));
end
else
socket.Close;
until ursize = sizeof(ur);
if (ur.header.Sequence_number2=ub.header.Sequence_number2)
and (ur.header.Sequence_number3=ub.header.Sequence_number3) then
socket.Close; end;
//------------------------------------------------------------------------------发送submit包
procedure TClientThread.SendSubmit(sStream: TWinsocketStream;TmpQuery:TADOQuery);
var
s:_submit;
sr:_Submit_Resp;
submitPackage : Submit_Package;
srsize:integer;
begin
FillChar(s,sizeof(s),0);
s.header.MsgLen:=htonl(sizeof(s)); //因为协议定义的时候将这个写死为160个了, 正常应该是
//将MSGCONTENT定义为动态数组,消息长度应该是SIZEOF数据结构加上
// 动态数组的长度 靠,SIZEOF计算含动态内存分配的数据结构不准
s.header.CmdID :=htonl(cmd_submit);
GenerateSequenceNo(s.header.Sequence_number1,s.header.Sequence_number2,
s.header.Sequence_number3);
//*********构建包体**********//
with submitPackage do
begin
CorpId := UnitConstant.CorpID;
SPNumber := UnitConstant.SPNum;
UserCount := 1;
with submitPackage,TmpQuery do
begin
ChargeNumber := '86'+FieldByName('ChargeNumber').AsString;
UserNumber := FieldByName('UserNumber').AsString;
ServiceType := FieldByName('ServiceType').AsString;
FeeType := FieldByName('FeeType').AsInteger;;
FeeValue := FieldByName('FeeValue').AsString;
GivenValue := FieldByName('GivenValue').AsInteger;
AgentFlag := FieldByName('AgentFlag').AsInteger;
MorelatetoMTFlag := FieldByName('MorelatetoMTFlag').AsInteger;
Priority := FieldByName('Priority').AsInteger;
//ExpireTime :=
//ScheduleTime :=
ReportFlag := FieldByName('ReportFlag').AsInteger;
TP_pid := 0;
TP_udhi := 0;
MessageCoding := FieldByName('MessageCoding').AsInteger;
MessageType := 1;
MessageContent := FieldByName('MessageContent').AsString;
MessageLength := length(MessageContent);
LinkID := FieldByName('LinkID').AsString;
end;
strpcopy(@s.body.SPNumber,spnumber);
strpcopy(@s.body.ChargeNumber,ChargeNumber);
s.body.UserCount:=UserCount;
strpcopy(@s.body.UserNumber,UserNumber);
strpcopy(@s.body.corpid,corpid);
strpcopy(@s.body.ServiceType,ServiceType);
s.body.FeeType := FeeType;
strpcopy(@s.body.FeeValue,FeeValue);
strpcopy(@s.body.givenvalue,inttostr(GivenValue));
s.body.AgentFlag := AgentFlag;
s.body.MorelatetoMTFlag := MorelatetoMTFlag;
s.body.Priority := Priority;
s.body.ReportFlag := ReportFlag;
s.body.TP_pid := TP_pid;
s.body.TP_udhi := TP_udhi;
s.body.MessageCoding := MessageCoding;
s.body.MessageType := MessageType;
s.body.MessageLength:= htonl(MessageLength);
strpcopy(@s.body.MessageContent,MessageContent);
strpcopy(@s.body.LinkID,LinkID);
end;
//**************************************//
if sStream.Write(s,sizeof(s))<>sizeof(s) then
begin
socket.Close;
exit;
end;
srsize:=0;
repeat
if sStream.WaitForData(WaitTimeOut) then
begin
fillchar(sr,sizeof(sr),0);
srsize:=sStream.Read(sr,sizeof(sr));
end
else
socket.Close;
until srsize = sizeof(sr);
if (sr.header.Sequence_number2=s.header.Sequence_number2)
and (sr.header.Sequence_number3=s.header.Sequence_number3)
and (sr.body.Result=0) then
begin
Log_Submit(submitPackage,0);
postmessage(frmmain.Handle,showruninfo,0,integer(pchar('Submit ok')));
end
else
begin
Log_Submit(submitPackage,sr.body.Result);
postmessage(frmmain.Handle,showruninfo,0,integer(pchar('Submit error')));
end;
//DeleteSubmit(TmpQuery);
end;
end.
procedure TFrmMain.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
header:Sgip_header;
cmdid:longword;
begin
//非阻塞式服务端,由客户端的读写操作触发服务器端的事件 FillChar(header,sizeof(header),0);
if socket.ReceiveBuf(header,sizeof(header))=sizeof(header) then
begin
cmdid:= ntohl(header.CmdID);
if cmdid=cmd_bind then handleBind(socket,header)//处理bind
else if cmdid=cmd_DELIVER then handledeliver(socket,header)//处理deliver
else if cmdid=cmd_UNBIND then handleunbind(socket,header)//处理unbind
else if cmdid=cmd_REPORT then handleReport(socket,header)//处理状态报告
else socket.Close; //不正确的命令字,就关掉连接
end; end;procedure TFrmMain.HandleBind(socket: TCustomWinSocket; header: Sgip_header);
var
b:Sgip_Bind ;
Br:_Bind_resp;
begin
fillchar(b,sizeof(b),0);
if socket.ReceiveBuf(b,sizeof(b))<>sizeof(b) then
begin
socket.Close;
exit;
end;
fillchar(br,sizeof(br),0);
br.header.CmdID:=htonl(cmd_BIND_RESP);
br.header.Sequence_number1:=header.Sequence_number1;
br.header.Sequence_number2:=header.Sequence_number2;
br.header.Sequence_number3:=header.Sequence_number3;
br.header.MsgLen:=htonl(sizeof(br));
//用户名密码校验
if (strpas(@b.Login_name)=username) and (strpas(@b.login_password)=password) then
br.body.Result:=0
else br.body.Result:=1;
//move('aaaa',br.body.Reserve,4); 现在bind包中的reserve字段还没使用
if socket.SendBuf(br,sizeof(br))<>sizeof(br) then
socket.Close;
end;procedure TFrmMain.HandleDeliver(socket: TCustomWinSocket;
header: Sgip_header);
var
Dr:_Deliver_Resp;
MsgLen:integer;
D:Sgip_deliver;
begin
fillchar(d,sizeof(d),0);
if socket.ReceiveBuf(d.Deliver1,sizeof(d.Deliver1))<>sizeof(d.Deliver1) then
begin
socket.Close;
exit;
end;
MsgLen:=ntohl(d.Deliver1.MessageLength);
fillchar(d.Deliver2,sizeof(d.Deliver2),0);
if socket.ReceiveBuf(d.Deliver2.MessageContent,MsgLen)<>MsgLen then //加上8是linkid的长度
begin
socket.Close;
exit;
end;
if socket.ReceiveBuf(d.Deliver2.linkid,8)<>8 then
begin
socket.Close;
exit;
end;
//将deliver写到数据库中
SaveDelivery(d); fillchar(dr,sizeof(dr),0);
dr.header.MsgLen:=htonl(sizeof(dr));
dr.header.CmdID:=htonl(cmd_DELIVER_RESP);
dr.header.Sequence_number1:=header.Sequence_number1;
dr.header.Sequence_number2:=header.Sequence_number2;
dr.header.Sequence_number3:=header.Sequence_number3;
dr.body.Result:=0;
//dr.body.Reserve 用户
if socket.SendBuf(dr,sizeof(dr))<>sizeof(dr) then
socket.Close;
end;procedure TFrmMain.HandleUnbind(socket: TCustomWinSocket;
header: Sgip_header);
var
Ur:_Unbind_Resp;
begin
fillchar(ur,sizeof(ur),0);
ur.header.MsgLen:=htonl(sizeof(ur));
ur.header.CmdID:=htonl(cmd_UNBIND_RESP);
ur.header.Sequence_number1:=header.Sequence_number1;
ur.header.Sequence_number2:=header.Sequence_number2;
ur.header.Sequence_number3:=header.Sequence_number3;
if socket.SendBuf(ur,sizeof(ur))<>sizeof(ur) then socket.Close;
end;procedure TFrmMain.HandleReport(socket: TCustomWinSocket;
header: Sgip_header);
var
r:Sgip_Report;
rr:_Report_Resp;
begin
fillchar(r,sizeof(r),0);
if socket.ReceiveBuf(r,sizeof(r))<>sizeof(r) then
begin
socket.Close;
exit;
end;
//将report写入到数据库中
SaveReport(r); FillChar(rr,sizeof(rr),0);
rr.header.MsgLen:=htonl(sizeof(rr));
rr.header.CmdID:=htonl(cmd_REPORT_RESP);
rr.header.Sequence_number1:=header.Sequence_number1;
rr.header.Sequence_number2:=header.Sequence_number2;
rr.header.Sequence_number3:=header.Sequence_number3;
rr.body.Result := 0;
//rr.body.Reserve :=
if socket.SendBuf(rr,sizeof(rr))<>sizeof(rr) then
socket.Close;
end;
function TFrmMain.Unicodetoascii(DeliverStr:Sgip_deliver):string;//将unicode编码文本转换为ascii文本
var
StrLength:integer;
i:integer;
strcode:string;
begin
strLength:=ntohl(deliverstr.Deliver1.MessageLength);
For i := 1 to (strLength div 2) do
begin
strcode:='$'+inttohex(ord(deliverstr.Deliver2.MessageContent[2*i-1]),2)
+inttohex(ord(deliverstr.Deliver2.MessageContent[2*i]),2);
result:=result+widechar(strtoint(strcode));
end;
end;
if socket.ReceiveBuf(header,sizeof(header))=sizeof(header) then
这条件的ELSE怎么不处理呢?
socket.close的
呵呵程序已经通过中国联通测试了
晕,也没人来顶顶
楼主的程序在不太高流量下会运行很好的.
不过反正联通短信流量都有限制..比如一秒20条什么的..
所以也不用考虑太多..
DelphiBird (爱你等于爱自己) ,halfdream(哈欠) 还有对短信感兴趣D同仁,咱们交个朋友,多交流交流,共同进步。
我在天津, QQ:37727640
呵呵那两个是我封装数据协议的单元
大家着协议写就行了,我也贴出来TO halfdream(哈欠):
请问你有什么好的解决方案,我这个程序的弱点大概主要是:
1.比如每对消息和消息的resp之间应该做异步处理的;建立队列机制;但是现在还没想到既能异步又能安全的解决方案;我想重开线程来做异步处理,又怕socket数据读取的时候发生冲突;比如新开线程去读RESP,保证队列不朝过联通规定的32个;但是会出现几个线程同时读SOCKET的情况;
2.另外发送和接受应该有缓存排序机制的,这个目前我实现在数据库中了;
3.还有就是长连接,因为联通不支持长连接,虽然它号称支持长连接,但是我找遍协议也没发现连路检测的消息;所以我在处理完所有submit命令还是会拆除连接的
uses
SysUtils;
const
cmd_BIND:longword =$1; //对客户端验证
cmd_BIND_RESP:longword =$80000001; //服务端返回验证请求
cmd_UNBIND:longword =$2; //断开连接
cmd_UNBIND_RESP:longword =$80000002; //返回断开连接状态
cmd_SUBMIT:longword =$3; //向SMG提交MT短消息
cmd_SUBMIT_RESP:longword =$80000003; //返回SP提交MT短消息状态
cmd_DELIVER:longword =$4; //SMG向SP发送一条MO短消息
cmd_DELIVER_RESP:longword =$80000004; //返回SMG状态
cmd_REPORT:longword =$5; //向SP发送一条先前的submit命令的当前状态
cmd_REPORT_RESP:longword =$80000005; //响应SMG状态
type
//***************消息头
Sgip_header = packed record
MsgLen:longword;
CmdID:longword;
Sequence_number1,
Sequence_number2,
Sequence_number3:longword;
end;
//***************Bind命令
Sgip_Bind = packed record
login_type:byte;
Login_name : packed array[1..16] of char;
login_password : packed array[1..16] of char;
Reserve : packed array[1..8] of char;
end;
//*****************Bind_Resp命令
Sgip_Bind_Resp = packed record
Result:byte; //Bind执行命令是否成功。0:执行成功其它:错误码
Reserve:packed array[1..8] of char;
end;
Sgip_UnBind = packed record
end;
Sgip_UnBind_Resp = packed record
end;
//*****************Unbind命令
Sgip_Submit=packed record
SPNumber:packed array[1..21] of char;
ChargeNumber:packed array[1..21] of char;
UserCount:byte;
UserNumber :packed array[1..21] of char;
CorpId :packed array[1..5] of char;
ServiceType:packed array[1..10] of char;
FeeType:byte;
FeeValue:packed array[1..6] of char;
GivenValue:packed array[1..6] of char;
AgentFlag:byte;
MorelatetoMTFlag:byte;
Priority:byte;
ExpireTime:packed array[1..16] of char;
ScheduleTime:packed array[1..16] of char;
ReportFlag:byte;
TP_pid:byte;
TP_udhi:byte;
MessageCoding:byte;
MessageType:byte;
MessageLength:longword;
MessageContent:packed array[1..160] of char; //Message Length
LinkID:packed array[1..8] of char;
end;
//***********************Submit_Resp命令
Sgip_Submit_Resp = packed record
Result:byte;
Reserve:packed array[1..8] of char;
end;
//***********************Deliver命令
Sgip_Deliver1 = packed record
UserNumber:packed array[1..21] of char;
SPNumber:packed array[1..21] of char;
TP_pid:byte;
TP_udhi:byte;
MessageCoding:byte;
MessageLength:longword;
end;
sgip_deliver2 = packed record
MessageContent :packed array[1..255] of char; //Message Length
LinkID:packed array[1..8] of char;
end;
Sgip_Deliver = packed record
Deliver1:Sgip_Deliver1;
Deliver2:Sgip_Deliver2;
end;
//*********************Deliver_Resp命令
Sgip_Deliver_Resp = packed record
Result:byte;
Reserve:packed array[1..8] of char;
end;
//**********************Report命令
Sgip_Report = packed record
SubmitSequenceNumber1:longword;
SubmitSequenceNumber2:longword;
SubmitSequenceNumber3:longword;
ReportType:byte;
UserNumber:packed array[1..21] of char;
State:byte;
ErrorCode:byte;
Reserve:packed array[1..8] of char;
end;
//**********************Report_Resp命令
Sgip_Report_Resp=packed record
Result:byte;
Reserve:packed array[1..8] of char;
end;
//------------------------------------------------------------------------------
_Bind = packed record
header:Sgip_header;
body:Sgip_Bind;
end;
_Bind_resp = packed record
header:Sgip_header;
body:Sgip_Bind_Resp;
end; _Unbind = packed record
header:Sgip_header;
body:Sgip_UnBind;
end;
_Unbind_Resp = packed record
header:Sgip_header;
body:Sgip_UnBind_Resp;
end; _Deliver = packed record
header:Sgip_header;
body:Sgip_Deliver;
end;
_Deliver_Resp = packed record
header:Sgip_header;
body:Sgip_Deliver_Resp;
end; _Submit = packed record
header:Sgip_header;
body:Sgip_Submit;
end;
_Submit_Resp = packed record
header:Sgip_header;
body:Sgip_Submit_Resp;
end;
_Report = packed record
header:Sgip_header;
body:Sgip_Report;
end;
_Report_Resp = packed record
header:Sgip_header;
body:Sgip_Report_Resp;
end;
implementationend.
begin
//*************产生消息顺序号,依据SGIP协议
sn1:=htonl(Sequence1);
sn2:=htonl(strtoint(formatdatetime('mmddhhmmss',now())));
if sn=4294967295 then sn:=0
else inc(sn);
sn3:=htonl(sn);
end;1:
>>if sn=4294967295 then sn:=0
4294967295 = INFINITE,不要直接写数字,看不懂
很多网关会有不同的最大值,所以,你得设个最大值: FMaxSequence
还有,不要用StrToInt, StrToIntDef,习惯问题2:
不要用SysUtils.StrPCopy
自已写个: StrCopy(const Src: string; Buf: PChar; BufSize);
TCP包字段的越界问题永远要考虑.3:
写两函数:
SendPacket(Socket: TCustomWInSOcket; var Buf; BufSize: Integer): Boolean;
RecvPacket(Socket: TCustomWInSOcket; var Buf; BufSize: Integer): Boolean;
SGIP, CMPP, CNGP, SMGP, SMPP每个协议都规定了包头第一个字节是包长度,为什么不封装一个收包和发包过程? (记住考虑Socket ErrCode = 10035的错误)4:
包结构既然很大部分都一样,为什么不考虑统一做一个处理包头结构,如:
InitPacket(buf: PChar; Len, Cmd....)5:
包长度既然用来用去,为什么不写个对象来封装这个包6:
活动try finally
而不是:
CoInitialize(nil);
if False then
begin
CoUninitialize;
Exit;
end;7:
不要怕对常量的定义
SGIP_OK = 0, SGIP_FAILED = 1,没人觉得会浪费8:
SOCKET滑行窗口实现很简单:Count := 10;
while Count > 0 do
begin
SubmtData(GetSubmtData);
WriteSubmitToBuffer; // Write Submit to Buffer写在SubmitData中,在socket.Send之前
Dec(Count);
end;while True do
begin
if not ReceivePacket(Packet) then break;
InterpreterPacket(Packet);
end;function InterpreterPacket(Packet);
begin
if Packet.Cmd = SGIP_SUBMIT_RESP then
DeleteSubmitWithSequenceId(Packet.SeqNo)
else
DoOther;
end;9:
SGIP的ActiveTest命令字为:
SGIP_KEEPALIVE_VALUE = $10000001;
SGIP_KEEPALIVE_RESP_VALUE = $10000010;10:
我的费话太多:D
你可以根据这些建议,找出你代码中重复代码,一步步重构它们..要作异步处理仅重开线程不好的..
SOCKET作异步有异步选择IO,和异步事件IO等.
TClientSocket和TServerSocket的非阻塞方式是用异步选择IO实现,
只是这种方式需要通过WINDOWS消息支持,也就是说它只工作在主线程.其实在主线程也不太坏,只是可能并发能力差了点.异步事件IO,是靠WINDOWS的EVENT支持实现的,DELPHI的TSocketconnection是用了它..
你可以看看那些源码.里面包含一些技巧..
地不到通知了
http://220.194.153.26:8089/noah/