服务器端是启动时就打开socket,并不是为每一个客户端而打开,所以不能随客户端关闭socket而服务器关闭相应的socket。但如果是最后一个客户端关闭socket的话,可以通过OnClientDisconnect事件来检测到如果没有客户端连接服务器,服务器可以断开,下面是一个例子为你参考:procedure TFrmMCS.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); var ClientConnectCount: integer; con: integer; begin ClientConnectCount := ServerSocket1.Socket.ActiveConnections; for con := 0 to ServerSocket1.Socket.ActiveConnections -1 do if Socket = ServerSocket1.Socket.Connections[con] then begin ComboBox1.Items.Delete(con); ClientConnectCount := ClientConnectCount -1; end; StaticText4.Caption := 'Total ' +inttostr(ClientConnectCount) +'Client(s) Connected Chat Server'; if ClientConnectCount < 1 then ServerSocket1.Active := false; end;
韦利谢谢你,我还想问 如果假设已有一个客户端连接上,但在下一个客户端连接前我如何把前一个连接关闭呢, 我用的是阻塞式 连接SOCKET的代码并启动线程的代码如下 procedure TForm1.DataServerSocketGetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread); begin SocketThread := TSendDataThread.Create(False, ClientSocket); end; 谢谢你能给我答复
我该怎么办呢?他已经困扰我多日了。 请各位大侠指点。谢了我用D5写了一个Socket的程序,服务器ServerSocket采用stThreadBlocking模式,在ServerSocket.OnGetThread事件中创建一个自己定义的TServerClientThread: procedure TForm1.ssGetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread); begin SocketThread:= TSocketCli.Create(ClientSocket); //(SocketThread); end;在TSocketCli的ClientExecute方法中执行数据处理(精简): procedure TSocketCli.ClientExecute; var Stream : TWinSocketStream; Buffer : array[0..99] of Char; begin while ((not Terminated) and ClientSocket.Connected) do begin Stream := TWinSocketStream.Create(ClientSocket, 3000); try if Stream.WaitForData(3000) then begin FillChar(Buffer, 100, 0); if Stream.Read(Buffer, 80) <> 0 then begin Str1:= String(Buffer); Synchronize(GetMsg); end; end; except ; end; Stream.Free; except ; end; end; end;但是当客户端执行Close后,while ((not Terminated) and ClientSocket.Connected) do 中的ClientSocket.Connected永远为True,导致服务器的线程不能终止,也就是说服务器不能知道Client已经Close。 我该怎么办呢?他已经困扰我多日了。 请各位大侠指点。谢了
怎么会呢,你的代码是正确的! 通常,如果每个客户端的Socket关闭后,服务器的ServerSocket会自动Free关闭后的客户端的线程,也就是说,客户端的Socket关闭不会触发ServerSocket的OnGetThread事件。 其实你可以在ServerSocket的OnClientDisconnect事件上检查Client是否关闭,你可以参考这段代码: procedure TFrmMCS.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); var ClientConnectCount: integer; con: integer; begin ClientConnectCount := ServerSocket1.Socket.ActiveConnections; with RichEdit3 do begin SelAttributes.Color := clBlack; RichEdit3.Refresh; Lines.Add(Socket.RemoteHost +' is exist the Chating room'); end; for con := 0 to ServerSocket1.Socket.ActiveConnections -1 do if Socket = ServerSocket1.Socket.Connections[con] then begin ComboBox1.Items.Delete(con); ClientConnectCount := ClientConnectCount -1; end; StaticText4.Caption := 'Total ' +inttostr(ClientConnectCount) +'Client(s) Connected Chat Server'; end;
Socket: TCustomWinSocket);
var
ClientConnectCount: integer;
con: integer;
begin
ClientConnectCount := ServerSocket1.Socket.ActiveConnections;
for con := 0 to ServerSocket1.Socket.ActiveConnections -1 do
if Socket = ServerSocket1.Socket.Connections[con] then
begin
ComboBox1.Items.Delete(con);
ClientConnectCount := ClientConnectCount -1;
end;
StaticText4.Caption := 'Total ' +inttostr(ClientConnectCount) +'Client(s) Connected Chat Server';
if ClientConnectCount < 1 then
ServerSocket1.Active := false;
end;
如果假设已有一个客户端连接上,但在下一个客户端连接前我如何把前一个连接关闭呢,
我用的是阻塞式
连接SOCKET的代码并启动线程的代码如下
procedure TForm1.DataServerSocketGetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
SocketThread := TSendDataThread.Create(False, ClientSocket);
end;
谢谢你能给我答复
ServerSocket1ClientDisconnect(Sender:TObject; Socket: TCustomWinSocket);
---------------------------------------------------
主 题: Socket 的多线程编程求救!!! 分不够再加!!
作 者: errorcode (errorcode)
等 级:
信 誉 值: 100
所属论坛: Delphi 网络编程/分布式开发
问题点数: 100
回复次数: 5
发表时间: 2003-04-03 12:46:01
我该怎么办呢?他已经困扰我多日了。
请各位大侠指点。谢了我用D5写了一个Socket的程序,服务器ServerSocket采用stThreadBlocking模式,在ServerSocket.OnGetThread事件中创建一个自己定义的TServerClientThread:
procedure TForm1.ssGetThread(Sender: TObject; ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
SocketThread:= TSocketCli.Create(ClientSocket); //(SocketThread);
end;在TSocketCli的ClientExecute方法中执行数据处理(精简):
procedure TSocketCli.ClientExecute;
var
Stream : TWinSocketStream;
Buffer : array[0..99] of Char;
begin
while ((not Terminated) and ClientSocket.Connected) do
begin
Stream := TWinSocketStream.Create(ClientSocket, 3000);
try
if Stream.WaitForData(3000) then
begin
FillChar(Buffer, 100, 0);
if Stream.Read(Buffer, 80) <> 0 then
begin
Str1:= String(Buffer);
Synchronize(GetMsg);
end;
end;
except
;
end;
Stream.Free;
except
;
end;
end;
end;但是当客户端执行Close后,while ((not Terminated) and ClientSocket.Connected) do 中的ClientSocket.Connected永远为True,导致服务器的线程不能终止,也就是说服务器不能知道Client已经Close。
我该怎么办呢?他已经困扰我多日了。
请各位大侠指点。谢了
回复人: errorcode(errorcode) ( ) 信誉:100 2003-04-03 12:49:00 得分:0
我该怎么办呢?他已经困扰我多日了。
请各位大侠指点。谢了
Top
回复人: errorcode(errorcode) ( ) 信誉:100 2003-04-03 15:08:00 得分:0
高人,帮帮我吧!
Top
回复人: Wally_wu(韦利) ( ) 信誉:101 2003-04-03 17:25:00 得分:0
怎么会呢,你的代码是正确的!
通常,如果每个客户端的Socket关闭后,服务器的ServerSocket会自动Free关闭后的客户端的线程,也就是说,客户端的Socket关闭不会触发ServerSocket的OnGetThread事件。
其实你可以在ServerSocket的OnClientDisconnect事件上检查Client是否关闭,你可以参考这段代码:
procedure TFrmMCS.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var
ClientConnectCount: integer;
con: integer;
begin
ClientConnectCount := ServerSocket1.Socket.ActiveConnections;
with RichEdit3 do
begin
SelAttributes.Color := clBlack;
RichEdit3.Refresh;
Lines.Add(Socket.RemoteHost +' is exist the Chating room');
end;
for con := 0 to ServerSocket1.Socket.ActiveConnections -1 do
if Socket = ServerSocket1.Socket.Connections[con] then
begin
ComboBox1.Items.Delete(con);
ClientConnectCount := ClientConnectCount -1;
end;
StaticText4.Caption := 'Total ' +inttostr(ClientConnectCount) +'Client(s) Connected Chat Server';
end;
Top
回复人: rcy() ( ) 信誉:100 2003-04-03 18:01:00 得分:0
在服務器端的ClientError中:ErrorCode:=0;
這樣服務器端不會死掉了。而且會自動結束和客戶端的連接並復位。
Top
回复人: errorcode(errorcode) ( ) 信誉:100 2003-04-03 18:03:00 得分:0
谢谢,
我已经找到原因了。
是我对SOCKet的编程还不熟悉,我看了TWinSocketStream的源代码。WaitForData其实是调用了IO复用Select。所以只要将Stream.WaitForData(3000) 中的时间值调整到一个很大的值就可以了,这样就能在没有数据传送的时候,线程阻塞在WaitForData,当有数据传送时,WaitForData返回,然后调用Stream.Read读取数据,如果读出数据长度为0,表示客户端关闭,如果数据长度不是0,表示使正常数据传送。