C
citybug_ch
Unregistered / Unconfirmed
GUEST, unregistred user!
目前我是在一个线程中处理SOCKET的数据接收和数据处理,SOCKET采用的是阻塞式连接。这样带来的问题就是SOCKET发送的数据量一旦很大,很频繁,如果没有及时把SOCKET的接收缓冲区清空,就会覆盖掉前面的数据,就造成数据丢失。
现在想改成一个线程负责接收,一个线程负责处理数据,SOCKET采用非阻塞式。但是有个困惑,就是在线程中如何接收SOCKET的数据,处理线程如何得到接收线程中得到的数据。
目前的代码如下:
unit IntfaceServer;
interface
uses
Classes,ScktComp,SysUtils,Commfunc,Dialogs,MapCommFunc;
//const SEND_TEXT='*W11A00001|NULL^';
type
TIntfaceServer = class(TThread)
private
{ Private declarations }
fInfo: string;
ReturnInfo: TStringList;
ClientSocket: TClientSocket;
protected
procedure Execute;
override;
public
procedure DrawWindow;
constructor Create(fClientSocket: TClientSocket);
end;
implementation
uses Main;
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TIntfaceServer.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
{ TIntfaceServer }
constructor TIntfaceServer.Create(fClientSocket: TClientSocket);
begin
ClientSocket:=fClientSocket;
inherited Create(False);
end;
procedure TIntfaceServer.Execute;
var
Buf: PChar;
sBuf: String;
BufLength: integer;
SendText: String;
i: integer;
begin
{ Place thread code here }
FreeOnTerminate:=True ;
SendText:='*W11' + frmMain.ManageDepID + '|NULL^';
ClientSocket.Socket.SendText(SendText);
i:=0;
while not ClientSocket.Activedo
begin
ClientSocket.Active :=True;
end;
Buf:=nil;
{
Buf:=AllocMem(ClientSocket.Socket.ReceiveLength);
BufLength:=ClientSocket.Socket.ReceiveLength;
ClientSocket.Socket.ReceiveBuf(Buf^,BufLength);
sBuf:=Strpas(buf);
SetLength(sBuf,BufLength);
FreeMem(buf);
while not ClientSocket.Activedo
begin
ClientSocket.Active :=True;
end;
ClientSocket.Socket.SendText(SendText);
}
while truedo
begin
try
i:=i + 1;
sBuf:='';
while (ClientSocket.Socket.ReceiveLength>0)do
begin
try
Buf:=AllocMem(ClientSocket.Socket.ReceiveLength);
BufLength:=ClientSocket.Socket.ReceiveLength;
ClientSocket.Socket.ReceiveBuf(Buf^,BufLength);
sBuf:=Strpas(buf);
setLength(sBuf,BufLength);
finally
FreeMem(Buf);
end;
end;
fInfo:=sBuf;
if (fInfo<>'') and (fInfo<>'*W12RGISTER^') then
begin
WriteLog(fInfo);
ReturnInfo:=InfoList(fInfo);
if ReturnInfo.Count >0 then
begin
Synchronize(DrawWindow);
ReturnInfo.Clear ;
end;
end;
if (i mod 6)=0 then
begin
ClientSocket.Socket.SendText('*Z28^');
i:=0;
end;
sleep(100);
except on e:exceptiondo
WriteLog(e.Message);
end;
end;
end;
procedure TIntfaceServer.DrawWindow;
var
i,j: integer;
return: string;
NextPos: integer;
ShipInfo: TStringList;
AlertInfo: TStringList;
ShipOffSet: TStringList;
ShipTrackInfo: TStringList;
AreaInfo: TStringList;
DelAlert: TStringList;
ListCount: integer;
TerminalNo: string;
SendText: string;
begin
try
NextPos:=0;
ListCount:=ReturnInfo.Count;
while ((NextPos+1)<ListCount)do
begin
if ReturnInfo[NextPos]='W12REGISTER' then
begin
SendText:='*W11' + frmMain.ManageDepID + '|NULL^';
ClientSocket.Socket.SendText(SendText);
NextPos:=NextPos + 1;
end
else
if Copy(ReturnInfo[NextPos],1,3)='W13' then
//初始船舶信息
begin
ShipInfo:=TStringList.Create ;
for j:=0 to 12do
begin
ShipInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
TerminalNo:=CreateShipOfMap(frmMain.Mapx,ShipInfo);
CreateShipTree(frmMain.ManageTree,frmMain.EnterpriseTree,ShipInfo);
AddItemToList(frmMain.NowShipList,ShipInfo,frmMain.PageCtrl3);
AddItemToCmb(ShipInfo,frmMain.cmbShipList);
AddItemToCmb(ShipInfo,frmMain.cmbShipList0);
ShipInfo.Free;
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z22' then
//初始报警信息
begin
AlertInfo:=TStringList.Create ;
for j:=0 to 6do
begin
AlertInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
ShowAlert(AlertInfo,frmMain.AlterInfoList,frmMain.ManageTree,frmMain.PageCtrl3);
end
else
if Copy(ReturnInfo[NextPos],1,3)='W04' then
//新增信息
begin
AlertInfo:=TStringList.Create ;
for j:=0 to 6do
begin
AlertInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
ShowAlert(AlertInfo,frmMain.AlterInfoList,frmMain.ManageTree,frmMain.PageCtrl3);
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z01' then
//船舶位置更新
begin
ShipOffSet:=TStringList.Create ;
for j:=0 to 6do
begin
ShipOffSet.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
ChangeShipOffSet(frmMain.Mapx,ShipOffSet);
ChangeShipOfList(frmMain.NowShipList,ShipOffSet);
end
else
if Copy(ReturnInfo[NextPos],1,3)='W09' then
//限制区域信息
begin
AreaInfo:=TStringList.Create;
for j:=0 to 10do
begin
AreaInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
SetLimiteArea(frmMain.Mapx,AreaInfo);
end
else
if Copy(ReturnInfo[NextPos],1,3)='W10' then
//删除限制区域
begin
DelLimiteArea(frmMain.Mapx,ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end
else
if Copy(ReturnInfo[NextPos],1,3)='W07' then
//删除终端
begin
TerminalNo:=Copy(ReturnInfo[NextPos],4,Length(ReturnInfo[NextPos])-3);
NextPos:=NextPos + 1;
DelShipfromMap(frmMain.Mapx,TerminalNo);
DelShipfromTree(frmMain.ManageTree,TerminalNo);
DelShipFromList(frmMain.NowShipList, TerminalNo);
end
else
if Copy(ReturnInfo[NextPos],1,3)='W08' then
//终端离线
begin
TerminalNo:=Copy(ReturnInfo[NextPos],4,Length(ReturnInfo[NextPos])-3);
NextPos:=NextPos + 1;
UnOnlinefromMap(frmMain.Mapx,TerminalNo);
UnOnlinefromTree(frmMain.ManageTree,TerminalNo);
UnOnlinefromList(frmMain.NowShipList,frmMain.PageCtrl3,TerminalNo);
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z20' then
//船舶轨迹请求后返回值
begin
ShipTrackInfo:=TStringList.Create ;
for j:=0 to 6do
begin
ShipTrackInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
TrackInfoAddList(frmMain.ShipTrackList,ShipTrackInfo,frmMain.PageCtrl3);
frmMain.BtnPlay.Enabled :=True;
frmMain.PageCtrl3.ActivePageIndex :=2;
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z21' then
begin
if Copy(ReturnInfo[NextPos],12,1)='S' then
begin
if frmMain.ShipTrackList.Items.Count>0 then
begin
frmMain.BtnPlay.Enabled :=True;
frmMain.PageCtrl3.ActivePageIndex :=2;
end;
end;
if Copy(ReturnInfo[NextPos],12,1)='F' then
begin
frmMain.BtnPlay.Enabled :=False;
end;
NextPos:=NextPos + 1;
end
else
if Copy(ReturnInfo[NextPos],1,3)='W16' then
//船舶轨迹请求后返回无轨迹消息
begin
NextPos:=NextPos + 1;
WriteLog('无符合条件的轨迹!');
end
else
if Copy(ReturnInfo[NextPos],1,3)='W19' then
//删除警报
begin
DelAlert:=TStringList.Create();
for i:=0 to 1do
begin
DelAlert.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
DelAlertFormList(frmMain.AlterInfoList,DelAlert);
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z29' then
begin
NextPos:=NextPos + 1;
Break;
end
else
begin
break;
end;
end;
except on e:exceptiondo
WriteLog(e.Message);
end;
end;
end.
现在想改成一个线程负责接收,一个线程负责处理数据,SOCKET采用非阻塞式。但是有个困惑,就是在线程中如何接收SOCKET的数据,处理线程如何得到接收线程中得到的数据。
目前的代码如下:
unit IntfaceServer;
interface
uses
Classes,ScktComp,SysUtils,Commfunc,Dialogs,MapCommFunc;
//const SEND_TEXT='*W11A00001|NULL^';
type
TIntfaceServer = class(TThread)
private
{ Private declarations }
fInfo: string;
ReturnInfo: TStringList;
ClientSocket: TClientSocket;
protected
procedure Execute;
override;
public
procedure DrawWindow;
constructor Create(fClientSocket: TClientSocket);
end;
implementation
uses Main;
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TIntfaceServer.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
{ TIntfaceServer }
constructor TIntfaceServer.Create(fClientSocket: TClientSocket);
begin
ClientSocket:=fClientSocket;
inherited Create(False);
end;
procedure TIntfaceServer.Execute;
var
Buf: PChar;
sBuf: String;
BufLength: integer;
SendText: String;
i: integer;
begin
{ Place thread code here }
FreeOnTerminate:=True ;
SendText:='*W11' + frmMain.ManageDepID + '|NULL^';
ClientSocket.Socket.SendText(SendText);
i:=0;
while not ClientSocket.Activedo
begin
ClientSocket.Active :=True;
end;
Buf:=nil;
{
Buf:=AllocMem(ClientSocket.Socket.ReceiveLength);
BufLength:=ClientSocket.Socket.ReceiveLength;
ClientSocket.Socket.ReceiveBuf(Buf^,BufLength);
sBuf:=Strpas(buf);
SetLength(sBuf,BufLength);
FreeMem(buf);
while not ClientSocket.Activedo
begin
ClientSocket.Active :=True;
end;
ClientSocket.Socket.SendText(SendText);
}
while truedo
begin
try
i:=i + 1;
sBuf:='';
while (ClientSocket.Socket.ReceiveLength>0)do
begin
try
Buf:=AllocMem(ClientSocket.Socket.ReceiveLength);
BufLength:=ClientSocket.Socket.ReceiveLength;
ClientSocket.Socket.ReceiveBuf(Buf^,BufLength);
sBuf:=Strpas(buf);
setLength(sBuf,BufLength);
finally
FreeMem(Buf);
end;
end;
fInfo:=sBuf;
if (fInfo<>'') and (fInfo<>'*W12RGISTER^') then
begin
WriteLog(fInfo);
ReturnInfo:=InfoList(fInfo);
if ReturnInfo.Count >0 then
begin
Synchronize(DrawWindow);
ReturnInfo.Clear ;
end;
end;
if (i mod 6)=0 then
begin
ClientSocket.Socket.SendText('*Z28^');
i:=0;
end;
sleep(100);
except on e:exceptiondo
WriteLog(e.Message);
end;
end;
end;
procedure TIntfaceServer.DrawWindow;
var
i,j: integer;
return: string;
NextPos: integer;
ShipInfo: TStringList;
AlertInfo: TStringList;
ShipOffSet: TStringList;
ShipTrackInfo: TStringList;
AreaInfo: TStringList;
DelAlert: TStringList;
ListCount: integer;
TerminalNo: string;
SendText: string;
begin
try
NextPos:=0;
ListCount:=ReturnInfo.Count;
while ((NextPos+1)<ListCount)do
begin
if ReturnInfo[NextPos]='W12REGISTER' then
begin
SendText:='*W11' + frmMain.ManageDepID + '|NULL^';
ClientSocket.Socket.SendText(SendText);
NextPos:=NextPos + 1;
end
else
if Copy(ReturnInfo[NextPos],1,3)='W13' then
//初始船舶信息
begin
ShipInfo:=TStringList.Create ;
for j:=0 to 12do
begin
ShipInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
TerminalNo:=CreateShipOfMap(frmMain.Mapx,ShipInfo);
CreateShipTree(frmMain.ManageTree,frmMain.EnterpriseTree,ShipInfo);
AddItemToList(frmMain.NowShipList,ShipInfo,frmMain.PageCtrl3);
AddItemToCmb(ShipInfo,frmMain.cmbShipList);
AddItemToCmb(ShipInfo,frmMain.cmbShipList0);
ShipInfo.Free;
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z22' then
//初始报警信息
begin
AlertInfo:=TStringList.Create ;
for j:=0 to 6do
begin
AlertInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
ShowAlert(AlertInfo,frmMain.AlterInfoList,frmMain.ManageTree,frmMain.PageCtrl3);
end
else
if Copy(ReturnInfo[NextPos],1,3)='W04' then
//新增信息
begin
AlertInfo:=TStringList.Create ;
for j:=0 to 6do
begin
AlertInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
ShowAlert(AlertInfo,frmMain.AlterInfoList,frmMain.ManageTree,frmMain.PageCtrl3);
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z01' then
//船舶位置更新
begin
ShipOffSet:=TStringList.Create ;
for j:=0 to 6do
begin
ShipOffSet.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
ChangeShipOffSet(frmMain.Mapx,ShipOffSet);
ChangeShipOfList(frmMain.NowShipList,ShipOffSet);
end
else
if Copy(ReturnInfo[NextPos],1,3)='W09' then
//限制区域信息
begin
AreaInfo:=TStringList.Create;
for j:=0 to 10do
begin
AreaInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
SetLimiteArea(frmMain.Mapx,AreaInfo);
end
else
if Copy(ReturnInfo[NextPos],1,3)='W10' then
//删除限制区域
begin
DelLimiteArea(frmMain.Mapx,ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end
else
if Copy(ReturnInfo[NextPos],1,3)='W07' then
//删除终端
begin
TerminalNo:=Copy(ReturnInfo[NextPos],4,Length(ReturnInfo[NextPos])-3);
NextPos:=NextPos + 1;
DelShipfromMap(frmMain.Mapx,TerminalNo);
DelShipfromTree(frmMain.ManageTree,TerminalNo);
DelShipFromList(frmMain.NowShipList, TerminalNo);
end
else
if Copy(ReturnInfo[NextPos],1,3)='W08' then
//终端离线
begin
TerminalNo:=Copy(ReturnInfo[NextPos],4,Length(ReturnInfo[NextPos])-3);
NextPos:=NextPos + 1;
UnOnlinefromMap(frmMain.Mapx,TerminalNo);
UnOnlinefromTree(frmMain.ManageTree,TerminalNo);
UnOnlinefromList(frmMain.NowShipList,frmMain.PageCtrl3,TerminalNo);
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z20' then
//船舶轨迹请求后返回值
begin
ShipTrackInfo:=TStringList.Create ;
for j:=0 to 6do
begin
ShipTrackInfo.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
TrackInfoAddList(frmMain.ShipTrackList,ShipTrackInfo,frmMain.PageCtrl3);
frmMain.BtnPlay.Enabled :=True;
frmMain.PageCtrl3.ActivePageIndex :=2;
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z21' then
begin
if Copy(ReturnInfo[NextPos],12,1)='S' then
begin
if frmMain.ShipTrackList.Items.Count>0 then
begin
frmMain.BtnPlay.Enabled :=True;
frmMain.PageCtrl3.ActivePageIndex :=2;
end;
end;
if Copy(ReturnInfo[NextPos],12,1)='F' then
begin
frmMain.BtnPlay.Enabled :=False;
end;
NextPos:=NextPos + 1;
end
else
if Copy(ReturnInfo[NextPos],1,3)='W16' then
//船舶轨迹请求后返回无轨迹消息
begin
NextPos:=NextPos + 1;
WriteLog('无符合条件的轨迹!');
end
else
if Copy(ReturnInfo[NextPos],1,3)='W19' then
//删除警报
begin
DelAlert:=TStringList.Create();
for i:=0 to 1do
begin
DelAlert.Add(ReturnInfo[NextPos]);
NextPos:=NextPos + 1;
end;
DelAlertFormList(frmMain.AlterInfoList,DelAlert);
end
else
if Copy(ReturnInfo[NextPos],1,3)='Z29' then
begin
NextPos:=NextPos + 1;
Break;
end
else
begin
break;
end;
end;
except on e:exceptiondo
WriteLog(e.Message);
end;
end;
end.