Текущий архив: 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