Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.30;
Скачать: CL | DM;

Вниз

ClienSocket и ServerSocket   Найти похожие ветки 

 
serko ©   (2006-02-22 14:18) [40]

1. Что такое рекурсия? Это связано с СОКЕТАМИ?
Эта ошибка на Pentium 133 выскакивает сразу при запуске проги, а на Athlon 2000+ ее нет вообще!
2. Но ведь не более 10, а 10 же еще можна?
3. И еще вопрос не в тему: Как в ListView программно выделить все имеющиеся Item?


 
Сергей М. ©   (2006-02-26 11:52) [41]


> Что такое рекурсия?


Вызов подпрограммой самой себя.

пример бесконечной рекурсии и гарантированного получения при этом SO-исключения:

procedure DummyRecursiveProc;
begin
 DummyRecursiveProc;
end;


 
serko ©   (2006-02-28 23:39) [42]

Вот что я заметил: если при Connect или Disconect посылать запрос на имя всех активных пользователей таким образом:

for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText("#N");

то выскакивает выше указанная ошибка, но при этом значение ServerSocket1.Socket.ActiveConnections почему то в два раза больше (по крайней мере при запуске программы, если же сразу повторить запрос то все становится нормуль) чем пользователей от которых пришел ответ т.е. его ИМЯ, а вот в примере приведенном Digitman ©   (14.02.06 14:09) [20], при запуске проги я не от всех получаю их имя, но при повторном запросе все становится номуль, но при этом ошибка Stack overflow вроде не выскакивает!
Ошибки у Клиента все еще выскакивают, при длительном отсутствии соединения!

Что еще подскажите, посоветуете?


 
Сергей М. ©   (2006-03-01 09:00) [43]

Приводи полный код клиента и сервера.
По тем обрывкам что ты привел никаких умозаключений и рекомендаций сделать невозможно.


 
serko ©   (2006-03-02 16:46) [44]

Ну вот вам код СЕРВЕРА:


procedure TForm1.FormCreate(Sender: TObject);
begin
    ListView1.Items.Clear;
    {Устанавливаем порт}
    ServerSocket1.Port := 1001;
    {Запускаем сервер}
    ServerSocket1.Open;
   
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
var  s, to_: string;
    i: Integer;
    Tsr:tSearchrec;
    l: Integer;
    buf: PChar;
    src: TFileStream;
begin
    {сохраняем в s присланную нам строку}
    s := Socket.ReceiveText;
    //Если кто-то прислал нам свое имя
    if Copy(s,1,2) = "#N" then
    begin
       Delete(s,1,2);
       //Поиск компьютеров.
       with ListView1.Items.Add do
       Begin
            Caption:=s;
            SubItems.Add("");
            SubItems.Add("");
            SubItems.Add("");
            SubItems.Add("");
            SubItems.Add("");
            SubItems.Add("");
            for i:=0 to ListView1.Items.Count-1 do
            begin
                ....
             end;
        end;
       Exit;
    end;

    //Если прислали запрос на СПИСОК курсантов
    if Copy(s,1,5) = "#Spis" then
    begin
         s:="#Spis";
         for i:=0 to ListView1.Items.Count-1 do
             S:=s+ListView1.Items.Item[i].SubItems.Strings[1]+":"+
                  ListView1.Items.Item[i].SubItems.Strings[2]+";";
         for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
              ServerSocket1.Socket.Connections[i].SendText(s);
         Exit;
    end;

   
end;

procedure TForm1.ServerSocket1Accept(Sender: TObject;
 Socket: TCustomWinSocket);
var i: Integer;
begin
 {Кто-то присоединился или отсоединился? Нет проблем!
 Запрашиваем у всех юзеров их имена}
 ListView1.Items.Clear;
 with ServerSocket1.Socket do
    for i := 0 to ActiveConnections-1 do
        if Connections[i] <> Socket then
           try
              Connections[i].SendText("#N");
           except
           end;

end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    ServerSocket1.Close;
end;

procedure TForm1.ServerSocket1ClientError(Sender: TObject;
 Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
 var ErrorCode: Integer);
begin
    ErrorCode:=0;
end;


А вот и КЛИЕНТ:


procedure TMainForms.FormCreate(Sender: TObject);
Var t:textfile;
   ScaleWidth, ScaleHeight, ScreenScale : Real;
begin
    Sms:=false;
    {Если соединение уже установлено, то обрываем его}
    if ClientSocket1.Active then
       ClientSocket1.Close;
    {Устанавливаем свойства Host и Port}
    IP:=MainForms.ReadINI("c:\windows\Systems.ini","Server","IP");
    ClientSocket1.Host := ip;
    Val(MainForms.ReadINI("c:\windows\Systems.ini","Server","Port"),Port,code);
    ClientSocket1.Port := Port;
    {Пытаемся соединиться}
    if IP<>"" then ClientSocket1.Open;
         
    KeyPreview := true;
   
end;

procedure TMainForms.ClientSocket1Read(Sender: TObject;
                                       Socket: TCustomWinSocket);
var s,to_: string;

begin
 {присваиваем s полученную от сервера строку}
 s := Socket.ReceiveText;

 {Если нам прислали запрос на наше имя юзера}
 if Copy(s,1,2) = "#N" then
 begin
  {Посылаем ответ}
  Pc:=MainForms.ReadINI("c:\windows\Systems.ini","Dir","Pc");
  Try
    ClientSocket1.Socket.SendText("#N"+pc);
  Except
  End;
  Exit;
 end;
 {Если нам прислали СПИСОК юзеров}
 if Copy(s,1,5) = "#Spis" then
 begin
      Delete(s,1,5);
      i:=1;
      while Spis[i,1]<>"" do
      Begin
           Spis[i,1]:="";
           Spis[i,2]:="";
           i:=i+1;
      End;
      i:=1;
      While Length(s)<>0 do
      Begin
          Spis[i,1]:=Copy(s,1,pos(":",s)-1);
          Delete(s,1,pos(":",s));
          Spis[i,2]:=Copy(s,1,pos(";",s)-1);
          Delete(s,1,pos(";",s));
          i:=i+1;
      End;
      Spis_Flag:=true;
      Exit;
 end;
 {Если нам прислали приватное сообщение (или не нам :) )}
 if Copy(s,1,2) = "#P" then
 begin
      Delete(s,1,2);
      {Выделяем в to_ - кому оно предназначено}
      to_ := Copy(s,1,Pos(";",s)-1);
      Delete(s,1,Pos(";",s));
     if (to_ = pc) then
     begin
          //-----------------------------------------------------------------------------
          MainForms.Memo1.Lines.Insert(0,s);
          //Пришел курсант
          //Выделяем фамилию и группу курсанта
          If Copy(s,1,4) = "#F_G" then
          begin
              Delete(s,1,4);
              MainForms.WriteINI(Put+"Options.ini","User","Fam",Copy(s,1,Pos(";",s)-1));
              Delete(s,1,Pos(";",s));
              MainForms.WriteINI(Put+"Options.ini","User","Group",Copy(s,1,Pos(";",s)-1));
              Delete(s,1,Pos(";",s));
              MainForms.WriteINI(Put+"Options.ini","User","Rezhim",Copy(s,1,Pos(";",s)-1));
              Delete(s,1,Pos(";",s));
              MainForms.WriteINI(Put+"Options.ini","User","Timer",Copy(s,1,Pos(";",s)-1));
              Delete(s,1,Pos(";",s));

              Connekt.Color:=clSkyBlue;
              Fam:=MainForms.ReadINI(put+"Options.ini","User","Fam");
              Gr:=Strtoint(MainForms.ReadINI(put+"Options.ini","User","Group"));
              Rezhim:=MainForms.ReadINI(put+"Options.ini","User","Rezhim");
              Connekt.Label2.Caption:=Fam+#13+"из Группы №"+inttostr(gr);
              Connekt.button1.Visible:=true;
              Connekt.ActiveControl:=Connekt.button1;
          End;
    end;
  Exit;
  end;
end;

procedure TMainForms.ClientSocket1Error(Sender: TObject;
 Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
 var ErrorCode: Integer);
begin
    Errorcode := 0;
    Socket.Close;
    ClientSocket1.Close;
end;

procedure TMainForms.Timer2Timer(Sender: TObject);
begin
    If not ClientSocket1.Active then
       Begin
           ClientSocket1.Open;
       End else
       Begin
            ClientSocket1.Socket.SendText("#P#Bil"+Pc+";"+MainForms.ReadINI(Put+"Options.ini","Bilet","Nom")+";"+
                                        MainForms.ReadINI(Put+"Options.ini","Bilet","Oshib")+";");
       End;
end;



Покажите и подправте места где может зарождаться ошибка!


 
Сергей М. ©   (2006-03-02 16:48) [45]

и ТЗ (полное !!) еще изложи.


 
serko ©   (2006-03-02 17:09) [46]


> и ТЗ (полное !!) еще изложи.


Что за "ТЗ"?


 
Сергей М. ©   (2006-03-03 08:14) [47]

Техническое задание


 
serko ©   (2006-03-03 14:04) [48]

Ааааа ну так бы и раньше сказал!

Задача такая: Основное это управлять КЛИЕНТским компом и приложением. Хотелось бы что это происходило так: КЛИЕНТская прога запускаеся и ждет подключения сервера; если сервер отключился то она снова переходит в режим "Попытки подключения" (не хочется чтобы всегда была запущена СЕРВЕРная прога), у меня при отключенном сервере через некоторое время у клиента выскакивает ошибка! А при запуске серверной программы в LISTVIEW должен появляться список подключенны клиентов, ну и обновляться при подключении\отключении КЛИЕНТа. Вот здесь у меня возникают проблемки, в остальном думаю разберусь!


 
Сергей М. ©   (2006-03-03 14:11) [49]

Это все в локальной сети должно работать ?


 
serko ©   (2006-03-03 23:37) [50]


> Это все в локальной сети должно работать ?


Так точно!


 
Сергей М. ©   (2006-03-06 13:05) [51]

Начнем по порядку ..

> procedure TForm1.ServerSocket1Accept(Sender: TObject;
>  Socket: TCustomWinSocket);
> var i: Integer;
> begin
>  {Кто-то присоединился или отсоединился?


Причем здесь "отсоединился" ?

Accept-событие фиксирует факт подтверждения сервером клиентского запроса на соединение


 
serko ©   (2006-03-06 21:13) [52]

Ну у меня OnAccept и OnDisconnect использует одну процедуру ServerSocket1Accept т.к. коды там одинаковы!


 
Сергей М. ©   (2006-03-07 08:45) [53]

А зачем всякий раз при акцепте или дисконнекте некоего очередного клиента запрашивать у остальных активных клиентов их имена ? Они что, измениться разве могут ?

И зачем чистить ListView при этом ?


 
serko ©   (2006-03-07 23:41) [54]


> Сергей М. ©   (07.03.06 08:45) [53]


Тут я с тобой полностью согласен, я просто сделал как было в статье. Думаеш это разрешит мою проблему?
Тогда в сообщении нужно осылать ИМЯ подключенного или отключенного клиента и потом его добавлять или искать и удалять из ListView?

P.S.Но ведь когда я отсылал те или иные сообщения для ВСЕХ клиентов, тоже глюки были!


 
serko ©   (2006-03-10 22:27) [55]

Сделал!  При запуске ошибка вроде не выскакивает!
Но у КЛИЕНТА ошибки все таки выскакиваю при долгом дисконекте!


 
serko ©   (2006-03-15 01:29) [56]

Вопрос: "У КЛИЕНТА выскакиваю ошибки при долгом дисконекте!" остается в силе!

И еще: "Почему ServerSocket1.SocketActiveConnections иногда бывает больше реального числа самих ClientSocket? Как лишние принудительно отключить?"


 
Сергей М. ©   (2006-03-15 09:24) [57]


> serko ©   (15.03.06 01:29) [56]


> выскакиваю ошибки при долгом дисконекте


Что такое "долгий дисконнект" ? Какие конкретно ошибки ?


> Почему ServerSocket1.SocketActiveConnections иногда бывает
> больше реального числа самих ClientSocket?


Не бывает такого.


 
serko ©   (2006-03-15 12:52) [58]


> Не бывает такого.

Ну если бы не было такого я бы не говорил. Я взял и проверил - кинул Label а на него ServerSocket1.SocketActiveConnections. И почти всегда показывает больше чем есть, только иногда реальное число!


> Что такое "долгий дисконнект" ? Какие конкретно ошибки ?


Читай внимательнее ранние посты.
Ну если я закрыл СЕРВЕР, то клиент находится в Disconnect. Так вот если он в Diconnect находится 1 мин, то все ок а если допустим минут 15, то выскакивают такие ошибки:
"10055 WSAENOBUFS  No buffer space available (Закончились буферы).
Невозможно осуществить операцию с сокетом, поскольку системе не хватает буферного пространства или переполнена очередь. Это означает, что WinSock временно не хватает буфров."

Как их избежать?


 
Сергей М. ©   (2006-03-15 12:57) [59]


> serko ©   (15.03.06 12:52) [58]


> кинул Label а на него ServerSocket1.SocketActiveConnections


В обработчике КАКОГО события сервера ты это делаешь ?
Это же крайне важно ...


> 10055 WSAENOBUFS  


Значит ты неверно обрабатываешь OnError


 
serko ©   (2006-03-15 16:50) [60]


> В обработчике КАКОГО события сервера ты это делаешь ?
> Это же крайне важно ...

Та я токо не делал! и в  Onread  просто по нажатию кнопки, точного числа не добивался!


> Значит ты неверно обрабатываешь OnError


Ну а как надо обрабатывать шоб ошибка не вылазила?
Дело в том шо у меня дома скоко бы не стояла ошибка не вылазит, а на др. компе Win 98 и видимо буфер маленький вот и вылазит такая ошибка!


 
Slavjanin   (2006-03-15 21:10) [61]

Здраствуйте, предложите пожалуйста мне исходник сканера портов, или дайте ссылку. Спасибо


 
Сергей М. ©   (2006-03-16 08:58) [62]


> serko ©   (15.03.06 16:50) [60]


> точного числа не добивался


Ну какая-то закономерность хоть наблюдается ?


> буфер маленький


Суть ошибки (10055 WSAENOBUFS) заключается в слишком большом кол-ве созданных тобой гнезд в клиентском приложении.

Создание нового гнезда происходит всякий раз при выполнении метода TClientSocket.Open, а уничтожение - при выполнении TCustomWinSocket.Close или TCustomWinSocket.Disconnect(хендл гнезда).

Успешный вызов метода TClientSocket.Open (т.е. вызов не приведший к исключению) в неблок.режиме нельзя интерпретировать как факт успешного установления соединения - об этом тебя известит асинхронное событие OnConnect. Начинать прием/передачу следует не ранее чем возникнет это событие.

После вызова TClientSocket.Open вместо события OnConnect может возникнуть событие OnError, говорящее о невозможности установки соединения с сервером по тем или иным причинам. Детальная инф-ция об этой причине передается параметром ErrorCode в обработчик события OnError. Кроме того, событие OnError может возникнуть и позже, уже после события OnConnect, в этом случае оно говорит об ошибках в ходе приема/передачи, например, о неожиданном разрыве соединения со стороны сервера в момент когда была инициирована асинхронная операция чтения/записи.

В любом случае в OnError можно (а в случае ошибки, связанной с невозможностью установления коннекта - обязательно) выполнить метод Socket.Close (Socket в дан.случае - это параметр, переданный в обработчик OnError, а не ClientSocket !), что приведет к безусловному уничтожению созданного ранее при вызове ClientSocket.Open гнезда, если оно еще не уничтожено на этот момент. После этого , если необходимо, можно проанализировать ErrorCode на предмет дальнейших действий и сбросить его в 0, чтобы не "выскочило" окно асинхронного сообщения об ошибке.

Далее по ходу выполнения обработчика OnError, если необходимо повторить попытку коннекта, можно активизировать таймер, в обработчике которого собственно выполнить ClientSocket.Open и тут же деактивировать таймер.


 
serko ©   (2006-03-16 23:53) [63]

Отето ответ и я понимаю! все бы так отвечали!
Спасибо, тебе, попробую сделать правильный вывод!


 
serko ©   (2006-03-17 23:01) [64]

Всеравно ниче не получается!

в таймере пишу:
ClientSocket1.Open;
Timer1.Enabled:=false;

а в OnError:

Errorcode:=0;
Socket.Close;
Timer1.enabled:=true;

и Вот что получается: Когда запустился КЛИЕНТ, произошло соединение и таймер выключился. Но когда я закрываю СЕРВЕР и снова его запускаю то уже connect не происходит (таймер то остановлен, и OnError выполняется).

Как симитировать ошибку? Или мож еще что подскажеш?


 
Сергей М. ©   (2006-03-20 09:08) [65]


> serko ©   (17.03.06 23:01) [64]



> я закрываю СЕРВЕР


Если это сделано штатно (ServerSocket.Close), то у клиента возникнет событие OnDisconnect, в обработчике которого можно запустить таймер.


 
serko ©   (2006-03-20 13:42) [66]

Попробуем еще так! Спасибо!


 
serko ©   (2006-03-21 22:20) [67]

Ты знаеш все пока работает - ПОЛЕТ нормальный!
ЕЩе раз спасибо!


 
Fandros ©   (2006-03-22 19:37) [68]


> Задача такая: Основное это управлять КЛИЕНТским компом и
> приложением. Хотелось бы что это происходило так: КЛИЕНТская
> прога запускаеся и ждет подключения сервера; если сервер
> отключился то она снова переходит в режим "Попытки подключения"
> (не хочется чтобы всегда была запущена СЕРВЕРная прога),
>  у меня при отключенном сервере через некоторое время у
> клиента выскакивает ошибка! А при запуске серверной программы
> в LISTVIEW должен появляться список подключенны клиентов,
>  ну и обновляться при подключении\отключении КЛИЕНТа. Вот
> здесь у меня возникают проблемки, в остальном думаю разберусь!
>


У меня примерно такая-же задача, но клиент должен находиться в сильно подправленной компоненте или в специальном классе! Поэтому использование таймера на форме - не подходит! Как можно заставить переконектиться клиенту (при мягком отрубе сервера)???
обработчик OnDisconnect не игнорирует команду ClientSocket.Open;


 
Сергей М. ©   (2006-03-23 08:10) [69]


> Fandros ©   (22.03.06 19:37) [68]



> использование таймера на форме - не подходит


Ничто не мешает создать таймер "не на форме".
Да и форма собственно ни при чем - твой "сильно подправленный компонент или специальный класс" тоже может не иметь к форме никакого отношения.



Страницы: 1 2 вся ветка

Текущий архив: 2006.07.30;
Скачать: CL | DM;

Наверх




Память: 0.64 MB
Время: 0.034 c
4-1145133480
Volf_555
2006-04-16 00:38
2006.07.30
Как убрать значок программы с панели задач?


2-1152693377
hgd
2006-07-12 12:36
2006.07.30
Polygon


3-1148380618
ASW
2006-05-23 14:36
2006.07.30
Вставка в dbgrid checkbox


3-1148422812
alpha5
2006-05-24 02:20
2006.07.30
Компоненты IB


4-1145132365
Antonyan
2006-04-16 00:19
2006.07.30
Проблема с Async Professional