Вот код простейшего сервера:
Код:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Web.Win.Sockets;
type
TForm1 = class(TForm)
TcpServer1: TTcpServer;
procedure TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.TcpServer1Accept(Sender: TObject;
ClientSocket: TCustomIpClient);
var Buf:array of byte;
BufSize:integer;
begin
while ClientSocket.ReceiveBuf(buf) > 0 do
begin
//code...
end;
end;
end.
Исследовал немного поведение TTCPServer.
1. При первом подключении (событие OnAccepr), создается от 1 до 3 потоков в DDServer.ServerSocketThread.ThreadPool.
2. Следующие подключения используют созданные потоки до тех пор, пока количество потоков не станет меньше, чем кол-во подключений. Как только очередному подключению не хватило потоков, кол-во потоков увеличивается на n(в моих тестах n менялось от 2-ух до 3-ех). Пример: при первом подключении создалось 3 потока. 2 и 3 подключение будут использовать 2 и 3 поток. 4-ое подключение спровоцирует увеличение кол-ва потоков с 3 до 3+n.
3. Потоки создаются автоматически. Создавать их вручную в обработчике OnGetThread не обязательно.
4. Поток не уничтожается после разрыва подключения. Освободившийся поток используется новыми подключениями.
5. ClientSocket.ReceiveBuf возвращает число меньше нуля, если подключение разорвано. В противном случае ClientSocket.ReceiveBuf ожидает получения данных. Таким образом код
Код:
while ClientSocket.ReceiveBuf(buf) > 0 do
begin
//code...
end;
будет выполнятся до тех пор, пока клиент не отключится.
6. Вызов методов TCPServer.Close и TCPServer.Destroy не влечет за собой уничтожение клиентских потоков. Они продолжают работать, если клиент не отключился. Если подключение разорвано, поток лишь останавливается (ClientSocketThread.Finished = True), но не уничтожается.
7. TCPClient никак не реагирует на полное отключение сервера(TCPServer1.Destroy + Application.Terminate + ручное уничтожение потоков в цикле TClientSocketThread(TCPServer1.ServerSocketThread. ThreadPool[i]).Free), и продолжает слать данные в пустоту.
Теперь вопросы:
1. Будет ли сервер на основе вышеприведенного кода работать корректно (при условии ручного уничтожения потоков после остановки сервера)?
2. Зачем во многих примерах в обработчике OnGetThread потоки создаются вручную?
3. Как правильно отследить отключение сервера на стороне клиента, не передавая никаких данных от сервера клиенту?