Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2010.12.12;
Скачать: [xml.tar.bz2];

Вниз

TServerSocket, как узнать IP клиента при подключении.   Найти похожие ветки 

 
ZV ©   (2010-09-09 18:21) [0]

Хочу в событии ServerSocketClientConnect определить адрес подключившегося клиента
Сверить его с базой разрешенных IP и если его там нет то отключить
Я так понимаю что для этого надо использовать  функции
ServerSocket.Socket.Connections[].RemonteAddress;
ServerSocket.Socket.Connections[].Close;
Но не пойму как . По идеи в событии ServerSocketClientConnect  я должен узнать  номер подключения  а  уже по номеру подключения  при помощи ServerSocket.Socket.Connections[].RemonteAddress;  определить IP.
И ещё мне не понятно какому типу  переменной присваивать значение функции ServerSocket.Socket.Connections[].RemonteAddress;   ведь IP адрес имеет такой формат 172.17.200.2; ?


 
ZV ©   (2010-09-09 18:43) [1]

Сделал так
Label10.Caption:=ServerSocket1.Socket.Connections[ServerSocket1.Socket.Act iveConnections-1].RemoteAddress;

В Label10 выводиться IP подключившегося клиента правда клиент только один и будет ли это работать когда подключется ещё один не знаю, теперь не пойму как мне работать с этим IP . мне нужна последняя цифра IP для проверки с базой как её извлечь ?


 
Anatoly Podgoretsky ©   (2010-09-09 19:31) [2]

> ZV  (09.09.2010 18:21:00)  [0]

Не ремонтный адрес, а удаленый.
Это строковый формат адреса, соответсвенно тип нужен STRING
Также есть и вариант с числом, соответсвенно тип Cardinal


 
Anatoly Podgoretsky ©   (2010-09-09 19:37) [3]

> ZV  (09.09.2010 18:43:01)  [1]

Зачем же так сложно, когда в обработчик передается Socket

Label10.Caption := Socket.RemoteAddress;

ExtractFileExt


Точку вначале сам удалишь?
Но ты зря не работаешь с цифровым представлением, там все проще.


 
ZV ©   (2010-09-09 19:50) [4]


> Не ремонтный адрес, а удаленый.

Не понял
> Это строковый формат адреса, соответсвенно тип нужен STRING
> Также есть и вариант с числом, соответсвенно тип Cardinal


Я не пойму как это 172.17.200.2 преобразовать в число и провести сравнение базы с последней цифрой IP то есть 2 .


 
ZV ©   (2010-09-09 19:51) [5]


> Но ты зря не работаешь с цифровым представлением, там все
> проще.

Да если бы я знал как


 
ZV ©   (2010-09-09 20:05) [6]


> Label10.Caption := Socket.RemoteAddress;

Да так проще. С определением IP, разобрался. А вот как работать с полученным  IP не пойму


 
Anatoly Podgoretsky ©   (2010-09-09 20:05) [7]

> ZV  (09.09.2010 19:50:04)  [4]

Не надо ничего преобразовывать RemoteAdr уже число, и можно обращаться к
любому байту через приведение LongRec().Bytes[3]
Cледующая ошибка, не надо в базе хранить последний октет ИП, храни полность
или строковое или цифровое представление, цифровое лучше, быстрее и размер
меньше в три раза.

remonte - ремонтный, remote - удаленый

Ты два раза повторил ремонтный, это означает, что это не опечатка.


 
ZV ©   (2010-09-09 20:30) [8]


> Ты два раза повторил ремонтный, это означает, что это не
> опечатка.

Угу
> LongRec().Bytes[3]

не пойму как
> Cледующая ошибка, не надо в базе хранить последний октет
> ИП, храни полность
> или строковое или цифровое представление, цифровое лучше,
>  быстрее и размер
> меньше в три раза.


А время на проверку уйдет больше, то ли  один байт сверит а так весь IP


 
Anatoly Podgoretsky ©   (2010-09-09 20:56) [9]

Хранение полностью цифровых значение благоприятно сказывается на скорости. Сравнение Integer наиболее быстрая операция.


 
ZV ©   (2010-09-09 21:04) [10]

У меня ступор с IP  не пойму как этим  LongRec().Bytes[3] воспользоваться
Весь IP я проверять все таки не буду в моей ситуации это не нужно .
Поэтому для контроля мне нужно последнее число в ip адресе
a:Byte;
a:= Socket.RemoteAddress;

как сделать так чтобы в переменной а оказалось последнее число в IP адреса?


 
Сергей М. ©   (2010-09-09 21:33) [11]


> ZV ©   (09.09.10 21:04) [10]


Ну оттяпай шматок строки после последней точки в адресе, преобразуй его в Integer - вот тебе и "последнее число"


 
FireMan_Alexey ©   (2010-09-09 21:38) [12]

Анатолий имел ввиду :)
var
 Address:Array [0..3] of Byte;
Begin
Integer(Address):=Socket.RemoteAddr.sin_addr.S_addr;
If Address[?]=2 Then "Format C:"
...
End;


 
ZV ©   (2010-09-09 21:40) [13]


> Ну оттяпай шматок строки после последней точки в адресе,
>  преобразуй его в Integer - вот тебе и "последнее число"
>

Не фига себе метод а проще не как, других вариантов нет?


 
Сергей М. ©   (2010-09-09 21:45) [14]


> а проще не как, других вариантов нет?


Тебе шашечки или ехать, я не пойму ?)


 
ZV ©   (2010-09-09 21:49) [15]

Я думал может есть более изящные методы, ну раз так тогда  оттяпаем шматок, преобразуем ,сравним.


 
FireMan_Alexey ©   (2010-09-09 21:50) [16]

>ZV ©

Читаем пост [12] :)
Проще не будет :)

Под вопросом я имел ввиду № октека, который тебе нужен для сравнения
Или вообще сравнивай весь адрес, как сказал Дядя Толя :)
А он плохого не посоветует :)


 
ZV ©   (2010-09-09 21:52) [17]


> оттяпаем шматок, преобразуем ,сравним.

Я боюсь что пока  это все проделаю ещё с десяток клиентов подключатся


 
Anatoly Podgoretsky ©   (2010-09-09 21:55) [18]

> ZV  (09.09.2010 21:04:10)  [10]

Я же написал для двух вариантов адресов.


 
ZV ©   (2010-09-09 21:56) [19]


> Читаем пост [12] :)
> Проще не будет :)
>

Я пока не сравниваю а пытаюсь вывести последнее число , но выводит в Label значение  0
var

 Address:Array [0..3] of Byte;
begin
{

Integer(Address):=Socket.RemoteAddr.sin_addr.S_addr;
 Label11.Caption := IntToStr(Address[3]);

Что я делаю не так


 
FireMan_Alexey ©   (2010-09-09 21:58) [20]

>ZV ©

Прости за откровенность, но ты сюда пришел для чего?
Я тебе дал самый оптимальный код без строковых преобразований, чего тебе еще нужно? Даже просто скопировать лень?


 
FireMan_Alexey ©   (2010-09-09 22:01) [21]

Если ты конектишся  на 127.0.0.1 но обратный адрес всегда будет 0.0.0.0 ...
По моему так, попробуй конектиться на свой реальный Адрес


 
Anatoly Podgoretsky ©   (2010-09-09 22:04) [22]

> FireMan_Alexey  (09.09.2010 21:38:12)  [12]

Немного не так, а так

  Address: Cardinal;
Begin
  Address := Socket.RemoteAddr;
  If LongRec(Address).Bytes[3] = 2 Then "Format C:"
 ...
End;

Но сама идея работать только с последней частью, мне очень не нравится,
усложнение и замедление
Гораздо лучше

if Address  = Field.Value Then "Format C:"


 
Anatoly Podgoretsky ©   (2010-09-09 22:05) [23]

> ZV  (09.09.2010 21:49:15)  [15]

А те решения, что я предложил, разве не изящны?


 
FireMan_Alexey ©   (2010-09-09 22:05) [24]

Слушай дядю Толю :) он хорошее советует :)


 
Anatoly Podgoretsky ©   (2010-09-09 22:07) [25]

> FireMan_Alexey  (09.09.2010 21:50:16)  [16]

У меня статистика Интернета построена на целых адресах, никакого выделения
октетов, только для индикации, а индикация основана на LongRec.Bytes как
самое простое и удобное.


 
ZV ©   (2010-09-09 22:11) [26]

Если переменную сменить на   Cardinal то компилятор ругается  E2010 Incompatible types: "Cardinal" and "sockaddr_in"


 
FireMan_Alexey ©   (2010-09-09 22:12) [27]


> Anatoly Podgoretsky ©   (09.09.10 22:07) [25]

Так я наоборот Вас поддерживаю... :)
А ТС просил побайтную, ну я и написал побайтную :)


 
FireMan_Alexey ©   (2010-09-09 22:13) [28]

Попробуй так :)
Address: Cardinal;
Begin
 Address := Cardinal(Socket.RemoteAddr);


 
Anatoly Podgoretsky ©   (2010-09-09 22:14) [29]

Разве вариант с ExtractFileExt не изящен, а использование LongRec не изящно


 
FireMan_Alexey ©   (2010-09-09 22:15) [30]

Прости забыл...

Address := Cardinal(Socket.RemoteAddr.sin_addr);


 
ZV ©   (2010-09-09 22:17) [31]


> У меня статистика Интернета построена на целых адресах,
> никакого выделения
> октетов, только для индикации, а индикация основана на LongRec.
> Bytes как
> самое простое и удобное.
>

Да я не против проверять весь IP , даже за (так все таки будет надежней), но я не пойму  как создать массив этих адресов, что делать с этими гребаными точками , и как потом сравнить полученный адрес с массивом


 
Anatoly Podgoretsky ©   (2010-09-09 22:19) [32]


> Если переменную сменить на   Cardinal то компилятор ругается
>  E2010 Incompatible types: "Cardinal" and "sockaddr_in"

Сделай или приведение, или смени тип переменной. Только откуда взялся "sockaddr_in", у меня такого нет.


 
ZV ©   (2010-09-09 22:27) [33]

сделал так
Address: Cardinal;
begin
{

 Label10.Caption := Socket.RemoteAddress;
Address := Cardinal(Socket.RemoteAddr.sin_addr);

label11.Caption:= IntToStr(LongRec(Address).Bytes[3]) ;

В результате в label10 выводится IP 172.17.228.200 (соответствует действительности)
в label11 опять 0


 
Anatoly Podgoretsky ©   (2010-09-09 22:46) [34]

> FireMan_Alexey  (09.09.2010 22:13:28)  [28]

Можно указать Address: LongInt;
Но все равно придется в других местах приводить к Cardinal, а ведь адрес по
сути это Cardinal - 32 битное беззнаковое.
Я же говорил, что я писал аналогичное по сути приложение, чтл не выбери, но
все равно придется приводить.
Мой опыт подсказал, что меньше всего проблем при реальном Cardinal, и в
модулях s_addr указан как U_Long, что и есть cardinal, но Борланд описал как
LongInt, не удивительно учитывая беды Борланда с cardinal, им потребовалось
много лет, что бы понять, что Cardinal это 32 битное беззнаковое, а он у них
побывал и Integer, и LongInt, только потом стал 32 битным беззнаковым. :-).


 
Anatoly Podgoretsky ©   (2010-09-09 22:47) [35]

> FireMan_Alexey  (09.09.2010 22:15:30)  [30]

Address := Cardinal(Socket.RemoteAddr.sin_addr.S_Addr);


 
Anatoly Podgoretsky ©   (2010-09-09 22:49) [36]

> ZV  (09.09.2010 22:17:31)  [31]

У цифровых нет никаких точек!!!
Причем тут массив я не пойму.
Сравнение делается операцией =
Хоть с переменной, хоть с константой, хоть с массивом, хоть с записью,
поскольку сранение ведется не с ними, а со значениями.


 
Anatoly Podgoretsky ©   (2010-09-09 22:50) [37]

> ZV  (09.09.2010 22:27:33)  [33]

Тут слишком много написано ерунды.


 
ZV ©   (2010-09-09 23:08) [38]

А воз и нынче там, вот это жесть. 3 часа прошло а как извлечь значения из Socket.RemoteAddress; так и не ясно


 
Anatoly Podgoretsky ©   (2010-09-09 23:20) [39]

> ZV  (09.09.2010 23:08:38)  [38]

Ладно не хочешь ExtractFileExt, то тогда LastDelimiter + Copy


 
ZV ©   (2010-09-13 23:20) [40]

Спасибо всем за советы.  Я все таки сделал определение всего IP а не последней цифры , преобразовать в цифровой  формат  Socket.RemoteAddress; у меня не получилось  по этому создал массив IP адресов в текстовом формате и сравниваю. В принципе работает меня пока устраивает , но возникла  новая проблема. В обработчике ServerSocket1ClientConnect   я определи IP клиента , выяснил, что клиенту доступ закрыт, теперь мне нужно его отключить через ServerSocket.Socket.Connections[?].Close . А   как я его отключу? Я знаю только его  IP но не номер его подключения. Как узнать какой номер подключения ?


 
ZV ©   (2010-09-14 12:20) [41]

Пока мне не ответили на вопрос я сделал так. При коннекте клиента  в поле клиента о номере подключения записываю  
NomberConnection:=ServerSocket1.Socket.ActiveConnections
И вроде  получаю номер подключения. Как то просто получилось. Может я что то упустил из виду?


 
Сергей М. ©   (2010-09-14 13:48) [42]


> ZV ©   (14.09.10 12:20) [41]


Накой шиш тебе этот "номер" ?

У тебя возникло событие OnClientConnect, фактическим параметром его обработчика тебе передан объект Socket, у него есть св-во RemoteAddress (и RemoteAddr - не суть как важно). Т.е. в момент обработки события ты знаешь адрес удаленного клиента. Ну так и отключай его, если нужно, впрямо в этом же обработчике вызовом Socket.Close ! За каким тебе понадобилось лезть в список активных соединений-то ?)


 
Anatoly Podgoretsky ©   (2010-09-14 13:56) [43]


> За каким тебе понадобилось лезть в список активных соединений-
> то ?)

Он нехочет слушать этот совет


 
ZV ©   (2010-09-14 13:57) [44]

У активных пользователей есть определенное  время нахождения на сервере. После тог как время истекло мне нужно этого пользователя от сервера отключить. И тут возникает вопрос - как? . Я знаю только IP  а не номер его подключения. А отключить я могу конкретного клиента только через ServerSocket.Socket.Connections[f].Close

Где f и есть номер подключения.
Поэтому я и хочу при коннекте клиента к серверу узнать номер его подключения и занести его  в запись о данных клиента клиенте. И когда его время истекает я обращаюсь к записи нахожу его номер подключения и отключаю


 
ZV ©   (2010-09-14 14:03) [45]


> NomberConnection:=ServerSocket1.Socket.ActiveConnections


Скорей всего это фигня. Это может работать только если клиенты будут отключаться в такой же последовательности как и подключались.
Мда, хрень


 
Сергей М. ©   (2010-09-14 14:09) [46]


> нужно этого пользователя от сервера отключить. И тут возникает
> вопрос - как? . Я знаю только IP


Не только. Еще и порт знаешь.
Вот эта комбинация IP-адреса и порта как раз и есть уникальный идентификатор клиента в списке активных клиентов сервера.
Остается в цикле пробежаться по всем активным соединениям в списке ActiveConnections, сравнить каждое соединение на совпадение удал. адреса и порта с искоммой комбинацией. Нафих нужен номер акт.клиента в этом списке, если он может измениться в любой момент времени ?

Ты пораскинь мозгами-то - вот, к примеру, последовательно подключились три клиента А, В и С. В списке ActiveConnections они фигурируют под индексами 0,1 и 2 соответственно. Теперь клиент В отключился. Вопрос на засыпку: каков теперь индекс соединения клиента С в этом списке ?


 
Сергей М. ©   (2010-09-14 14:11) [47]

Ты-то запомнил клиента С в момент его подключения под индексом 2, а после отключения клиента В клиент С вовсе не третий (по порядку) в этом списке

)


 
Palladin ©   (2010-09-14 14:34) [48]

"... да и цикл удаления из списка у него с единицы начинался" (С)


 
ZV ©   (2010-09-14 14:56) [49]


> Сергей М


> если он может измениться в любой момент времени ?

Я вник в суть проблемы

Значит я должен сделать приблизительно так ?


for i:=0 to ServerSocket1.Socket.ActiveConnections do
a:=ServerSocket1.Socket.Connections[i].RemoteAddress ;
for d:=1 to MaxClient do
if a=Client[d].IP then
begine
if Client[d].Status=false then
begin
ServerSocket1.Socket.Connections[i].Close ;
end
end


 
Сергей М. ©   (2010-09-14 15:07) [50]

Ну а где в этом "приближительно" сравнение порта ?


 
ZV ©   (2010-09-14 15:13) [51]

А порт на кой нужен? IP не достаточно?


 
Сергей М. ©   (2010-09-14 15:18) [52]


> А порт на кой нужен?


А что мешает двум совершенно разным клиентам подключиться к твоему серверу под одним и тем же IP-адресом ?
Ничто)


 
ZV ©   (2010-09-14 15:30) [53]


> Сергей М

Понял.

Сейчас вроде как все понятно. Но есть одна кака с которой я не знаю как бороться . У клиента есть такая особенность как неожиданный разрыв соединения без всяких уведомлений и потом повторное подключение, естественно у меня на сервер возникает ошибка и сервер падает. И эта кака не куда не денется,  по этому с ней нужно как то бороться. Я так понимаю что нужно сделать процедуру обработчик ошибки сокета
procedure TForm1.KaKa(Sender: TObject; Error: Exception);
begin
 If (Error.ClassName = "ESocketError") then
   Begin
    // Что написать при обрыве связи с клиентом и повторном его подключении  я не пойму
   end
 else Application.ShowException(Error);  
end;


 
Anatoly Podgoretsky ©   (2010-09-14 15:37) [54]

> ZV  (14.09.2010 15:13:51)  [51]

ИП недостаточно, подключений может быть много.


 
Anatoly Podgoretsky ©   (2010-09-14 15:38) [55]


> А что мешает двум совершенно разным клиентам подключиться
> к твоему серверу под одним и тем же IP-адресом ?

Особенно из-за НАТ


 
Сергей М. ©   (2010-09-14 15:38) [56]

А где у тебя обработчик OnClientError ?


 
Anatoly Podgoretsky ©   (2010-09-14 15:40) [57]

Прощай Сеть


 
ZV ©   (2010-09-14 15:51) [58]


> А где у тебя обработчик OnClientError ?

Нет, его у меня.
А в каком случае он сработает? И что в нем делать?

> Прощай Сеть

:)


 
Сергей М. ©   (2010-09-14 16:09) [59]

OnClientError может сработать в случае возникновения отказа в ходе выполнения сервером того или иного метода приема или передачи. Параметр ErrorCode укажет причину отказа. Самое простое и надежное - тут же закрыть соединение вызовом Socket.Close.

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


 
ZV ©   (2010-09-14 16:43) [60]

Получается что если клиент  неожиданно  разорвал связь и пытается повторить соединение  то в этом обработчике нужно закрыть сокет
If (Error.ClassName = "ESocketError") then
  Begin
    If (Error.ClassName = "ESocketError") then
  Begin

ServerSocket1.Close.;

  end
else Application.ShowException(Error)

Сервер закроет сокет с которым возникает конфликт , а клиент все таки подключиться или ему после этого повторно нужно подключаться?


 
Сергей М. ©   (2010-09-14 21:56) [61]


> Сервер закроет сокет с которым возникает конфликт


Ну да, закроет.
Зачем ему нужно несуществующее соединение ?
Не нужно оно ему.


> а клиент все таки подключиться


вот когда он подключится - тогда и разговор будет.

Тогда и новое OnClientConnect будет возбуждено.


 
ZV ©   (2010-09-15 09:23) [62]

Что то не хрена не получается устранить ошибку при повторном подключении клиента после обрыва связи
Вот что написал в обработчике ошибок
procedure TForm5.ServerSocket1ClientError(Sender: TObject;
 Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
 Memo1.Lines.Text:=" Ошибка!!!" ;
 ServerSocket1.Socket.Connections[ServerSocket1.Socket.ActiveConnections-1].Close;

 end;

И в этом
procedure TForm5.ClException(Sender: TObject; Error: Exception);
begin
 If (Error.ClassName = "ESocketError") then
   Begin
     Memo1.Lines.Add("Ошибка!!! ");
    ServerSocket1.Socket.Connections[ServerSocket1.Socket.ActiveConnections].Close;
   end
 else Application.ShowException(Error);  
end;

Толку нет, сервер вылетает с ошибкой сокета

Как с этим бороться ?
Что делаю не правильно ?


 
Anatoly Podgoretsky ©   (2010-09-15 10:06) [63]

> ZV  (15.09.2010 09:23:02)  [62]

А что это значит [ServerSocket1.Socket.ActiveConnections].


 
ZV ©   (2010-09-15 11:43) [64]


> А что это значит [ServerSocket1.Socket.ActiveConnections].

Ну типа отключить того кто пытается подключиться. Что советуют то и делаю
Ну не знаю я что делать в обработчике ошибки.
Только что проверял чужой сервер на резкий обрыв связь и повторное подключения работает безотказно.
Значит можно решить эту проблему, но как?


 
Anatoly Podgoretsky ©   (2010-09-15 12:09) [65]

Я не поленился и просмотре все обсуждение, никто такого не советовал.


 
Anatoly Podgoretsky ©   (2010-09-15 12:11) [66]

Ищем не там где потерял, а там где светло.


 
Сергей М. ©   (2010-09-15 12:15) [67]


> отключить того кто пытается подключиться


А чем он провинился ?)


 
ZV ©   (2010-09-15 13:01) [68]

Ну так что делать в обработчике ошибок когда клиент пытается подключится после обрыва связи? И почему возникает ошибка .Если бы не эта хрень то все работает нормально.


 
Anatoly Podgoretsky ©   (2010-09-15 13:12) [69]

> Сергей М.  (15.09.2010 12:15:07)  [67]

Диверсант.


 
Сергей М. ©   (2010-09-15 13:51) [70]


> ZV ©   (15.09.10 13:01) [68]


Обработчик OnClientError не вызывается при копвтке коннекта, не выдумывай небылиц.


 
ZV ©   (2010-09-15 14:17) [71]

Я не знаю что где вызывается. Но в мемо1 OnClientError надпись выводит значит срабатывает  так же как и процедура ClException.

Но это все не главное . Вопрос остается открытым - Что делать?
При повторном подключении оборвавшегося клиента  сервер падает.


 
Сергей М. ©   (2010-09-15 14:24) [72]


> Я не знаю что где вызывается


Ну вот теперь будешь знать)


> в мемо1 OnClientError надпись выводит


А ты убери полностью всю требуху из OnClientConnect/Disconnect/Read/Write и удивись - никто никакие надписи никуда выводить не будет)


 
ZV ©   (2010-09-15 15:31) [73]

Зачем что то убирать , все нормально работает. Вы наверно не поймете в чем проблема, я постараюсь объяснить. В качестве клиентов выступают микроконтроллеры они коннектятся к серверу и получают от него нужную информацию . Когда микроконтроллеру не нужно получать информацию он отключается от сервера а когда нужно опять подключается. Все это на данный момент работает  к сервер одновременно подключено  78 клиентов. Нормально происходит авторизация доступа к серверу и отключение не нужных клиентов.

Но если взять и отключить питание клиенту(микроконтроллеру) подключенному к серверу , то он перезагружается и снова коннектися к серверу и вот тут сервер дает сбой в виде ошибки сокета . Я так думаю это происходит потому что произошел обрыв связи и соединение не было закрыто как положено, и при повторном подключении этого же клиента,  сервер падает.
Те клиенты которые отключились самостоятельно нормально подключаются снова и работают с сервером.
 
Только не надо спрашивать а зачем отключать питание и т.д.


 
Сергей М. ©   (2010-09-15 15:54) [74]


> коннектися к серверу и вот тут сервер дает сбой в виде ошибки
> сокета


Т.е. ты утверждаешь что при этом OnClientConnect не возникает, а вместо него с какого-то перепугу возникает OnClientError ?

Ты готов кровью поклясться в истинности своего утверждения ?)


 
ZV ©   (2010-09-15 16:41) [75]

Вот какая складывается ситуация
При повторном подключении клиента у меня выскакивают сообщения
Asynchronous Socket error 10053  я игнорирую сообщение и нажимаю кнопку дальше и смотрю какие сообщения и от каких процедур  появилось в поле Мемо

вот что я вижу

Ошибка!!! (1)
[15:09:17]Клиент отключился IP-172.17.226.1 (2)
Ошибка!!! Повторное подключение (3)
[15:09:17]Подключился клиент (4)

1-сообщение от ServerSocket1ClientError(Sender: TObject;
 Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);

2-сообщение от ServerSocket1ClientDisconnect(Sender: TObject; Socket:TCustomWinSocket);

3-сообщение от ClException(Sender: TObject; Error: Exception);)

4-сообщение от ServerSocket1ClientConnect(Sender: TObject;
 Socket: TCustomWinSocket);

Сергей М. Вы правы клиент все таки подключился , и вроде бы  работал.
Но что делать с выпадающим окном с сообщением об ошибке, в чем причина появления этого сообщения


 
Anatoly Podgoretsky ©   (2010-09-15 16:45) [76]

Разберись, что ошибка 10053 значит.


 
Anatoly Podgoretsky ©   (2010-09-15 16:46) [77]

И зачем ты игнорируешь, или раз ты не можешь работать с ассинхронными сокетами, то перейди на синхронные. Без знаний работа с с ассинхронными сокетами безперспективна.


 
Сергей М. ©   (2010-09-15 16:55) [78]


> клиент все таки подключился


Ну наконец-то)
Теперь, полагаю, ты осознал что ошибку вызывает не факт подключения, а кривые действия твоего сервера уже после успешного подключения ?

Вот я тебе и предлагаю - чтобы лишний раз убедиться в этом, выкинь требуху изо всех обработчиков кроме OnClientConnect и OnClientDisconnect, оставив в них только протоколирование возникновения этих событий.
Событие OnClientError не должно возникнуть ни разу на всем протяжении времени пока сервер активен.


 
Сергей М. ©   (2010-09-15 17:09) [79]


> ZV ©   (15.09.10 16:41) [75]


Ты пойми одну простую вещь - OnClientError не может возникнуть, если сервер не производит никаких операций с соединением, ассоциированным с ранее подключившимся клиентом (т.е. фигурирующим в списке Connections). К этим действиям относятся вызовы сервером любых Send- и Receive-методов, а также метода Close объекта TServerClientWinSocket, коим клиент представлен в списке Connections.


 
ZV ©   (2010-09-15 17:19) [80]


> ошибку вызывает не факт подключения, а кривые действия твоего
> сервера уже после успешного подключения ?
>

Да не тут все не так, вы посмотрите внимательно на последовательность появления сообщений, сперва идет обработка ошибок а затем подключение . У меня в обработчиках ошибок ни чего кроме вывода сообщения нет.
Вот что пишут об этой ошибке (автоматический перевод с англ)


WSAECONNABORTED (10053) Программное обеспечение вызвало связи Прервать.

Беркли Описание: прервать соединение было вызвано внутренними на вашей машине. Программное обеспечение вызвало связи прервать из-за отсутствия места на очереди сокета и сокета не может принимать новые соединения.

WinSock описание: Частично же, как и Беркли. Ошибка может возникать при локальной вычислительной сети прерывает соединение. Это может произойти, если WinSock прервалось после установленного соединения ретрансляции данных не удается (получатель никогда не признает данные, передаваемые на поток данных сокета).

TCP / IP сценарий: соединение будет таймаут, если местная система не получает (ACK) nowledgement для переданных данных. Было бы также, если тайм-аут (FIN) иш пакетов TCP не ACK"d (и даже если это FIN ACK"d, в конечном счете, если тайм-аут FIN не возвращается).

Пользователь предложения: Есть несколько вещей, чтобы проверить, что может помочь определить, почему произошел сбой. В принципе, вы хотите определить, где возникла проблема.

 Пинг удаленного хоста вы были связаны. Если он не отвечает, это может быть офф-лайн или могут быть проблемы в сети на этом пути. Если это не реагировать, то эту проблему можно было бы переходных 1 (так что вы можно восстановить в настоящее время), или сервер приложений вы подключены к бы прекращено (так что вы не сможете подключиться снова).
   ) Пинг местного узла, чтобы проверить вашу локальную сеть продолжает функционировать (если на последовательный порт, см. следующий шаг)
    Если вы на последовательный порт, локальный маршрутизатор IP-адрес хоста, который первоначально вошли на с SLIP или PPP.
  Пинг хоста на той же подсети, что и хозяин вы подключены к (если вы знаете, 1). Это позволит убедиться, что сеть не функционирует.
  Попробуйте "Traceroute" принимающей вы подключены. Это не будет раскрывать слишком много, если вы не знаете адреса маршрутизатора на удаленной машине, но это может помочь определить, что проблема находится где-то в пути.

Функции: Recv () , recvfrom () , SendTo () , Fd_Close
Дополнительные функции: отправить () с CAN также WSAECONNABORTED Fail. Любая функция, как входной разъем, который принимает параметр - за исключением Закрыть сокет () - Неужели это возможно к ошибке.


оригинал здесь http://www.sockets.com/err_lst1.htm


 
Сергей М. ©   (2010-09-15 18:14) [81]

Да упарил ты уже своим  "сначала" да "потом")
Еще раз повторяю - если ты не вызываешь никакие методы объекта, ассоциированного с неким ранее подключившимся клиентом, то OnSocketError для этого соединения никогда не возникнет !!!!


 
Сергей М. ©   (2010-09-15 18:20) [82]

Черным же по белому написано в том документе, на который ты пеняешь:

WinSock functions: recv(), recvfrom(), sendto(), FD_CLOSE
Additional functions: send()


Нет вызова тех самых методов - нет и вызова этих функций.
Нет вызова этих ф-ций - нет и ошибки.
Нет ошибки - нет и исключения.

Или опять не понятно ?)


 
Anatoly Podgoretsky ©   (2010-09-15 18:50) [83]

> ZV  (15.09.2010 17:19:20)  [80]

Нафига ты переводил, нам что теперь делать обратный перевод?


 
ZV ©   (2010-09-15 18:54) [84]


> Нафига ты переводил, нам что теперь делать обратный перевод?
>
>

В низу  топика ссылка на оригинал


 
Anatoly Podgoretsky ©   (2010-09-15 19:10) [85]

> ZV  (15.09.2010 18:54:24)  [84]

Тоже нафиг


 
ZV ©   (2010-09-20 15:30) [86]

И так, проблема с ошибкой soketa при повторном подключении так и не решена, это начинает уже напрягать, так как сама программа готова.
Написал элементарную программку для проверки ( как утверждал Сергей М. нужно выкинуть все лишнее из кода и ошибки не будет) ниж приведен код из которого уже выкидывать не чего  , но ошибка вылетает так как и вылетала

Вот собственно сам код

unit Unit6;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ScktComp, StdCtrls;

type
 TForm6 = class(TForm)
   Memo1: TMemo;
   ServerSocket1: TServerSocket;
   procedure ServerSocket1ClientConnect(Sender: TObject;
    Socket: TCustomWinSocket);
   procedure ServerSocket1ClientDisconnect(Sender: TObject;
     Socket: TCustomWinSocket);
   procedure ServerSocket1ClientError(Sender: TObject;
     Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
     var ErrorCode: Integer);

 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form6: TForm6;

implementation

{$R *.dfm}

procedure TForm6.ServerSocket1ClientConnect(Sender: TObject;
 Socket: TCustomWinSocket);
begin
     Memo1.Lines.Add("["+TimeToStr(Time)+"] Клиент подключился ");
end;

procedure TForm6.ServerSocket1ClientDisconnect(Sender: TObject;
 Socket: TCustomWinSocket);
begin
     Memo1.Lines.Add("["+TimeToStr(Time)+"] Клиент отключился  ");
end;

procedure TForm6.ServerSocket1ClientError(Sender: TObject;
 Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
       Memo1.Lines.Add("["+TimeToStr(Time)+"] ServerSocket1ClientError");
end;

end.


Вот что выводиться в поле Мемо1

[14:16:14] Клиент подключился    //клиент подключился , затем reset клиента
[14:16:19] ServerSocket1ClientError // повторное подключение клиента
[14:16:20] Клиент подключился  // игнорирование ошибки в сообщении



Коментариий Сергея М. -Еще раз повторяю - если ты не вызываешь никакие методы объекта, ассоциированного с неким ранее подключившимся клиентом, то OnSocketError для этого соединения никогда не возникнет !!!!
Ну и какие я методы вызвал в данной программе? Почему возникло ServerSocket1ClientError ?

Я так понимаю что эту ошибку победить нельзя в случе неожиданного  обрыва клиента? Пока я не увидел ни одного рационального предложения, только размышления

P.S. использую Delphi 2009, может в этом проблема ?


 
Сергей М. ©   (2010-09-20 16:23) [87]


> ZV ©   (20.09.10 15:30) [86]


Я полагаю что у тебя ServerSocket1.ServerType = stNonBlocking.
Это соответствует действительности ?


 
Anatoly Podgoretsky ©   (2010-09-20 16:26) [88]

> ZV  (20.09.2010 15:30:26)  [86]

Какое значение ErrorCode, не пытался ли обработать ErrorEvent


 
Anatoly Podgoretsky ©   (2010-09-20 16:28) [89]

И в обработчикаъ подключение/отключение показать сокет.


 
ZV ©   (2010-09-20 16:52) [90]


> Я полагаю что у тебя ServerSocket1.ServerType = stNonBlocking.

Да, только без приставки Type

> Какое значение ErrorCode, не пытался ли обработать ErrorEvent
>


Код ошибкb тот же вот что написано в сообщении
rasied exception class Esocket Error with message "Ascynchronous socket error 1053


> не пытался ли обработать ErrorEvent
>

Я такого события для ServerSocket не нашел, или я не правильно вас понял

У меня есть программка мини сервер , так вот я над ней издеваюсь , к ней подключаются  10 клиентов , затем я делаю клиентам reset и повторный коннект, и хрен какая ошибка вылетает, и так молотит каждую секунду, и ещё к этому серверу подключено 5 клиентов которые просто  висят на сервере,
Но  я заметил на этом сервере такую вещь , там выводится информация о подключении и отключении так вот когда я повторно подключаю клиентов то сервер выводит информацию от том что произошел дисконнект а затем коннект
Походу он закрывает подключения отвалившихся клиентов а затем подключает их.

Значит как то это решаемо?


 
ZV ©   (2010-09-20 16:53) [91]


> Я полагаю что у тебя ServerSocket1.ServerType = stNonBlocking.

Да, только без приставки Type

> Какое значение ErrorCode, не пытался ли обработать ErrorEvent
>


Код ошибкb тот же вот что написано в сообщении
rasied exception class Esocket Error with message "Ascynchronous socket error 1053


> не пытался ли обработать ErrorEvent
>

Я такого события для ServerSocket не нашел, или я не правильно вас понял

У меня есть программка мини сервер , так вот я над ней издеваюсь , к ней подключаются  10 клиентов , затем я делаю клиентам reset и повторный коннект, и хрен какая ошибка вылетает, и так молотит каждую секунду, и ещё к этому серверу подключено 5 клиентов которые просто  висят на сервере,
Но  я заметил на этом сервере такую вещь , там выводится информация о подключении и отключении так вот когда я повторно подключаю клиентов то сервер выводит информацию от том что произошел дисконнект а затем коннект
Походу он закрывает подключения отвалившихся клиентов а затем подключает их.

Значит как то это решаемо?


 
ZV ©   (2010-09-20 17:09) [92]

Я хрен пойму эту проблему , ну отвалился клиент, остался сокет открытым, подключается заново  клиент для него создается новый сокет, я же не работаю с отвалившимся клиентом какого хрена вылетает ошибка . Или ServeSocket при коннекте делает какую то сверку   по ip клиента который хочет подключиться  и с базой подключенных клиентов и  тут возникает коллизия из за повтора iP , по ходу в обработчике ошибки нужно найти  номер коннекта клиента с таким же Ip отключить его а потом разрешить коннект  клиенту?  
Если отвалившимся  клиентам сменить IP адреса  коннект проходит без проблем.
P.S. Все настроения испортила эта ошибка, дальше делать ни чего не хочется.


 
Сергей М. ©   (2010-09-20 17:26) [93]


> Да, только без приставки Type


Это как это ?


> Я такого события для ServerSocket не нашел


Черным же по белому написано в справке к OnClientError :

Set the ErrorCode parameter to 0 if the OnClientError event handler successfully deals with the error condition to prevent an ESocketError from being raised.


> я делаю клиентам reset


Что ты называешь reset"ом ?

reset он разный бывает..


> ServeSocket при коннекте делает какую то сверку   по ip
> клиента который хочет подключиться  и с базой подключенных
> клиентов и  тут возникает коллизия из за повтора iP


Не делает он никаких "сверок по ip".
По кр.мере в D7.


 
ZV ©   (2010-09-20 17:57) [94]


> Что ты называешь reset"ом ?

Полная  перезагрузка ПО клиента


 
ZV ©   (2010-09-20 18:01) [95]


> > Да, только без приставки Type
>
>
> Это как это ?
>

Ошибся , с приставкой


 
Сергей М. ©   (2010-09-20 18:08) [96]


> перезагрузка ПО клиента


Это тоже можно трактовать двояко.
Например, нажатие кнопульки Reset на корпусе дивайса - это тоже "перезагрузка ПО клиента", которую принято называть "холодным рестартом".


 
ZV ©   (2010-09-20 18:32) [97]


> Это тоже можно трактовать двояко.

Короче, отключение  питания девайса (обесточивание).Но  это  сейчас не главное.

Вопрос стоит в том что делать с моей проблемой? Как устранять ошибку?


 
Anatoly Podgoretsky ©   (2010-09-20 19:29) [98]


> > не пытался ли обработать ErrorEvent
> >
>
> Я такого события для ServerSocket не нашел, или я не правильно
> вас понял

А это что

> procedure TForm6.ServerSocket1ClientError(Sender: TObject;
>
>  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var
> ErrorCode: Integer);


 
Сергей М. ©   (2010-09-20 21:00) [99]


> ZV ©   (20.09.10 18:32) [97]


А скажи, любезный, эти твои дивайсы коннектятся к серверу всегда с одного и того же порта ?
Или номер порта при каждой попытке коннекта различен ?


 
ZV ©   (2010-09-20 23:08) [100]


>
> А скажи, любезный, эти твои дивайсы коннектятся к серверу
> всегда с одного и того же порта ?
> Или номер порта при каждой попытке коннекта различен ?

Подключение всегда по одному порту,этот параметр прошит в памяти.
Со стороны девайса проблем нет, тестировал на сервере который делаю, запустили на круговой  коннект дисконнект, 20000 подключений и отключений и не одной сбойки не было . Я же выше писал что тестировал и на чужом сервере  при одновременном подключении и отключении 10 девайсов, все работает .

А тут как то не получается,  я полазил по сайтам подобная проблема не только у меня, у создателей чатов тоже выпадает такая ошибка если клиент резко выпадает из сети и опять коннектится. Но они проблему решили проверкой времени между контрольными посылками от клиентов, если прошел таймаут а клиент не прислал контрольный пакет то сервер его отключает.
И ещё пишут о перехвате ошибке сокета и уже на основании её выполнение каких то действий но каких не написано.

Да, такой каки я не ожидал.

> Я такого события для ServerSocket не нашел, или я не правильно
> вас понял

А это что

> procedure TForm6.ServerSocket1ClientError(Sender: TObject;
>
>  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var
> ErrorCode: Integer);

А как обработать ErrorEvent ? Я же не гуру в Delphi а только учусь.

Вы подскажите как а я сделаю что вы скажите, я сам в этой проблеме не разберусь, опыт у меня не тот что у Вас к сожалению.


 
Anatoly Podgoretsky ©   (2010-09-20 23:20) [101]

> ZV  (20.09.2010 23:08:40)  [100]

TErrorEvent описан в справке.


 
ZV ©   (2010-09-20 23:53) [102]

Снял лог  обмена пакетами между девайсом и моим сервером и девайсом и чужим сервером при повторном подключение . Пакеты идентичны.
М да легче от этого  не стало, зацепится не зачто.


 
ZV ©   (2010-09-21 00:32) [103]


> TErrorEvent описан в справке.

Без примера я не пойму что делать с TErrorEvent . Справка на английском языке мне много не даст. Не ужели тяжело показать пример как работать с TErrorEvent ?
Вы поймите что я не так хорошо владеют Delphi как Вы , и что для Вас очевидно, для меня темный лес.


 
Anatoly Podgoretsky ©   (2010-09-21 09:37) [104]

> ZV  (21.09.2010 00:32:43)  [103]

То есть ты хочешь сказать, что ты даже основ не знаешь,
Не умеешь работать с нумероваными типами,
Тогда тебе еще рано программировать сокеты.


 
app ©   (2010-09-21 09:46) [105]

> Anatoly Podgoretsky  (21.09.2010 09:37:44)  [104]

Если прогноза не будет, то закрою ветку, нельзя же столько времени мусолить
данный вопрос, как бесперспективная тема. Максим еще 5 постов.


 
app ©   (2010-09-21 09:50) [106]

> app  (21.09.2010 09:46:45)  [105]

Прогноз такой - если прогресса ...


 
Сергей М. ©   (2010-09-21 10:47) [107]


> Подключение всегда по одному порту,этот параметр прошит
> в памяти


Что значит "по порту" ?

У сервера номер порт фиксирован, например, 12345.
А у клиента ?

Что говорит твой сервер в OnClienConnect по поводу Socket.RemotePort ?
Это порт всегда один и тот же или различен при каждом коннекте ?


 
Anatoly Podgoretsky ©   (2010-09-21 11:06) [108]

Я еще в [89] просил дать информацию по сокету и нуль, одна трепология вокруг да около.


 
Сергей М. ©   (2010-09-21 11:10) [109]


> Справка на английском языке мне много не даст


Как это не даст ? Всем дает, а тебе отказывает ?)
Плохо уговариваешь)


 
ZV ©   (2010-09-21 13:28) [110]

Прогресс есть, решил проблему таким образом в событии ServerSocket1ClientError

прописал   ErrorCode:=0;
Теперь сообщение об ошибке Socketa не появляется, сервер пока работает нормально, запустил на тест с постоянным отпаданием  клиента и повторным коннектом, уже прошло 200 обрывов, повторный коннект проходит без проблем,сервер работает стабильно

Почему  тут ни кто не написал чтобы я так сделал?
Блин одна строчка кода  и проблема исчезла  .


>
> У сервера номер порт фиксирован, например, 12345.
> А у клиента ?
>
> Что говорит твой сервер в OnClienConnect по поводу Socket.
> RemotePort ?
> Это порт всегда один и тот же или различен при каждом коннекте
> ?

Номер порта что у клиента что у сервера один и тот же, фиксированный. Порт один и тот же при каждом коннекте


 
Сергей М. ©   (2010-09-21 13:37) [111]


> Почему  тут ни кто не написал чтобы я так сделал?


А тебе тут кто-то чем-то обязан ?)


> Порт один и тот же при каждом коннекте


Ну тогда ситуация с ошибкой 10053 вполне объяснима.
А вот как только клиент будет коннектиться к твоему серверу с разных портов, вот тогда ошибку эту с учетом [82] ты никогда не увидишь. И будут битые соединения висеть мертвым грузом в списке активных, пока твой сервер активен и не использует тот или иной KeepAlive-механизм для периодического обнаружения клиентских трупов)


 
ZV ©   (2010-09-21 14:09) [112]


> И будут битые соединения висеть мертвым грузом в списке
> активных, пока твой сервер активен и не использует тот или
> иной KeepAlive-механизм для периодического обнаружения клиентских
> трупов)

Получается что сокет будет висеть открытым , потому что клиент отвалился и не дал команду на закрытие, а сервер не в курсе что этот сокет больше не используется и нужно его закрывать. А каким образом делать проверку не используемых сокетов? Может есть какой то параметр у сокета если он не активен определенный промежуток времени то его нужно закрыть ?


 
Сергей М. ©   (2010-09-21 14:33) [113]


> ZV ©   (21.09.10 14:09) [112]


http://www.rsdn.ru/article/net/keep_alive.xml
http://www.rsdn.ru/forum/network/2553292.flat.aspx


 
ZV ©   (2010-09-21 14:38) [114]


> Сергей М

<Большое спасибо, будем разбираться.


 
ZV ©   (2010-09-21 15:49) [115]

Да KeepAlive , это жестко, есть описание или для С++ или UNIX , вот все что нашел для Delphi  http://www.delphi-forum.de/topic_Problem+beim+Nutzen+von+Socket+setsockopt+und+SOKEEPALIVE_96953,0.html но что из этого мне нужно я не пойму, подскажите , я сам не разберусь.


 
Сергей М. ©   (2010-09-21 16:31) [116]


> KeepAlive , это жестко


Ну сделай "мягко", раз сишный код для тебя новые ворота - по таймеру периодически отправляй своему клиенту какую-нибудь безобидную хрень. Если схлопочешь при  очередной отправке исключение, значит на том конце труп)

Я ж тебе об этом еще в [82] сказал)



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

Форум: "Начинающим";
Текущий архив: 2010.12.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.8 MB
Время: 0.005 c
2-1284042092
ZV
2010-09-09 18:21
2010.12.12
TServerSocket, как узнать IP клиента при подключении.


6-1230380237
pomashok
2008-12-27 15:17
2010.12.12
Расшаривание интернет соединения


15-1283514271
tesseract
2010-09-03 15:44
2010.12.12
www магазинчики


3-1249327055
DmitrichJ
2009-08-03 23:17
2010.12.12
Организация поиска по документам в БД


15-1283256546
AlexDn
2010-08-31 16:09
2010.12.12
Поисковики и регион





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский