Форум: "Сети";
Текущий архив: 2003.12.16;
Скачать: [xml.tar.bz2];
ВнизБлокирующий tserversocket-не генерятся события отключения клиента Найти похожие ветки
← →
Виноградов Алексей (2003-10-21 20:42) [0]Люди, я с ума сойду ! Есть TServerSocket. Блокирующий. На форме -одна кнопка старта сервера. После подключения клиента для него аккуратно создается поток (видно в Диспетчере Задач), и сервер начинает с помощью метода READ сокетного потока MYSOCKET читать данные (байт) от клиента. Все работает (подключаюсь к серверу телнетом). Если закрыть телнет, то событие OnClientDisconnect не генерируется, и поток клиента остается неубитым. Если подключить n клиентов и потом закрsть, от них останатся n потоков. У меня вопрос - почему не генерятся события отключения,как сделать так, чтобы они генерились, и как узнать, что от сервера отключился клиент ? Вот мой код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ScktComp, StdCtrls, Inifiles, Grids, ComCtrls, ExtCtrls, Buttons;
type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
Start_Server: TBitBtn;
procedure FormActivate(Sender: TObject);
procedure ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
procedure ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Start_ServerClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
{Класс-наследник для процесса каждого клиента}
type
tmyserverthread = class(tserverclientthread)
public
procedure clientexecute; override;
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
application.icon:=form1.icon; application.title:=form1.caption;
start_server.setfocus;
end;
{Это событие возникает, если серверному сокету нужно создать новый поток для соедининия с клиентом}
procedure TForm1.ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
{SocketThread - поток, использующийся единственным соединением}
{Отсылаем приветствие ...}
clientsocket.sendtext ("Hello! Have a nice day!" + #13 + #10);
socketthread:=tmyserverthread.create (true, clientsocket); {Создаем поток}
socketthread.priority:=tpnormal; {Устанавливаем приоритет}
socketthread.resume; {Запускаем поток в работу}
end;
procedure tmyserverthread.clientexecute;
{MySocket - это поток, предоставляющий сервисы, позволяющие читать (писать)в сокетное соединение}
var mysocket : twinsocketstream;
how_many_bytes : word;
one_letter : char;
begin
{Сокетный поток сообщит о таймауте, если через 5 секунд после запуска чтения или записи не будет принято никаких данных}
mysocket:=twinsocketstream.create(clientsocket, 5000);
try
while (not terminated) and (clientsocket.connected) do begin
how_many_bytes:=mysocket.read(one_letter,1);
end;
finally
mysocket.free; {Закрываем поток, предоставляющий сервисы}
if clientsocket.connected = true then clientsocket.close;
end;
end;
{От Сервера отключился Клиент}
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
showmessage("Еще один клиент отключился ...");
end;
{Пользователь запускает сервер}
procedure TForm1.Start_ServerClick(Sender: TObject);
begin
serversocket1.active:=true; {Запускаем сервер}
start_server.enabled:=false;
end;
end.
← →
Reindeer Moss Eater (2003-10-22 08:44) [1]Если закрыть телнет, то событие OnClientDisconnect не генерируется
А с какой стати оно должно генерироваться?
Клиент по тихому закрыл соединение ничего не говоря серверу, сервер в свою очередь никакого обмена с клиентом не ведет.
Откуда серверу узнать что клиента уже нет?
← →
Digitman (2003-10-22 08:56) [2]procedure tmyserverthread.clientexecute;
var mysocket : twinsocketstream;
how_many_bytes : word;
one_letter : char;
begin
try
mysocket:=twinsocketstream.create(clientsocket, 5000);
try
while (not Terminated) and (clientsocket.connected) do
try
how_many_bytes:=mysocket.read(one_letter,1);
// ... обрабатываем успешно полученные данные
except
// при чтении данных возникло исключение, например, по причине дисконнекта по инициативе клиента
// закроем гнездо
clientsocket.Close; // вот при выполнении этого метода и будет сгенерировано синхронное событие OnClientDisconnect()
raise;
end;
finally
mysocket.free;
end;
except
// .. здесь можно вести лог исключений, например, с пом. HandleException
end;
end;
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
// showmessage("Еще один клиент отключился ..."); // недопустимо !!! showmessage() - потоконебезопасный вызов
MsgBox(...); // если так необходимо вывести диал.окно с сообщением, то или MsgBox() или синхронизировать вызов showmessage() с пом. метода Synchronize()
end;
← →
Виноградов Алексей (2003-10-22 09:31) [3]Reindeer Moss Eater © (22.10.03 08:44) [1]
Клиент по тихому закрыл соединение ничего не говоря серверу, сервер в свою очередь никакого обмена с клиентом не ведет.
Как не ведет ?
А чтение в сокетном потоке ?!
← →
Reindeer Moss Eater (2003-10-22 09:37) [4]Как не ведет ?
А чтение в сокетном потоке ?!
Нужно писать. Если сервер попробует писать и не получит квитанцию приема то спустя некоторое время решит что был дисконнект. (точнее это стек протокола решает а не сервер)
← →
Виноградов Алексей (2003-10-22 10:01) [5]Reindeer Moss Eater
Нужно писать. Если сервер попробует писать и не получит квитанцию приема то спустя некоторое время решит что был дисконнект. (точнее это стек протокола решает а не сервер)
То есть я должен писать, а клиент (не телнет, или же телнет, если я успею на клаве нажимать кнопки) - слать квитанцию ? Сама она не генерится ?
← →
Reindeer Moss Eater (2003-10-22 10:05) [6]Сама она не генерится ?
Я же сказал, что этим занимается TCP. Он сообщит экземпляру сервера что нет больше соединения. А сервер сгенерит OnDisconnect.
Либо с клиентской стороны должен прилететь fin пакет, говорящий, что клиент уходит.
← →
Reindeer Moss Eater (2003-10-22 10:06) [7]Либо клиент на прикладном уровне должен сообщить о том, что уходит, а сервер обработать это сообщение
← →
Виноградов Алексей (2003-10-22 10:12) [8]Reindeer Moss Eater © (22.10.03 10:05) [6]
Я же сказал, что этим занимается TCP. Он сообщит экземпляру сервера что нет больше соединения. А сервер сгенерит OnDisconnect.
Да, спасибо, так работает ! Если сервер шлет подключенному клиенту некий символ, а потом закрывается телнет, происходит исключение пр записи ...
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2003.12.16;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.008 c