Серверное Приложение С Tcpserver

Тема в разделе "Delphi - Сети", создана пользователем borpavlenko, 20 дек 2012.

  1. borpavlenko

    borpavlenko New Member

    Регистрация:
    10 июл 2008
    Сообщения:
    2
    Симпатии:
    0
    Здравствуйте, товарищи!

    Пишу серверное многопользовательское приложение.
    За основу взял пример отсюда http://softengines.ru/showthread.php?t=6863
    На всякий случай продублирую код
    Код (Text):

    type
    TMyClientThread = class(TClientSocketThread)
    private
    FCmd: String;
    FData: String;
    protected
    procedure SyncProc; override;
    end;

    procedure TMyClientThread. SyncProc;
    begin
    if FCmd = ‘CLR’ then
    Form1.ListBox2.Clear
    else
    if FCmd =’TXT’ then
    Form1.ListBox2.Items.Add(FData)
    else
    if FCmd = ‘BYE’ then begin
    Terminate;
    Form1.ListBox1.Items.Add(‘Отключился:’+ ClientSocket.RemoteHost);
    end;
    else
    if FCmd = ‘’ then
    Form1.ListBox1.Items.Add(‘Подключился:’+ ClientSocket.RemoteHost);
    end;

    procedure TForm1.RormCreate(Sender: TObject);
    begin
    Caption:=’Сервер’;
    ListBox1.Clear;
    ListBox2.Clear;
    TcpServer1.LocalPort :=’5050’;
    TcpServer1.Active := ‘True’;
    end;
    procedure TForm1. TcpServer1GetThread(Sender: TObject;
    var ClientSocketThread: TClientSocketThread);
    begin
    ClientSocketThread:=
    TMyClientThread.Create(TcpServer1.ServerSocketThread);
    end;
    procedure TForm1. TcpServer1Accept(Sender: TObject;
    ClientSocket:TCustomIpClient);
    begin
    with (ClientSocket.GetThreadObject as TMyClientThread) do begin
    FCmd:=’’;
    ExecuteSyncProc;
    while not Terminated do begin
    FCmd:= ClientSocket.Receiveln;
    if FCmd = ‘TXT’ then
    FData:= ClientSocket.Receiveln;
    if FCmd <> ‘’ then
    ExecuteSyncProc;
    end;
    end;
    end;
    Итак, сам компонент TCPSocket ожидает подключения в отдельном потоке. При подключении клиента создается клиентский поток, в котором уже выполняется общение с клиентом.

    Суть-вопросы.

    1. Для закрытия соединения при получении команды 'BYE' используется вызов Terminate, который (как я понимаю) убивает клиентский поток. Правильно ли это? Не надо ли вызывать методы Disconnect, Close класса ClientSocket ? Проясните этот момент, кто знает.

    2. Для меня сейчас более актуально разобраться в следующем:
    если клиент не отправляет команду 'BYE', а просто вырубается, рвется соединение и т.п., то цикл while в TcpServer1Accept начинает бесконечно гонять по кругу. Т.е. получается, что сокет висит в каком-то неопределенном состоянии (пробовал определять эту ситуацию проверкой ClientSocket.Connected, но ничего не вышло, остается TRUE), пользовательский поток гоняет по кругу цикл, который уже ничего не сделает, хотя должен умереть.
    Как правильно отследить и обработать эту ситуацию?

    В общем, научите правильно закрывать соединения со стороны сервера во всех случаях. Заранее спасибо.
     
  2. sinkopa

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    Не надо путать понятия Socket и поток обслуживающий Socket
    Вызов Terminate всего лишь устанавливает свойство Terminated в True, тем самым сообщая потоку что ему пора вывалиться их цикла ожидания и "тихо", корректно помереть.
    Сам поток ничего не знает ни про Disconnect, Close ни про класс ClientSocket. Ему "по барабану" в результате какого действия ему скажут "умри"... :)
    Конечно он будет крутиться... откуда бы ему узнать что какой то там клиент, (на другом конце света), не просто задумался на время... а взял и помер не успев положить трубку на рычаг телефона?... :)
    Вы правильно поняли суть проблемы... тем самым вплотную приблизились к пониманию понятия "протокол сетевого обмена информацией"... :)
    В той реализации сетевого общения которую Вы представили, я лично вижу только одну возможность.
    1. Вы устанавливаете (добавляете к существующим) комаду типа 'Я ЕЩЕ ЖИВ' и с оговоренной (с сервером) периодичностью отправляете ее серверу, в то время пока сокет ваш не занят другими данными...
    2. Сервер (зная максимально допустимое время простоя клиента) самостоятельно вырубает клиентский поток если за указанный промежуток времени от клиента не поступило никаких команд.
    Код (Delphi):
        while not Terminated do
    begin
    FCmd:= ClientSocket.Receiveln;

    if (FCmd = 'WaitMe') then
    ClientIDLCount := 1000000
    else if (FCmd = '') then
    begin
    Dec(ClientIDLCount);
    if (ClientIDLCount < 1) then
    FCmd:= 'BYE';
    end;

    if (FCmd = 'TXT') then
    FData:= ClientSocket.Receiveln;

    if (FCmd <> '') then
    ExecuteSyncProc;
    end;
    Где-то так в общем... Ну или организуйте встречный сокет канал, чтобы сервер сам мог спрашивать у клиента : "эй парень? ты жив еще?" :)
    Давайте я Вам лучше ссылку дам http://delphiworld.narod.ru/_all_articles_.html
    Читайте раздел Сокеты (27 интересных примеров и статей)
     
Загрузка...
Похожие Темы - Серверное Приложение Tcpserver
  1. Studentische
    Ответов:
    0
    Просмотров:
    1.467
  2. ClassicRock
    Ответов:
    0
    Просмотров:
    1.374
  3. Lenoriya
    Ответов:
    5
    Просмотров:
    2.729
  4. erhe
    Ответов:
    18
    Просмотров:
    3.003
  5. dimat
    Ответов:
    4
    Просмотров:
    3.799

Поделиться этой страницей