W
weyoung
Unregistered / Unconfirmed
GUEST, unregistred user!
最近在写一个小程序,客户端用Delphi编写,通过Socket与Java编写的服务端通讯。基本上都是一收一发,比如系统登录,客户端将用户名、密码送到服务端,然后等待服务端返回,服务端收到后验证用户名、名称,再将结果返回给客户端。还有一种情况是服务端主动向客户端发请求,客户端在接收到请求后触发相应的事件。
我自己写了一个线程,在线程内接收/发送Socket,代码见mySocketThread.pas。
在主窗体内放一个Indy的TcpClient,然后执行以下代码,程序就能跑起来了:
////////////////////连接服务端/////////////////////////
var myThread: TmySocketThread;
With IdTCPClient1 do
begin
Host := edServerAddr.Text;
Port := StrToInt(edServerPort.Text);
Try
Connect;
except
On E:Exception do
begin
WriteLog('在连接服务器时发生错误,错误消息:' + E.Message);
Exit;
end;
end;
//在这里创建线程,将Socket传进去
myThread := TmySocketThread.Create(False,IdTCPClient1.Socket);
WriteLog('服务器连接成功!');
end;
////////////////////发送/接收数据/////////////////////////
Var
sMsg: String
begin
sMsg := '<message><command>Login</command>...</message>'
if Not myThread.SendData(sMsg) then //发送
begin
ShowMessage('发送失败');
end;
if Not myThread.WaitFor('LoginResp',10,sLocalMsg) then //等待服务器返回结果,如果10秒后服务器还没有返回,则报错。
begin
ShowMessage('服务器没有返回请求结果');
end;
end;
程序能正常执行,发送/接收数据都能正常,只是目前碰到一个问题:有时候(注意只是有时候,不定期的)程序会报错,或者没有报错直接退出了,报错的时候报的错误是“Exception EInvalidPointer in modul QHQL.exe at 0015C469. Invalid pointer operaton”,这种情况一般都发生在我请求非常频繁时,比如我循环100次,不停地向服务器发送登录请求,就会出现这种错误。
请各位DX帮忙解决一下。解决后立即送分。
//////////////////////////////mySocketThread.pas////////////////////////////
unit mySocketThread;
interface
uses
Variants, Graphics, Controls, Forms,Dialogs,
Classes, Windows ,WinSock,ScktComp, Messages, SysUtils,IdAntiFreezeBase, IdAntiFreeze,
IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,IdIOHandlerSocket,SyncObjs;
type
PMyPack = ^TMyPack;
TMyPack = packed record
OrgID: Word; //送端主机编码
OrgPort: Word; //发送端通信端口号
DestID: Word; //接收端主机编码
DestPort: Word; //接收端通信端口号
PackLen: Word; //xml包体的长度
PacketType: Byte; //包类型标识:0x00-单独包,0x01-拆分包的中间包,0x02-拆分包的最后一个包
SubPacketSNO: Byte; //拆分包的包序号,从1开始计数,最大只允许255个包
PacketSNO: Word; //包序号,用于一个包拆分之前的计数
PacketCodeType: Byte; //包编码类型:ucsp为0,client为1,wap为2,web为3,pda为4
Reserved: Byte; //保留,保证包头大小为4的整数倍
end;
type
TmySocketThread = class(TThread)
private
mySocket:TIdIOHandlerSocket;
protected
procedure Execute; override; //读取
public
Constructor Create(CreateSuspended: Boolean;Sock:TIdIOHandlerSocket);
function ProcessCmd(sMsg: string): Boolean; //处理收到的消息
function SendData(sMsg:String):Boolean;virtual; //发送
Function WaitFor(Flag:String;iTimeOut:Integer;Var sLocalMsg:String):Boolean; //等待预期的结果;
end;
implementation
Uses Share,FunPublic,unMain;
{ TSockThread }
constructor TmySocketThread.Create(CreateSuspended: Boolean;
Sock: TIdIOHandlerSocket);
begin
Inherited Create(CreateSuspended);
FreeOnTerminate:=True;
mySocket := Sock;
end;
{destructor TmySocketThread.Destroy;
begin
Try
if Assigned(mySocket) then
begin
mySocket.Free;
mySocket := nil;
end;
Except
end;
inherited;
end;}
procedure TmySocketThread.Execute;
Var
pHeadBuf,pBodyBufChar;
iHeadLen,iBodyLen:Integer;
myPackMyPack;
sMsg:String;
begin
pHeadBuf := nil; pBodyBuf := nil;
iHeadLen := SizeOf(TMyPack);
While (Not Terminated) do
begin
if Not Assigned(mySocket) then
begin
WriteLog('mySocket Not Assigned! App Exit...');
Synchronize(frmMain.ForceExit);
Exit;
end;
if Not mySocket.Connected then
begin
WriteLog('mySocket Not Connected! App Exit...');
Synchronize(frmMain.ForceExit);
end;
GetMem(pHeadBuf,iHeadLen);
Try
Try
mySocket.Recv(pHeadBuf^,iHeadLen); //先读取包头
myPack := PMyPack(pHeadBuf); //解析出包头
iBodyLen := myPack^.PackLen; //得到包体的长度
if iBodyLen > 0 then
begin
//再读取包体
if pBodyBuf = nil then GetMem(pBodyBuf,iBodyLen);
if Not Assigned(pBodyBuf) then
begin
WriteLog('GetMem Error! App Exit...');
Synchronize(frmMain.ForceExit);
end;
mySocket.Recv(pBodyBuf^,iBodyLen);
SetLength(sMsg, iBodyLen);
StrCopy(PChar(sMsg), pBodyBuf);
if not ProcessCmd(sMsg) then
begin
WriteLog('ProcessCmd Error! App Exit...');
Synchronize(frmMain.ForceExit);
end;
end;
Except
On E:Exception do
begin
WriteLog('Socket Read Data Error! ErrorMsg:'+ E.Message + 'App Exit...');
Synchronize(frmMain.ForceExit);
end;
end;
Finally
Try
if Assigned(pHeadBuf) then
begin
FreeMem(pHeadBuf);
pHeadBuf := nil;
end;
if Assigned(pBodyBuf) then
begin
FreeMem(pBodyBuf);
pBodyBuf := nil;
end;
myPack := nil;
Except
end;
end;
//Sleep(100);
//Application.ProcessMessages;
end;
end;
function TmySocketThread.SendData(sMsg: String): Boolean;
Var
sBody:String;
myPack:^TMyPack;
pBufchar;
BodyLen, PackLen:integer;
begin
pBuf := nil;
if Not Assigned(mySocket) then
begin
WriteLog('SendData: mySocket No Assigned! App Exit...');
Synchronize(frmMain.ForceExit);
end;
if Not mySocket.Connected then
begin
WriteLog('SendData: mySocket Not Connected! App Exit...');
Synchronize(frmMain.ForceExit);
end;
sBody := sMsg;
BodyLen := Length(sBody);
PackLen := BodyLen + SizeOf(TMyPack);
New(myPack);
FillMemory(myPack, SizeOf(myPack^), 0);
myPack.OrgID := 1;
myPack.OrgPort := 1;
myPack.DestID := 1;
myPack.DestPort := 1;
myPack.PackLen := BodyLen;
myPack.PacketType := 0;
myPack.SubPacketSNO := 1;
myPack.PacketSNO := 1;
myPack.PacketCodeType := 1;
myPack.Reserved := 0;
if pBuf = nil then GetMem(pBuf, PackLen);
if not Assigned(pBuf) then
begin
WriteLog('GetMem Error! App Exit...');
Synchronize(frmMain.ForceExit);
end;
Try
Try
CopyMemory(pBuf, myPack, SizeOf(TMyPack));
CopyMemory(pBuf+SizeOf(TMyPack),@sBody[1], BodyLen);
mySocket.Send(pBuf^,PackLen);
ReceiveMsg := '';
ReceiveCmd := '';
{$ifDef _COMMLOG}
WriteLog(sMsg);
{$endif}
Result := True;
Except
Result := False;
WriteLog('Send Data Error! App Exit...');
Synchronize(frmMain.ForceExit);
end;
Finally
if Assigned(pBuf) then
begin
FreeMem(pBuf);
pBuf := nil;
end;
myPack := nil;
end;
Sleep(200);
//Application.ProcessMessages;
end;
function TmySocketThread.WaitFor(Flag: String; iTimeOut: Integer;Var sLocalMsg:String): Boolean;
Var
iInit: Integer;
begin
iInit := 0;
sLocalMsg := '';
While iInit < iTimeOut*1000 do
begin
if UPPERCASE(Flag) = UPPERCASE(ReceiveCmd) then
begin
sLocalMsg := ReceiveMsg;
Result := True;
Exit;
end
else
begin
Synchronize(Application.ProcessMessages);
Sleep(100);
end;
iInit := iInit + 100;
end;
Result := False;
end;
function TmySocketThread.ProcessCmd(sMsg: string): Boolean;
Var
sIsResult : String;
begin
Result := True;
sIsResult := GetPackContent('isresult', sMsg);
if uppercase(sIsResult)=uppercase('true') then //服务端根据客户端发出请求返回的响应信息;
begin
ReceiveMsg := sMsg;
ReceiveCmd := GetPackContent('command', sMsg);
{$ifDef _COMMLOG}
WriteLog('Receive From Server Command=' + ReceiveCmd + ',ReceiveMsg=' + ReceiveMsg);
{$endif}
end
else
begin //服务端主动发过来的消息,需要根据消息内容触发相应的事件;
{$ifDef _COMMLOG}
WriteLog('Receive From Server:' + sMsg);
{$endif}
end;
end;
end.
我自己写了一个线程,在线程内接收/发送Socket,代码见mySocketThread.pas。
在主窗体内放一个Indy的TcpClient,然后执行以下代码,程序就能跑起来了:
////////////////////连接服务端/////////////////////////
var myThread: TmySocketThread;
With IdTCPClient1 do
begin
Host := edServerAddr.Text;
Port := StrToInt(edServerPort.Text);
Try
Connect;
except
On E:Exception do
begin
WriteLog('在连接服务器时发生错误,错误消息:' + E.Message);
Exit;
end;
end;
//在这里创建线程,将Socket传进去
myThread := TmySocketThread.Create(False,IdTCPClient1.Socket);
WriteLog('服务器连接成功!');
end;
////////////////////发送/接收数据/////////////////////////
Var
sMsg: String
begin
sMsg := '<message><command>Login</command>...</message>'
if Not myThread.SendData(sMsg) then //发送
begin
ShowMessage('发送失败');
end;
if Not myThread.WaitFor('LoginResp',10,sLocalMsg) then //等待服务器返回结果,如果10秒后服务器还没有返回,则报错。
begin
ShowMessage('服务器没有返回请求结果');
end;
end;
程序能正常执行,发送/接收数据都能正常,只是目前碰到一个问题:有时候(注意只是有时候,不定期的)程序会报错,或者没有报错直接退出了,报错的时候报的错误是“Exception EInvalidPointer in modul QHQL.exe at 0015C469. Invalid pointer operaton”,这种情况一般都发生在我请求非常频繁时,比如我循环100次,不停地向服务器发送登录请求,就会出现这种错误。
请各位DX帮忙解决一下。解决后立即送分。
//////////////////////////////mySocketThread.pas////////////////////////////
unit mySocketThread;
interface
uses
Variants, Graphics, Controls, Forms,Dialogs,
Classes, Windows ,WinSock,ScktComp, Messages, SysUtils,IdAntiFreezeBase, IdAntiFreeze,
IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,IdIOHandlerSocket,SyncObjs;
type
PMyPack = ^TMyPack;
TMyPack = packed record
OrgID: Word; //送端主机编码
OrgPort: Word; //发送端通信端口号
DestID: Word; //接收端主机编码
DestPort: Word; //接收端通信端口号
PackLen: Word; //xml包体的长度
PacketType: Byte; //包类型标识:0x00-单独包,0x01-拆分包的中间包,0x02-拆分包的最后一个包
SubPacketSNO: Byte; //拆分包的包序号,从1开始计数,最大只允许255个包
PacketSNO: Word; //包序号,用于一个包拆分之前的计数
PacketCodeType: Byte; //包编码类型:ucsp为0,client为1,wap为2,web为3,pda为4
Reserved: Byte; //保留,保证包头大小为4的整数倍
end;
type
TmySocketThread = class(TThread)
private
mySocket:TIdIOHandlerSocket;
protected
procedure Execute; override; //读取
public
Constructor Create(CreateSuspended: Boolean;Sock:TIdIOHandlerSocket);
function ProcessCmd(sMsg: string): Boolean; //处理收到的消息
function SendData(sMsg:String):Boolean;virtual; //发送
Function WaitFor(Flag:String;iTimeOut:Integer;Var sLocalMsg:String):Boolean; //等待预期的结果;
end;
implementation
Uses Share,FunPublic,unMain;
{ TSockThread }
constructor TmySocketThread.Create(CreateSuspended: Boolean;
Sock: TIdIOHandlerSocket);
begin
Inherited Create(CreateSuspended);
FreeOnTerminate:=True;
mySocket := Sock;
end;
{destructor TmySocketThread.Destroy;
begin
Try
if Assigned(mySocket) then
begin
mySocket.Free;
mySocket := nil;
end;
Except
end;
inherited;
end;}
procedure TmySocketThread.Execute;
Var
pHeadBuf,pBodyBufChar;
iHeadLen,iBodyLen:Integer;
myPackMyPack;
sMsg:String;
begin
pHeadBuf := nil; pBodyBuf := nil;
iHeadLen := SizeOf(TMyPack);
While (Not Terminated) do
begin
if Not Assigned(mySocket) then
begin
WriteLog('mySocket Not Assigned! App Exit...');
Synchronize(frmMain.ForceExit);
Exit;
end;
if Not mySocket.Connected then
begin
WriteLog('mySocket Not Connected! App Exit...');
Synchronize(frmMain.ForceExit);
end;
GetMem(pHeadBuf,iHeadLen);
Try
Try
mySocket.Recv(pHeadBuf^,iHeadLen); //先读取包头
myPack := PMyPack(pHeadBuf); //解析出包头
iBodyLen := myPack^.PackLen; //得到包体的长度
if iBodyLen > 0 then
begin
//再读取包体
if pBodyBuf = nil then GetMem(pBodyBuf,iBodyLen);
if Not Assigned(pBodyBuf) then
begin
WriteLog('GetMem Error! App Exit...');
Synchronize(frmMain.ForceExit);
end;
mySocket.Recv(pBodyBuf^,iBodyLen);
SetLength(sMsg, iBodyLen);
StrCopy(PChar(sMsg), pBodyBuf);
if not ProcessCmd(sMsg) then
begin
WriteLog('ProcessCmd Error! App Exit...');
Synchronize(frmMain.ForceExit);
end;
end;
Except
On E:Exception do
begin
WriteLog('Socket Read Data Error! ErrorMsg:'+ E.Message + 'App Exit...');
Synchronize(frmMain.ForceExit);
end;
end;
Finally
Try
if Assigned(pHeadBuf) then
begin
FreeMem(pHeadBuf);
pHeadBuf := nil;
end;
if Assigned(pBodyBuf) then
begin
FreeMem(pBodyBuf);
pBodyBuf := nil;
end;
myPack := nil;
Except
end;
end;
//Sleep(100);
//Application.ProcessMessages;
end;
end;
function TmySocketThread.SendData(sMsg: String): Boolean;
Var
sBody:String;
myPack:^TMyPack;
pBufchar;
BodyLen, PackLen:integer;
begin
pBuf := nil;
if Not Assigned(mySocket) then
begin
WriteLog('SendData: mySocket No Assigned! App Exit...');
Synchronize(frmMain.ForceExit);
end;
if Not mySocket.Connected then
begin
WriteLog('SendData: mySocket Not Connected! App Exit...');
Synchronize(frmMain.ForceExit);
end;
sBody := sMsg;
BodyLen := Length(sBody);
PackLen := BodyLen + SizeOf(TMyPack);
New(myPack);
FillMemory(myPack, SizeOf(myPack^), 0);
myPack.OrgID := 1;
myPack.OrgPort := 1;
myPack.DestID := 1;
myPack.DestPort := 1;
myPack.PackLen := BodyLen;
myPack.PacketType := 0;
myPack.SubPacketSNO := 1;
myPack.PacketSNO := 1;
myPack.PacketCodeType := 1;
myPack.Reserved := 0;
if pBuf = nil then GetMem(pBuf, PackLen);
if not Assigned(pBuf) then
begin
WriteLog('GetMem Error! App Exit...');
Synchronize(frmMain.ForceExit);
end;
Try
Try
CopyMemory(pBuf, myPack, SizeOf(TMyPack));
CopyMemory(pBuf+SizeOf(TMyPack),@sBody[1], BodyLen);
mySocket.Send(pBuf^,PackLen);
ReceiveMsg := '';
ReceiveCmd := '';
{$ifDef _COMMLOG}
WriteLog(sMsg);
{$endif}
Result := True;
Except
Result := False;
WriteLog('Send Data Error! App Exit...');
Synchronize(frmMain.ForceExit);
end;
Finally
if Assigned(pBuf) then
begin
FreeMem(pBuf);
pBuf := nil;
end;
myPack := nil;
end;
Sleep(200);
//Application.ProcessMessages;
end;
function TmySocketThread.WaitFor(Flag: String; iTimeOut: Integer;Var sLocalMsg:String): Boolean;
Var
iInit: Integer;
begin
iInit := 0;
sLocalMsg := '';
While iInit < iTimeOut*1000 do
begin
if UPPERCASE(Flag) = UPPERCASE(ReceiveCmd) then
begin
sLocalMsg := ReceiveMsg;
Result := True;
Exit;
end
else
begin
Synchronize(Application.ProcessMessages);
Sleep(100);
end;
iInit := iInit + 100;
end;
Result := False;
end;
function TmySocketThread.ProcessCmd(sMsg: string): Boolean;
Var
sIsResult : String;
begin
Result := True;
sIsResult := GetPackContent('isresult', sMsg);
if uppercase(sIsResult)=uppercase('true') then //服务端根据客户端发出请求返回的响应信息;
begin
ReceiveMsg := sMsg;
ReceiveCmd := GetPackContent('command', sMsg);
{$ifDef _COMMLOG}
WriteLog('Receive From Server Command=' + ReceiveCmd + ',ReceiveMsg=' + ReceiveMsg);
{$endif}
end
else
begin //服务端主动发过来的消息,需要根据消息内容触发相应的事件;
{$ifDef _COMMLOG}
WriteLog('Receive From Server:' + sMsg);
{$endif}
end;
end;
end.