问题:ServerSocket 采用stThreadBlocking方式,如何给指定的客户端发送数据,如何断开指定的Client?具体描述:当有三个客户端连接进来时,服务端可以显示三个连接进来的客户端,此时我如何能关闭指定(或选定)的已连接进来的客户端,或者说我如果才能向指定(或选定)的客户端发送相关的指令。说明:这里不考虑客户端的软件问题,客户端是一个产品。请各位帮忙看看如何可以实现我的那种方法。个人曾想过使用动态数组定义SvrSocketThr : array of TClientThread,可是不知道如何来做,因为客户端连接进来的个数是不定的,今天可能是三个客户端连接进来,明天也许是二十个客户端连接进来。而且在连接过程有可能断线重连。还请各个帮忙看看...
部份的源码如下://在主窗体文件中的部份代码如下:
var //在这里定义窗体的全局变量
frmMain: TfrmMain;
SvrSocketThr :TClientThread;procedure TfrmMain.SSGetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
// Add Client to lvClient compoment
AddUser(ClientSocket);
// Create a new thread for connection
SvrSocketThr := TClientThread.Create(False, ClientSocket);
SocketThread := SvrSocketThr;
end;//线程类中的代码如下:
unit UnitTClientThread;interfaceuses
Classes,SysUtils, Messages,ScktComp;type
TClientThread = class(TServerClientThread)
private
{ Private declarations }
FRecText : PChar;
procedure SetRecText(const Value: PChar);
procedure ShowMmoReceiveResult();
procedure DeleteUser();
procedure DisConnectClientSocket();
procedure ReceiveClientData();
protected
procedure Execute; override;
public
SocketStream: TWinSocketStream;
property RecText:PChar read FRecText write SetRecText;
end;implementationuses UnitMain;procedure TClientThread.Execute;
Var
Data: Array[0..1023] Of char;
Begin
{ Place thread code here }
While (not Terminated) and (ClientSocket.Connected) Do
Try
FreeOnTerminate := True; //线程执行完之后自动关闭并释放线程
SocketStream := TWinSocketStream.Create(ClientSocket,30000);
Try
FillChar(Data, SizeOf(Data), 0);
if SocketStream.WaitForData(30000) then // give the client 30 seconds to start writing
begin
if Terminated then //判断是线断是否被关闭
DisConnectClientSocket //Close Socket
else
begin
if SocketStream.Read(Data, SizeOf(Data)) = 0 then //if can't read in 60 seconds
DisConnectClientSocket //Close Socket
else
ReceiveClientData(); // Receive Data
end;
end
else
DisConnectClientSocket; //Close Socket
Finally
SocketStream.Free;
End;
Except
HandleException;
End;
End;procedure TClientThread.ShowMmoReceiveResult();
begin
frmMain.mmoReceive.Lines.Add(RecText);
end;procedure TClientThread.SetRecText(const Value: PChar);
begin
FRecText := Value;
end;procedure TClientThread.DeleteUser();
var
i:Integer;
begin
for i:=0 to frmMain.lvClient.Items.Count-1 do
begin
if frmMain.lvClient.Items[i].Caption=ClientSocket.RemoteAddress then
begin
frmMain.lvClient.Items.Item[i].delete;
frmMain.mmoReceive.Lines.add('时间:'+datetimetostr(now())+' ===== IP为:'+ ClientSocket.RemoteAddress + ':' + IntToStr(ClientSocket.RemotePort) +' 的客户端与服务器断开连接!');
Break;
end;
end;
end;procedure TClientThread.DisConnectClientSocket();
begin
// If we didn't get any data after xx seconds then close the connection
ClientSocket.SendText('SETUP END'+#13#10);
//Wait a little time to allow sending of text before disconnect
sleep(1);
// Delete Client to lvClient compoment
//Synchronize(DeleteUser);
DeleteUser;
// Close ClientSocket
ClientSocket.Close;
Terminate;
end;procedure TClientThread.ReceiveClientData();
beginend; end.
部份的源码如下://在主窗体文件中的部份代码如下:
var //在这里定义窗体的全局变量
frmMain: TfrmMain;
SvrSocketThr :TClientThread;procedure TfrmMain.SSGetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
// Add Client to lvClient compoment
AddUser(ClientSocket);
// Create a new thread for connection
SvrSocketThr := TClientThread.Create(False, ClientSocket);
SocketThread := SvrSocketThr;
end;//线程类中的代码如下:
unit UnitTClientThread;interfaceuses
Classes,SysUtils, Messages,ScktComp;type
TClientThread = class(TServerClientThread)
private
{ Private declarations }
FRecText : PChar;
procedure SetRecText(const Value: PChar);
procedure ShowMmoReceiveResult();
procedure DeleteUser();
procedure DisConnectClientSocket();
procedure ReceiveClientData();
protected
procedure Execute; override;
public
SocketStream: TWinSocketStream;
property RecText:PChar read FRecText write SetRecText;
end;implementationuses UnitMain;procedure TClientThread.Execute;
Var
Data: Array[0..1023] Of char;
Begin
{ Place thread code here }
While (not Terminated) and (ClientSocket.Connected) Do
Try
FreeOnTerminate := True; //线程执行完之后自动关闭并释放线程
SocketStream := TWinSocketStream.Create(ClientSocket,30000);
Try
FillChar(Data, SizeOf(Data), 0);
if SocketStream.WaitForData(30000) then // give the client 30 seconds to start writing
begin
if Terminated then //判断是线断是否被关闭
DisConnectClientSocket //Close Socket
else
begin
if SocketStream.Read(Data, SizeOf(Data)) = 0 then //if can't read in 60 seconds
DisConnectClientSocket //Close Socket
else
ReceiveClientData(); // Receive Data
end;
end
else
DisConnectClientSocket; //Close Socket
Finally
SocketStream.Free;
End;
Except
HandleException;
End;
End;procedure TClientThread.ShowMmoReceiveResult();
begin
frmMain.mmoReceive.Lines.Add(RecText);
end;procedure TClientThread.SetRecText(const Value: PChar);
begin
FRecText := Value;
end;procedure TClientThread.DeleteUser();
var
i:Integer;
begin
for i:=0 to frmMain.lvClient.Items.Count-1 do
begin
if frmMain.lvClient.Items[i].Caption=ClientSocket.RemoteAddress then
begin
frmMain.lvClient.Items.Item[i].delete;
frmMain.mmoReceive.Lines.add('时间:'+datetimetostr(now())+' ===== IP为:'+ ClientSocket.RemoteAddress + ':' + IntToStr(ClientSocket.RemotePort) +' 的客户端与服务器断开连接!');
Break;
end;
end;
end;procedure TClientThread.DisConnectClientSocket();
begin
// If we didn't get any data after xx seconds then close the connection
ClientSocket.SendText('SETUP END'+#13#10);
//Wait a little time to allow sending of text before disconnect
sleep(1);
// Delete Client to lvClient compoment
//Synchronize(DeleteUser);
DeleteUser;
// Close ClientSocket
ClientSocket.Close;
Terminate;
end;procedure TClientThread.ReceiveClientData();
beginend; end.
解决方案 »
- 为什么我没次都要输入两次!
- dbgrid那个方法可以使记录移到最后的记录?
- 怎样删除选取的多条纪录?用的是cxgrid
- 谁有Rational Rose 2001 windows版本的lisence key啊,帮帮我,
- 有关Mail的发送?请帮我看一我这样为什么发不出去呀,好吗?高分回报!在线!
- 请问怎样获得制定文件类型的图标?
- Delphi6 中使用dbexpress连接MySql数据库的问题!
- 表的全copy
- 征求ado+access时的建议:关于增加、删除、修改等操作到底用什么方法比较好?update、insert into还是post、edit?
- 为什么debug状态下和编译成.exe运行后的结果不一样?(50分送上,谢谢)
- delphi dll 连接数据库出错
- DBLookupcombobox做省、市、县三级联动的问题 问题解决后,另开贴100分酬谢
我根据你说的方法定义了一个类如下:TClientThreadData = record
CSocketThread : TServerClientThread;
ClientSocket : TServerClientWinSocket;
ClientIP : string;
end;
我在这里的指向如下:procedure TfrmMain.SSGetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
// Add Client to lvClient compoment
AddUser(ClientSocket,SocketThread);
// Create a new thread for connection
SvrSocketThr := TClientThread.Create(False, ClientSocket);
SocketThread := SvrSocketThr;
end;procedure TfrmMain.AddUser(ClientSocket : TServerClientWinSocket;SocketThread: TServerClientThread);
var
lvItem:TlistItem;
ClientData : ^TClientThreadData;
i : Integer;
begin
lvItem:=lvClient.Items.add;
lvItem.Caption := ClientSocket.RemoteAddress;
New(ClientData);
ClientData.CSocketThread := SocketThread;
ClientData.ClientSocket := ClientSocket;
ClientData.ClientIP := lvItem.Caption;
lvItem.Data := ClientData;
end;
根据上面的指定工作我进行断开的代码如下:procedure TfrmMain.btnUnConnectClick(Sender: TObject);
var
i : Integer;
Data: Array[0..1023] Of char;
begin
for i:=0 to lvClient.Items.Count-1 do
begin
if TClientThreadData(lvClient.Selected.Data^).ClientIP = lvClient.Items[i].Caption then
begin
//发送断开指令
TClientThreadData(lvClient.Selected.Data^).ClientSocket.SendText('SETUP END'+#13#10);
Sleep(1);
//断开连接
TClientThreadData(lvClient.Selected.Data^).ClientSocket.Close;
//释放线程
TClientThreadData(lvClient.Selected.Data^).CSocketThread.Terminate;
//删除节点
lvClient.Items[i].Delete;
Break;
end;
end;
end;
在断开的代码中执行到TClientThreadData(lvClient.Selected.Data^).ClientSocket.Close语句时提示客户端线程类中读取数据时出错。客户端线程类的语句如下(断开时执行到这句出错):
if SocketStream.Read(Data, SizeOf(Data)) = 0 then //if can't read in 60 seconds
错误的提示信息:
Read error 6, The handle is invalid.
Project GPRSServer.exe raised exception class EThread with message 'Thread Error: The handle is invalid (6)'. Process stopped. Use Step or Run to continue.停止服务的代码如下:procedure TfrmMain.btnStopClick(Sender: TObject);
var
i : integer;
begin
for i:=0 to lvClient.Items.Count-1 do
begin
TClientThreadData(lvClient.Items[i].Data^).ClientSocket.Close;
TClientThreadData(lvClient.Items[i].Data^).CSocketThread.Terminate;
end;
//关闭服务器的端口监听服务
ServerSocket.Active := False;
//清除连接进来的客户端
for i:=0 to lvClient.Items.Count-1 do
lvClient.Items[0].Delete; //删除客户端显示
btnStart.Enabled := True;
btnStop.Enabled := False;
end;