我在Delphi 5下基于TCP/IP用ClientSocket和ServerSocket进行非阻塞通信,客户端发出数据请求,服务器接到请求后在库里查询记录并返回(一条记录为一包,大小在140个字节左右,通常为几千个包,服务器端已经固定,我无法修改,只能修改客户端),但我的客户端接收到的数据与我所期望的并不一致(表现为不稳定,有时处理成功有时失败),不知道究竟是服务器发包不对还是我的处理代码有问题,请大虾们帮我看看如下的代码:
type
TPackHeader =packed record
len : longint; //包的总长度,为包头和包体长度总和
morepkt : char; //1:有后续包 0:无
sequence : longint; //包序号
errorcode : smallint; //返回码
end;
type
TPackage=packed record
PackHeader : TPackHeader; //包头
datatrans : array[0..0] of char; //传送内容,从datatrans开始, end; //实际使用时取其地址作为指针使用
TPPackage=^TPackage;
const PackHeadSize=11;
var
ErrorInfo:string;
templist:TStringList;
procedure Tfrm_Progress.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
DataTrans:array[0..2048-1] of char;
Data:string;
PackHeader:TPackHeader;
tempSize:integer;
BodySize:integer;
P:Pointer;
RecLen:Integer;
begin
while true do //去掉while循环还是有问题
begin
if socket.ReceiveLength<=PackHeadSize then continue;//去掉该句还是有问题
fillchar(PackHeader,sizeof(PackHeader),#0);
tempSize:=0;
while tempSize<PackHeadSize do
begin
P:=pointer(integer(@PackHeader)+tempSize);
RecLen:=socket.ReceiveBuf(p^,PackHeadSize-tempSize);
if RecLen>0 then
tempSize:=tempSize+RecLen
else
delay4(0,0,0,1);
end;
DataTrans:=#0;
BodySize:=PackHeader.len-PackHeadSize;
tempSize:=0;
while tempSize<BodySize do
begin
RecLen:=socket.ReceiveBuf(DataTrans[tempSize],BodySize-tempSize);
if RecLen > 0 then
tempSize:=tempSize+RecLen
else
delay4(0,0,0,1);
end;
Data:=copy(PChar(@DataTrans),0,PackHeader.len-PackHeadSize);
//DataTrans数组中的有效数据无#0,最后一个字符才为#0,故copy该句应该没问题
if PackHeader.errorcode<>0 then //如果查询出错
begin
ErrorInfo:='Error!'; //有时程序从这里退出,说明接到的包数据乱了,??
Exit;
end;
templist.Add(Data);
if (PackHeader.morepkt = '0') then
begin
ErrorInfo:='Complete!';
ProcessData();//数据包全部接收完,开始进行处理,提取各字段写入数据库操作
exit;
end;
end; //延时函数
procedure Tfrm_Progress.Delay4(Hour,Min,Sec,MSec:word);
var timeout:TDateTime;
begin
timeout:=now+encodeTime(Hour,Min,Sec,MSec);
While now<timeout do
Application.ProcessMessages;
end;
分全给了,请高手指点是否代码可行?如果不,请给出一个类似处理的例子(有服务器端代码更好),另外,有什么办法可以一边接收一边ProcessData()处理数据而保证不会出错?很急很急,万万分感谢!!!
type
TPackHeader =packed record
len : longint; //包的总长度,为包头和包体长度总和
morepkt : char; //1:有后续包 0:无
sequence : longint; //包序号
errorcode : smallint; //返回码
end;
type
TPackage=packed record
PackHeader : TPackHeader; //包头
datatrans : array[0..0] of char; //传送内容,从datatrans开始, end; //实际使用时取其地址作为指针使用
TPPackage=^TPackage;
const PackHeadSize=11;
var
ErrorInfo:string;
templist:TStringList;
procedure Tfrm_Progress.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
DataTrans:array[0..2048-1] of char;
Data:string;
PackHeader:TPackHeader;
tempSize:integer;
BodySize:integer;
P:Pointer;
RecLen:Integer;
begin
while true do //去掉while循环还是有问题
begin
if socket.ReceiveLength<=PackHeadSize then continue;//去掉该句还是有问题
fillchar(PackHeader,sizeof(PackHeader),#0);
tempSize:=0;
while tempSize<PackHeadSize do
begin
P:=pointer(integer(@PackHeader)+tempSize);
RecLen:=socket.ReceiveBuf(p^,PackHeadSize-tempSize);
if RecLen>0 then
tempSize:=tempSize+RecLen
else
delay4(0,0,0,1);
end;
DataTrans:=#0;
BodySize:=PackHeader.len-PackHeadSize;
tempSize:=0;
while tempSize<BodySize do
begin
RecLen:=socket.ReceiveBuf(DataTrans[tempSize],BodySize-tempSize);
if RecLen > 0 then
tempSize:=tempSize+RecLen
else
delay4(0,0,0,1);
end;
Data:=copy(PChar(@DataTrans),0,PackHeader.len-PackHeadSize);
//DataTrans数组中的有效数据无#0,最后一个字符才为#0,故copy该句应该没问题
if PackHeader.errorcode<>0 then //如果查询出错
begin
ErrorInfo:='Error!'; //有时程序从这里退出,说明接到的包数据乱了,??
Exit;
end;
templist.Add(Data);
if (PackHeader.morepkt = '0') then
begin
ErrorInfo:='Complete!';
ProcessData();//数据包全部接收完,开始进行处理,提取各字段写入数据库操作
exit;
end;
end; //延时函数
procedure Tfrm_Progress.Delay4(Hour,Min,Sec,MSec:word);
var timeout:TDateTime;
begin
timeout:=now+encodeTime(Hour,Min,Sec,MSec);
While now<timeout do
Application.ProcessMessages;
end;
分全给了,请高手指点是否代码可行?如果不,请给出一个类似处理的例子(有服务器端代码更好),另外,有什么办法可以一边接收一边ProcessData()处理数据而保证不会出错?很急很急,万万分感谢!!!
谢谢!
,我想问一个我的问题如下:(问题现象是:为什么接收到的数据与发出去的不符,而且还出现内存访问错误(使用TSeverSocket与TClientSocket))定义如下数据结构:type Block=record Num:integer;//块在块列表的序号
ScrRect:iScrRect;//对应的屏幕矩形
UserName:string;//计算此块的计算机名
UserIP:string;//计算此块的计算机IP
UserSocketID:integer;//计算此块的Socket连接句柄
DispatchedTime:string;//被分配出去的时间
CompletetTime:string;//计算完成的时间
end;
type CalPara=record//定义发送给Client端的计算参数的消息数据结构
cMin:ePoint;
sDCX:extended; //复数实部变化步长
sDCY:extended;//复数虚部变化步长
iMaxLoopNum:integer;//最大迭代次数
iBoarder:extended; //吸引子
end;
type AllCalInfo=record
BlockInfo:Block;
CurCalPara:CalPara;
end;发送端:
function getAllCalInfo(var ACI:AllCalInfo):boolean;begin
if BlockNum<>-1 then
begin ACI.BlockInfo:=Blocks[BlockNum]; ACI.CurCalPara.cMin.X:=StrToFloat(FrmServer.LedtcXMin.Text);
ACI.CurCalPara.cMin.Y:=StrToFloat(FrmServer.LedtcYMin.Text); ACI.CurCalPara.sDCX:= (strToFloat(FrmServer.LedtcXMax.Text)-StrToFloat(FrmServer.LedtcXMin.Text))/FrmServer.SpWidth.Value;
ACI.CurCalPara.sDCY:=
(StrToFloat(FrmServer.LedtcYMax.Text)-StrToFloat(FrmServer.LedtcYMin.Text))/FrmServer.SpHeight.Value;
ACI.CurCalPara.iMaxLoopNum:=FrmServer.SpNum.Value;
ACI.CurCalPara.iBoarder:=FrmServer.SpXYZ.Value;
result:=true;
end else result:=false;end;
var Info:^AllCalInfo;
begin
GetMem(Info,SizeOf(blocks[0]));
if getAllCalInfo(Info^) then
begin
SendNum:=Socket.SendBuf(Info,sizeOf(AllCalInfo));
end else showmessage('发生意外,不能取得计算信息!')end;Client端:var
re:pchar;
CalInfo:^AllCalInfo;
sbuf:string;
relong:integer;
begin
// ShowMessage(inttostr(Sizeof(AllCalInfo))); reLong:=Socket.ReceiveLength;
GetMem(CalInfo,reLong);
ZeroMemory(CalInfo,reLong);
Socket.ReceiveBuf(CalInfo,reLong); if CalInfo^.BlockInfo.Num >-1 then//在这里查看CalInfo^的数据,发现与发送的不同
begin
Echo.Lines.Add('得到任务...');
end;
end;
end;
在线等待!!!
所以你在服务器里一定要有判断,并把重新把两个包串起来.得到你要的数据结构