请高手帮我看看这段程序:(100分)

  • 主题发起人 主题发起人 chimney
  • 开始时间 开始时间
C

chimney

Unregistered / Unconfirmed
GUEST, unregistred user!
TServerSocket和TClientSocket,NoBlocking,

Const
BufMaxSize=4096;
Type
TFrameDataUnit=Array[0..BufMaxSize-SizeOf(Integer)*2-SizeOf(TTranseCode)-1] of Char;
TFrameData=Packed Record//数据包结构
PackLen:Integer;//包长度
PackOrder:Integer;//包序号
TransCode:TTransCode;//数据包内容类型
DataUnit:TFrameDataUnit;//数据包内容
end;
TBuffer=Array[0..BufMaxSize-1] of Char;
TTempDatas=Array[0..4*BufMaxSize-1] of Char;
TTempRecDatas=Record
Length:Integer;//Datas长度
Datas:TTempDatas;
end;
TSocketState=Record
CurRecPacketOrder:Integer;//当前应收到得数据包序号
CurSendPacketOrder:Integer;//当前发送数据包得序号
RecDatasCount:Integer;//RecDatas得长度
TempRecBufFull:Boolean;//TempRecDatas是否已满
RecBufFull:Boolean;//RecDatas是否已满
TempRecDatas:TTempRecDatas;
RecDatas:Array[0..99] of TFrameData;
end;
服务端:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
FrameData:TFrameData;
TempBuf:TBuffer;
RecBuf:TFrameDataUnit;
ReceiveBufReturn,RecPackLen:Integer;
begin
ReceiveBufReturn:=0;
FrameData.DataUnit:=#0;
TempBuf:=#0;
RecBuf:=#0;
if Not Socket.Connected then
Exit;
if (Not TSocketState(Socket.Data^).RecBufFull) and (Not TSocketState(Socket.Data^).TempRecBufFull) then
begin
While ReceiveBufReturn < Socket.ReceiveLength do
begin
Inc(ReceiveBufReturn,Socket.ReceiveBuf(RecBuf,Socket.ReceiveLength));
end;
ArrayCopy(TSocketState(Socket.Data^).TempRecDatas.Datas,
RecBuf,TSocketState(Socket.Data^).TempRecDatas.Length,ReceiveBufReturn);
//ArrayCopy(A,B,C,D):将B中0开始长度D的串复制到A中(起始位置为C)
Inc(TSocketState(Socket.Data^).TempRecDatas.Length,ReceiveBufReturn);
if TSocketState(Socket.Data^).TempRecDatas.Length >= SizeOf(TTempDatas) then
TSocketState(Socket.Data^).TempRecBufFull:=True;
end;
While True do
begin
if TSocketState(Socket.Data^).TempRecDatas.Length < PackLen_Size then
begin
Break;
end;
Move(TSocketState(Socket.Data^).TempRecDatas.Datas,RecPackLen,PackLen_Size);
if TSocketState(Socket.Data^).TempRecDatas.Length < RecPackLen then
begin
Break;
end;
if TSocketState(Socket.Data^).RecDatasCount < High(TSocketState(Socket.Data^).RecDatas)-Low(TSocketState(Socket.Data^).RecDatas)+1 then
begin
TempBuf:=ArrayMoveFrom(TSocketState(Socket.Data^).TempRecDatas.Datas,0,RecPackLen);
//ArrayMoveFrom(A,B,C):将A中的起始位置0长度的串复制出,并删除该部分
Dec(TSocketState(Socket.Data^).TempRecDatas.Length,RecPackLen);
if TSocketState(Socket.Data^).TempRecDatas.Length < SizeOf(TTempDatas) then
TSocketState(Socket.Data^).TempRecBufFull:=False;
Move(TempBuf,FrameData,SizeOf(TempBuf));
TSocketState(Socket.Data^).RecDatas[TSocketState(Socket.Data^).RecDatasCount]:=FrameData;
Inc(TSocketState(Socket.Data^).RecDatasCount,1);
TSocketState(Socket.Data^).RecBufFull:=False;
end
else
begin
TSocketState(Socket.Data^).RecBufFull:=True;
Break;
end;
end;
ProcessData(Socket);
end;
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
i:Integer;
PSocketState:^TSocketState;
begin
if Socket.Connected then
begin
New(PSocketState);
Socket.Data:=PSocketState;
With TSocketState(Socket.Data^) do
begin
CurRecPacketOrder:=0;
CurSendPacketOrder:=0;
RecDatasCount:=0;
TempRecDatas.Length:=0;
TempRecDatas.Datas:=#0;
RecBufFull:=False;
TempRecBufFull:=False;
for i:=Low(RecDatas) to High(RecDatas) do
begin
RecDatas.PackOrder:=-1;
RecDatas.DataUnit:=#0;
end;
end;
end;
end;
客户端:
procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
var
i:Integer;
PSocketState:^TSocketState;
begin
if Socket.Connected then
begin
New(PSocketState);
Socket.Data:=PSocketState;
With TSocketState(Socket.Data^) do
begin
CurRecPacketOrder:=0;
CurSendPacketOrder:=0;
RecDatasCount:=0;
TempRecDatas.Length:=0;
TempRecDatas.Datas:=#0;
RecBufFull:=False;
TempRecBufFull:=False;
for i:=Low(RecDatas) to High(RecDatas) do
begin
RecDatas.PackOrder:=-1;
RecDatas.DataUnit:=#0;
end;
end;
end;
Timer1.Enabled:=True;
end;
procedure TForm1.Timer1Timer(Sender: TObject);//每10m秒发送一个数据包
begin
SendData(ClientSocket1.Socket,TTransCode(2),@Data,SizeOf(Data));
end;
procedure SendData(Socket:TCustomWinSocket;TransCode:TTransCode;Data:Pointer;Size:Integer);
var
SendBufSize,SendLength:Integer;
FrameData:TFrameData;
SendBuf:Array[0..BufMaxSize-1] of Char;
begin
if Socket.Handle = 0 then
Exit;
FillChar(FrameData.DataUnit,SizeOf(FrameData.DataUnit),#0);
FrameData.TransCode:=TransCode;
FrameData.PackOrder:=TSocketState(Socket.Data^).CurSendPacketOrder;
Move(Data^,FrameData.DataUnit,Size);
SendBufSize:=Size+FrameData_HeadSize;
FrameData.PackLen:=SendBufSize;
SendBuf:=#0;
Move(FrameData,SendBuf,SendBufSize);
While (SendBufSize > 0) and (SendLength > 0) do
begin
SendLength:=Socket.SendBuf(SendBuf,SendBufSize);
Dec(SendBufSize,SendLength);
if SendBufSize <=0 then
Break;
end;
Inc(TSocketState(Socket.Data^).CurSendPacketOrder,1);
end;
问题:快速发大数据包(1K/10ms)时或机器繁忙时(本机测试),前面一些包正常,后面的包会丢失。好像是服务端处理不过来,可是我死活查不出原因在哪里。
 
Blocking的模式适合用线程解决,
NonBlocking的模式, 发送或接收一般用OnClientRead, OnRead, OnClientWrite,
OnWrite事件触发, 象这种用Timer触发的, 需要判断ClientSocket是否忙
 
多线程。。
 
后退
顶部