![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
ClienSocket и ServerSocket [D6, WinXP]
serko © (2006-01-27 00:03:00)Вот у меня одна прога типа сервер а другая клиент!
Естественно что Клиент подключается к уже запущенному Серверу.
Но вот если запустить клиента когда сервер еще не запущен то выскакивает ошибка "Asynchronous socket error 10061".
Как сделать так чтобы Клиент подключался до тех пор пока не запустится Сервер, без вывода этой ошибки?
Сергей М. (2006-03-03 14:11:00) [21]Это все в локальнойсети должно работать ?
serko (2006-03-03 14:04:00) [22]Ааааа ну так бы и раньше сказал!
Задача такая: Основное это управлять КЛИЕНТским компом и приложением. Хотелось бы что это происходило так: КЛИЕНТская прога запускаеся и ждет подключения сервера; если сервер отключился то она снова переходит в режим "Попытки подключения" (не хочется чтобы всегда была запущена СЕРВЕРная прога), у меня при отключенном сервере через некоторое время у клиента выскакивает ошибка! А при запуске серверной программы в LISTVIEW должен появляться список подключенны клиентов, ну и обновляться при подключении\отключении КЛИЕНТа. Вот здесь у меня возникают проблемки, в остальном думаю разберусь!
Сергей М. (2006-03-03 08:14:00) [23]Техническое задание
serko (2006-03-02 17:09:00) [24]
> и ТЗ (полное !!) еще изложи.
Что за "ТЗ"?
Сергей М. (2006-03-02 16:48:00) [25]и ТЗ (полное !!) еще изложи.
serko (2006-03-02 16:46:00) [26]Ну вот вам код СЕРВЕРА:
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-01 09:00:00) [27]Приводи полный код клиента и сервера.
По тем обрывкам что ты привел никаких умозаключений и рекомендаций сделать невозможно.
serko (2006-02-28 23:39:00) [28]Вот что я заметил: если при 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-02-26 11:52:00) [29]
> Что такое рекурсия?
Вызов подпрограммой самой себя.
пример бесконечной рекурсии и гарантированного получения при этом SO-исключения:
procedure DummyRecursiveProc;
begin
DummyRecursiveProc;
end;
serko (2006-02-22 14:18:00) [30]1. Что такое рекурсия? Это связано с СОКЕТАМИ?
Эта ошибка на Pentium 133 выскакивает сразу при запуске проги, а на Athlon 2000+ ее нет вообще!
2. Но ведь не более 10, а 10 же еще можна?
3. И еще вопрос не в тему: Как в ListView программно выделить все имеющиеся Item?
Сергей М. (2006-02-22 11:09:00) [31]
> Что означает ошибка Stack Overflow?
Переполнение стека.
Где-то ты допустил бесконечную рекурсию.
atruhin (2006-02-22 06:42:00) [32]1. у тебя ошибки в программе.
2. в windows есть ограничение на кол-во одновременных подключений, не более 10, этого ограничения нет у серверных систем.
serko (2006-02-21 22:32:00) [33]Что нет вариантов?
А у меня еще вопросы появились:
1. Что означает ошибка Stack Overflow? Я так подозреваю она происходит при выполнении кода:
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText('#N');
Суть его такова, что отсылается запрос на NiCkName КЛИЕНТА ввиде "#N", и потом уже каждый клиент присылает СЕРВЕРУ свой NickName. На нормальных компах эта ошибка не выскакивает, но почемуто приходит 2 ответа на запрос в виде "#NUser_1#NUser_1". Помогите разобраться!
2. И еще на КЛИЕНТ у меня стоит на 10 компах с 98 виндой, так вот на 9 прога запускается нормально, а на 10-ом при попытке открыть Сокет пишет "Can't create new socket". Что это может быть? Может в винде надо чето настроить?
Ребя помогите в этом разобраться!
serko (2006-02-18 21:09:00) [34]Вот сегодня оставил клиентскую прогу на более менее нормальном компе, так при выключеной серверной программе, сутки простояла и все ок! А на слабых компах глючит!
Что посоветуете? Можно ли как то буфер чистить?
Digitmn (2006-02-17 12:30:00) [35]
> Клиент должен пытаться подключиться к серверу, до успешного
> соеденения
Фактом успешного соединения является факт возникновения события OnConnect
serko (2006-02-16 16:54:00) [36]И вот я снова тут, в своих тапках! :)
Мне все же хочется сделать по-моему т.е. с ctNonBlocking.
У меня клиентские программы стоят на слабеньких компах с WIN 98, по сравнению с сервером WIN XP - Celeron 2000 Mhz.
Наверное поэтому на клиентах через некоторое время и выскакивает ошибка типа:
"10055 WSAENOBUFS No buffer space available (Закончились буферы).
Невозможно осуществить операцию с сокетом, поскольку системе не хватает буферного пространства или переполнена очередь. Это означает, что WinSock временно не хватает буфров. Это не должно вызывать проблем, если не продолжается долгое время."
Как я уже говорил у меня в таймере происходит:
If not ClientSocket1.Active then
ClientSocket1.Open;
Try
Begin
ClientSocket1.Socket.SendText('Text');
End;
Except
End;
Может как-то можна очищать этот буфер? На более мощных компах, за такой же промежуток времени ошибка не выскакивает!
Задача все таже! Клиент должен пытаться подключиться к серверу, до успешного соеденения. Вслучае разрыва связи все должно повторяться! И что самое главное БЕЗ выскакивающих ОШИБОК!
Digitman (2006-02-14 17:31:00) [37]
> Ну ладно хватит на сегодня тебя муч ать
Приходите еще).. Желательно - со своими тапками
serko (2006-02-14 16:52:00) [38]Ну ладно хватит на сегодня тебя мучать, ты мне и так много чего разъяснил и за это тебе большое спасибо! Ну если что, то я вернусь!
Digitman (2006-02-14 16:42:00) [39]
> 1. В каких событиях обрабатывать эти примеры для СЕРВЕРА
> и КЛИЕНТА, ведь в таком случае OnRead и OnClientRead не
> срабатывают?
А что , разве на событиях свет клином сошелся ? Без событий уже никак ?
> 2. Как узнать что удаленная машина отправила текст, чтобы
> я смог вызвать ПРИЕМ?
Если TCustomWinSocket.ReceiveLength() вернула результат больше 0, это говорит о непустом буфере приема
serko (2006-02-14 16:37:00) [40]Ну всеравно появляются вопросы:
1. В каких событиях обрабатывать эти примеры для СЕРВЕРА и КЛИЕНТА, ведь в таком случае OnRead и OnClientRead не срабатывают?
2. Как узнать что удаленная машина отправила текст, чтобы я смог вызвать ПРИЕМ?