Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 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
9-52045
Livid
2003-06-02 22:54
2003.12.16
kf2->max


3-52110
softmaster
2003-11-23 10:17
2003.12.16
Станность с БД


6-52301
Vladimir Bolotin
2003-10-22 21:27
2003.12.16
поддержка нескольких протоколов (POP3, IMAP,...)


1-52276
ИМХО
2003-12-04 08:41
2003.12.16
Пример рекурсии


3-52099
Чайник
2003-11-24 12:19
2003.12.16
помогите с запросом





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский