-
Хочу в событии 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; ?
-
Сделал так Label10.Caption :=ServerSocket1.Socket.Connections[ServerSocket1.Socket.Act iveConnections-1].RemoteAddress; В Label10 выводиться IP подключившегося клиента правда клиент только один и будет ли это работать когда подключется ещё один не знаю, теперь не пойму как мне работать с этим IP . мне нужна последняя цифра IP для проверки с базой как её извлечь ?
-
> ZV (09.09.2010 18:21:00) [0]
Не ремонтный адрес, а удаленый. Это строковый формат адреса, соответсвенно тип нужен STRING Также есть и вариант с числом, соответсвенно тип Cardinal
-
> ZV (09.09.2010 18:43:01) [1]
Зачем же так сложно, когда в обработчик передается Socket Label10.Caption := Socket.RemoteAddress; ExtractFileExt Точку вначале сам удалишь? Но ты зря не работаешь с цифровым представлением, там все проще.
-
> Не ремонтный адрес, а удаленый.
Не понял > Это строковый формат адреса, соответсвенно тип нужен STRING > Также есть и вариант с числом, соответсвенно тип Cardinal
Я не пойму как это 172.17.200.2 преобразовать в число и провести сравнение базы с последней цифрой IP то есть 2 .
-
> Но ты зря не работаешь с цифровым представлением, там все > проще.
Да если бы я знал как
-
> Label10.Caption := Socket.RemoteAddress;
Да так проще. С определением IP, разобрался. А вот как работать с полученным IP не пойму
-
> ZV (09.09.2010 19:50:04) [4]
Не надо ничего преобразовывать RemoteAdr уже число, и можно обращаться к любому байту через приведение LongRec().Bytes[3] Cледующая ошибка, не надо в базе хранить последний октет ИП, храни полность или строковое или цифровое представление, цифровое лучше, быстрее и размер меньше в три раза. remonte - ремонтный, remote - удаленый Ты два раза повторил ремонтный, это означает, что это не опечатка.
-
> Ты два раза повторил ремонтный, это означает, что это не > опечатка.
Угу > LongRec().Bytes[3]
не пойму как > Cледующая ошибка, не надо в базе хранить последний октет > ИП, храни полность > или строковое или цифровое представление, цифровое лучше, > быстрее и размер > меньше в три раза.
А время на проверку уйдет больше, то ли один байт сверит а так весь IP
-
Хранение полностью цифровых значение благоприятно сказывается на скорости. Сравнение Integer наиболее быстрая операция.
-
У меня ступор с IP не пойму как этим LongRec().Bytes [3] воспользоваться Весь IP я проверять все таки не буду в моей ситуации это не нужно . Поэтому для контроля мне нужно последнее число в ip адресе a:Byte;
a:= Socket.RemoteAddress; как сделать так чтобы в переменной а оказалось последнее число в IP адреса?
-
> ZV © (09.09.10 21:04) [10]
Ну оттяпай шматок строки после последней точки в адресе, преобразуй его в Integer - вот тебе и "последнее число"
-
Анатолий имел ввиду :) var Address:Array [0..3] of Byte; Begin Integer(Address):=Socket.RemoteAddr.sin_addr.S_addr; If Address[?]=2 Then "Format C:" ... End;
-
> Ну оттяпай шматок строки после последней точки в адресе, > преобразуй его в Integer - вот тебе и "последнее число" >
Не фига себе метод а проще не как, других вариантов нет?
-
> а проще не как, других вариантов нет?
Тебе шашечки или ехать, я не пойму ?)
-
Я думал может есть более изящные методы, ну раз так тогда оттяпаем шматок, преобразуем ,сравним.
-
>ZV ©
Читаем пост [12] :) Проще не будет :)
Под вопросом я имел ввиду № октека, который тебе нужен для сравнения Или вообще сравнивай весь адрес, как сказал Дядя Толя :) А он плохого не посоветует :)
-
> оттяпаем шматок, преобразуем ,сравним.
Я боюсь что пока это все проделаю ещё с десяток клиентов подключатся
-
> ZV (09.09.2010 21:04:10) [10]
Я же написал для двух вариантов адресов.
-
> Читаем пост [12] :) > Проще не будет :) >
Я пока не сравниваю а пытаюсь вывести последнее число , но выводит в Label значение 0 var
Address:Array [0..3] of Byte;
begin
{
Integer(Address):=Socket.RemoteAddr.sin_addr.S_addr;
Label11.Caption := IntToStr(Address[3]); Что я делаю не так
-
>ZV ©
Прости за откровенность, но ты сюда пришел для чего? Я тебе дал самый оптимальный код без строковых преобразований, чего тебе еще нужно? Даже просто скопировать лень?
-
Если ты конектишся на 127.0.0.1 но обратный адрес всегда будет 0.0.0.0 ... По моему так, попробуй конектиться на свой реальный Адрес
-
> 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:"
-
> ZV (09.09.2010 21:49:15) [15]
А те решения, что я предложил, разве не изящны?
-
Слушай дядю Толю :) он хорошее советует :)
-
> FireMan_Alexey (09.09.2010 21:50:16) [16]
У меня статистика Интернета построена на целых адресах, никакого выделения октетов, только для индикации, а индикация основана на LongRec.Bytes как самое простое и удобное.
-
Если переменную сменить на Cardinal то компилятор ругается E2010 Incompatible types: 'Cardinal' and 'sockaddr_in'
-
> Anatoly Podgoretsky © (09.09.10 22:07) [25]
Так я наоборот Вас поддерживаю... :) А ТС просил побайтную, ну я и написал побайтную :)
-
Попробуй так :) Address: Cardinal;
Begin
Address := Cardinal(Socket.RemoteAddr);
-
Разве вариант с ExtractFileExt не изящен, а использование LongRec не изящно
-
Прости забыл... Address := Cardinal(Socket.RemoteAddr.sin_addr);
-
> У меня статистика Интернета построена на целых адресах, > никакого выделения > октетов, только для индикации, а индикация основана на LongRec. > Bytes как > самое простое и удобное. >
Да я не против проверять весь IP , даже за (так все таки будет надежней), но я не пойму как создать массив этих адресов, что делать с этими гребаными точками , и как потом сравнить полученный адрес с массивом
-
> Если переменную сменить на Cardinal то компилятор ругается > E2010 Incompatible types: 'Cardinal' and 'sockaddr_in'
Сделай или приведение, или смени тип переменной. Только откуда взялся 'sockaddr_in', у меня такого нет.
-
сделал так 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
-
> 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 битным беззнаковым. :-).
-
> FireMan_Alexey (09.09.2010 22:15:30) [30]
Address := Cardinal(Socket.RemoteAddr.sin_addr.S_Addr);
-
> ZV (09.09.2010 22:17:31) [31]
У цифровых нет никаких точек!!! Причем тут массив я не пойму. Сравнение делается операцией = Хоть с переменной, хоть с константой, хоть с массивом, хоть с записью, поскольку сранение ведется не с ними, а со значениями.
-
> ZV (09.09.2010 22:27:33) [33]
Тут слишком много написано ерунды.
-
А воз и нынче там, вот это жесть. 3 часа прошло а как извлечь значения из Socket.RemoteAddress; так и не ясно
-
> ZV (09.09.2010 23:08:38) [38]
Ладно не хочешь ExtractFileExt, то тогда LastDelimiter + Copy
-
Спасибо всем за советы. Я все таки сделал определение всего IP а не последней цифры , преобразовать в цифровой формат Socket.RemoteAddress; у меня не получилось по этому создал массив IP адресов в текстовом формате и сравниваю. В принципе работает меня пока устраивает , но возникла новая проблема. В обработчике ServerSocket1ClientConnect я определи IP клиента , выяснил, что клиенту доступ закрыт, теперь мне нужно его отключить через ServerSocket.Socket.Connections[?].Close . А как я его отключу? Я знаю только его IP но не номер его подключения. Как узнать какой номер подключения ?
-
Пока мне не ответили на вопрос я сделал так. При коннекте клиента в поле клиента о номере подключения записываю NomberConnection:=ServerSocket1.Socket.ActiveConnections И вроде получаю номер подключения. Как то просто получилось. Может я что то упустил из виду?
-
> ZV © (14.09.10 12:20) [41]
Накой шиш тебе этот "номер" ?
У тебя возникло событие OnClientConnect, фактическим параметром его обработчика тебе передан объект Socket, у него есть св-во RemoteAddress (и RemoteAddr - не суть как важно). Т.е. в момент обработки события ты знаешь адрес удаленного клиента. Ну так и отключай его, если нужно, впрямо в этом же обработчике вызовом Socket.Close ! За каким тебе понадобилось лезть в список активных соединений-то ?)
-
> За каким тебе понадобилось лезть в список активных соединений- > то ?)
Он нехочет слушать этот совет
-
У активных пользователей есть определенное время нахождения на сервере. После тог как время истекло мне нужно этого пользователя от сервера отключить. И тут возникает вопрос - как? . Я знаю только IP а не номер его подключения. А отключить я могу конкретного клиента только через ServerSocket.Socket.Connections[f].Close
Где f и есть номер подключения. Поэтому я и хочу при коннекте клиента к серверу узнать номер его подключения и занести его в запись о данных клиента клиенте. И когда его время истекает я обращаюсь к записи нахожу его номер подключения и отключаю
-
> NomberConnection:=ServerSocket1.Socket.ActiveConnections
Скорей всего это фигня. Это может работать только если клиенты будут отключаться в такой же последовательности как и подключались. Мда, хрень
-
> нужно этого пользователя от сервера отключить. И тут возникает > вопрос - как? . Я знаю только IP
Не только. Еще и порт знаешь. Вот эта комбинация IP-адреса и порта как раз и есть уникальный идентификатор клиента в списке активных клиентов сервера. Остается в цикле пробежаться по всем активным соединениям в списке ActiveConnections, сравнить каждое соединение на совпадение удал. адреса и порта с искоммой комбинацией. Нафих нужен номер акт.клиента в этом списке, если он может измениться в любой момент времени ?
Ты пораскинь мозгами-то - вот, к примеру, последовательно подключились три клиента А, В и С. В списке ActiveConnections они фигурируют под индексами 0,1 и 2 соответственно. Теперь клиент В отключился. Вопрос на засыпку: каков теперь индекс соединения клиента С в этом списке ?
-
Ты-то запомнил клиента С в момент его подключения под индексом 2, а после отключения клиента В клиент С вовсе не третий (по порядку) в этом списке
)
-
"... да и цикл удаления из списка у него с единицы начинался" (С)
-
> Сергей М > если он может измениться в любой момент времени ?
Я вник в суть проблемы Значит я должен сделать приблизительно так ?
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
-
Ну а где в этом "приближительно" сравнение порта ?
-
А порт на кой нужен? IP не достаточно?
-
> А порт на кой нужен?
А что мешает двум совершенно разным клиентам подключиться к твоему серверу под одним и тем же IP-адресом ? Ничто)
-
> Сергей М
Понял.
Сейчас вроде как все понятно. Но есть одна кака с которой я не знаю как бороться . У клиента есть такая особенность как неожиданный разрыв соединения без всяких уведомлений и потом повторное подключение, естественно у меня на сервер возникает ошибка и сервер падает. И эта кака не куда не денется, по этому с ней нужно как то бороться. Я так понимаю что нужно сделать процедуру обработчик ошибки сокета procedure TForm1.KaKa(Sender: TObject; Error: Exception); begin If (Error.ClassName = 'ESocketError') then Begin // Что написать при обрыве связи с клиентом и повторном его подключении я не пойму end else Application.ShowException(Error); end;
-
> ZV (14.09.2010 15:13:51) [51]
ИП недостаточно, подключений может быть много.
-
> А что мешает двум совершенно разным клиентам подключиться > к твоему серверу под одним и тем же IP-адресом ?
Особенно из-за НАТ
-
А где у тебя обработчик OnClientError ?
-
Прощай Сеть
-
> А где у тебя обработчик OnClientError ?
Нет, его у меня. А в каком случае он сработает? И что в нем делать?
> Прощай Сеть
:)
-
OnClientError может сработать в случае возникновения отказа в ходе выполнения сервером того или иного метода приема или передачи. Параметр ErrorCode укажет причину отказа. Самое простое и надежное - тут же закрыть соединение вызовом Socket.Close.
Если при вызове сервером того или иного метода приема или передачи отказ обнаружен еще до инициации асинхронной соответствующей операции, сервер возбудит исключение ESocketError, которое можно обработать точно так же.
-
Получается что если клиент неожиданно разорвал связь и пытается повторить соединение то в этом обработчике нужно закрыть сокет If (Error.ClassName = 'ESocketError') then Begin If (Error.ClassName = 'ESocketError') then Begin
ServerSocket1.Close.;
end else Application.ShowException(Error)
Сервер закроет сокет с которым возникает конфликт , а клиент все таки подключиться или ему после этого повторно нужно подключаться?
-
> Сервер закроет сокет с которым возникает конфликт
Ну да, закроет. Зачем ему нужно несуществующее соединение ? Не нужно оно ему.
> а клиент все таки подключиться
вот когда он подключится - тогда и разговор будет.
Тогда и новое OnClientConnect будет возбуждено.
-
Что то не хрена не получается устранить ошибку при повторном подключении клиента после обрыва связи Вот что написал в обработчике ошибок 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; Толку нет, сервер вылетает с ошибкой сокета Как с этим бороться ? Что делаю не правильно ?
-
> ZV (15.09.2010 09:23:02) [62]
А что это значит [ServerSocket1.Socket.ActiveConnections].
-
> А что это значит [ServerSocket1.Socket.ActiveConnections].
Ну типа отключить того кто пытается подключиться. Что советуют то и делаю Ну не знаю я что делать в обработчике ошибки. Только что проверял чужой сервер на резкий обрыв связь и повторное подключения работает безотказно. Значит можно решить эту проблему, но как?
-
Я не поленился и просмотре все обсуждение, никто такого не советовал.
-
Ищем не там где потерял, а там где светло.
-
> отключить того кто пытается подключиться
А чем он провинился ?)
-
Ну так что делать в обработчике ошибок когда клиент пытается подключится после обрыва связи? И почему возникает ошибка .Если бы не эта хрень то все работает нормально.
-
> Сергей М. (15.09.2010 12:15:07) [67]
Диверсант.
-
> ZV © (15.09.10 13:01) [68]
Обработчик OnClientError не вызывается при копвтке коннекта, не выдумывай небылиц.
-
Я не знаю что где вызывается. Но в мемо1 OnClientError надпись выводит значит срабатывает так же как и процедура ClException.
Но это все не главное . Вопрос остается открытым - Что делать? При повторном подключении оборвавшегося клиента сервер падает.
-
> Я не знаю что где вызывается
Ну вот теперь будешь знать)
> в мемо1 OnClientError надпись выводит
А ты убери полностью всю требуху из OnClientConnect/Disconnect/Read/Write и удивись - никто никакие надписи никуда выводить не будет)
-
Зачем что то убирать , все нормально работает. Вы наверно не поймете в чем проблема, я постараюсь объяснить. В качестве клиентов выступают микроконтроллеры они коннектятся к серверу и получают от него нужную информацию . Когда микроконтроллеру не нужно получать информацию он отключается от сервера а когда нужно опять подключается. Все это на данный момент работает к сервер одновременно подключено 78 клиентов. Нормально происходит авторизация доступа к серверу и отключение не нужных клиентов.
Но если взять и отключить питание клиенту(микроконтроллеру) подключенному к серверу , то он перезагружается и снова коннектися к серверу и вот тут сервер дает сбой в виде ошибки сокета . Я так думаю это происходит потому что произошел обрыв связи и соединение не было закрыто как положено, и при повторном подключении этого же клиента, сервер падает. Те клиенты которые отключились самостоятельно нормально подключаются снова и работают с сервером. Только не надо спрашивать а зачем отключать питание и т.д.
-
> коннектися к серверу и вот тут сервер дает сбой в виде ошибки > сокета
Т.е. ты утверждаешь что при этом OnClientConnect не возникает, а вместо него с какого-то перепугу возникает OnClientError ?
Ты готов кровью поклясться в истинности своего утверждения ?)
-
Вот какая складывается ситуация При повторном подключении клиента у меня выскакивают сообщения 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);
Сергей М. Вы правы клиент все таки подключился , и вроде бы работал. Но что делать с выпадающим окном с сообщением об ошибке, в чем причина появления этого сообщения
-
Разберись, что ошибка 10053 значит.
-
И зачем ты игнорируешь, или раз ты не можешь работать с ассинхронными сокетами, то перейди на синхронные. Без знаний работа с с ассинхронными сокетами безперспективна.
-
> клиент все таки подключился
Ну наконец-то) Теперь, полагаю, ты осознал что ошибку вызывает не факт подключения, а кривые действия твоего сервера уже после успешного подключения ?
Вот я тебе и предлагаю - чтобы лишний раз убедиться в этом, выкинь требуху изо всех обработчиков кроме OnClientConnect и OnClientDisconnect, оставив в них только протоколирование возникновения этих событий. Событие OnClientError не должно возникнуть ни разу на всем протяжении времени пока сервер активен.
-
> ZV © (15.09.10 16:41) [75]
Ты пойми одну простую вещь - OnClientError не может возникнуть, если сервер не производит никаких операций с соединением, ассоциированным с ранее подключившимся клиентом (т.е. фигурирующим в списке Connections). К этим действиям относятся вызовы сервером любых Send- и Receive-методов, а также метода Close объекта TServerClientWinSocket, коим клиент представлен в списке Connections.
-
> ошибку вызывает не факт подключения, а кривые действия твоего > сервера уже после успешного подключения ? >
Да не тут все не так, вы посмотрите внимательно на последовательность появления сообщений, сперва идет обработка ошибок а затем подключение . У меня в обработчиках ошибок ни чего кроме вывода сообщения нет. Вот что пишут об этой ошибке (автоматический перевод с англ)
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
-
Да упарил ты уже своим "сначала" да "потом") Еще раз повторяю - если ты не вызываешь никакие методы объекта, ассоциированного с неким ранее подключившимся клиентом, то OnSocketError для этого соединения никогда не возникнет !!!!
-
Черным же по белому написано в том документе, на который ты пеняешь:
WinSock functions: recv(), recvfrom(), sendto(), FD_CLOSE Additional functions: send()
Нет вызова тех самых методов - нет и вызова этих функций. Нет вызова этих ф-ций - нет и ошибки. Нет ошибки - нет и исключения.
Или опять не понятно ?)
-
> ZV (15.09.2010 17:19:20) [80]
Нафига ты переводил, нам что теперь делать обратный перевод?
-
> Нафига ты переводил, нам что теперь делать обратный перевод? > >
В низу топика ссылка на оригинал
-
> ZV (15.09.2010 18:54:24) [84]
Тоже нафиг
-
И так, проблема с ошибкой 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
public
end;
var
Form6: TForm6;
implementation
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] Клиент подключился [14:16:19] ServerSocket1ClientError [14:16:20] Клиент подключился
Коментариий Сергея М. - Еще раз повторяю - если ты не вызываешь никакие методы объекта, ассоциированного с неким ранее подключившимся клиентом, то OnSocketError для этого соединения никогда не возникнет !!!! Ну и какие я методы вызвал в данной программе? Почему возникло ServerSocket1ClientError ? Я так понимаю что эту ошибку победить нельзя в случе неожиданного обрыва клиента? Пока я не увидел ни одного рационального предложения, только размышления P.S. использую Delphi 2009, может в этом проблема ?
-
> ZV © (20.09.10 15:30) [86]
Я полагаю что у тебя ServerSocket1.ServerType = stNonBlocking. Это соответствует действительности ?
-
> ZV (20.09.2010 15:30:26) [86]
Какое значение ErrorCode, не пытался ли обработать ErrorEvent
-
И в обработчикаъ подключение/отключение показать сокет.
-
> Я полагаю что у тебя ServerSocket1.ServerType = stNonBlocking.
Да, только без приставки Type > Какое значение ErrorCode, не пытался ли обработать ErrorEvent >
Код ошибкb тот же вот что написано в сообщении
rasied exception class Esocket Error with message 'Ascynchronous socket error 1053 > не пытался ли обработать ErrorEvent >
Я такого события для ServerSocket не нашел, или я не правильно вас понял У меня есть программка мини сервер , так вот я над ней издеваюсь , к ней подключаются 10 клиентов , затем я делаю клиентам reset и повторный коннект, и хрен какая ошибка вылетает, и так молотит каждую секунду, и ещё к этому серверу подключено 5 клиентов которые просто висят на сервере, Но я заметил на этом сервере такую вещь , там выводится информация о подключении и отключении так вот когда я повторно подключаю клиентов то сервер выводит информацию от том что произошел дисконнект а затем коннект Походу он закрывает подключения отвалившихся клиентов а затем подключает их. Значит как то это решаемо?
-
> Я полагаю что у тебя ServerSocket1.ServerType = stNonBlocking.
Да, только без приставки Type > Какое значение ErrorCode, не пытался ли обработать ErrorEvent >
Код ошибкb тот же вот что написано в сообщении
rasied exception class Esocket Error with message 'Ascynchronous socket error 1053 > не пытался ли обработать ErrorEvent >
Я такого события для ServerSocket не нашел, или я не правильно вас понял У меня есть программка мини сервер , так вот я над ней издеваюсь , к ней подключаются 10 клиентов , затем я делаю клиентам reset и повторный коннект, и хрен какая ошибка вылетает, и так молотит каждую секунду, и ещё к этому серверу подключено 5 клиентов которые просто висят на сервере, Но я заметил на этом сервере такую вещь , там выводится информация о подключении и отключении так вот когда я повторно подключаю клиентов то сервер выводит информацию от том что произошел дисконнект а затем коннект Походу он закрывает подключения отвалившихся клиентов а затем подключает их. Значит как то это решаемо?
-
Я хрен пойму эту проблему , ну отвалился клиент, остался сокет открытым, подключается заново клиент для него создается новый сокет, я же не работаю с отвалившимся клиентом какого хрена вылетает ошибка . Или ServeSocket при коннекте делает какую то сверку по ip клиента который хочет подключиться и с базой подключенных клиентов и тут возникает коллизия из за повтора iP , по ходу в обработчике ошибки нужно найти номер коннекта клиента с таким же Ip отключить его а потом разрешить коннект клиенту? Если отвалившимся клиентам сменить IP адреса коннект проходит без проблем. P.S. Все настроения испортила эта ошибка, дальше делать ни чего не хочется.
-
> Да, только без приставки 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.
-
> Что ты называешь reset'ом ?
Полная перезагрузка ПО клиента
-
> > Да, только без приставки Type > > > Это как это ? >
Ошибся , с приставкой
-
> перезагрузка ПО клиента
Это тоже можно трактовать двояко. Например, нажатие кнопульки Reset на корпусе дивайса - это тоже "перезагрузка ПО клиента", которую принято называть "холодным рестартом".
-
> Это тоже можно трактовать двояко.
Короче, отключение питания девайса (обесточивание).Но это сейчас не главное.
Вопрос стоит в том что делать с моей проблемой? Как устранять ошибку?
-
> > не пытался ли обработать ErrorEvent > > > > Я такого события для ServerSocket не нашел, или я не правильно > вас понял
А это что
> procedure TForm6.ServerSocket1ClientError(Sender: TObject; > > Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var > ErrorCode: Integer);
-
> ZV © (20.09.10 18:32) [97]
А скажи, любезный, эти твои дивайсы коннектятся к серверу всегда с одного и того же порта ? Или номер порта при каждой попытке коннекта различен ?
-
> > А скажи, любезный, эти твои дивайсы коннектятся к серверу > всегда с одного и того же порта ? > Или номер порта при каждой попытке коннекта различен ?
Подключение всегда по одному порту,этот параметр прошит в памяти. Со стороны девайса проблем нет, тестировал на сервере который делаю, запустили на круговой коннект дисконнект, 20000 подключений и отключений и не одной сбойки не было . Я же выше писал что тестировал и на чужом сервере при одновременном подключении и отключении 10 девайсов, все работает .
А тут как то не получается, я полазил по сайтам подобная проблема не только у меня, у создателей чатов тоже выпадает такая ошибка если клиент резко выпадает из сети и опять коннектится. Но они проблему решили проверкой времени между контрольными посылками от клиентов, если прошел таймаут а клиент не прислал контрольный пакет то сервер его отключает. И ещё пишут о перехвате ошибке сокета и уже на основании её выполнение каких то действий но каких не написано.
Да, такой каки я не ожидал.
> Я такого события для ServerSocket не нашел, или я не правильно > вас понял
А это что
> procedure TForm6.ServerSocket1ClientError(Sender: TObject; > > Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var > ErrorCode: Integer);
А как обработать ErrorEvent ? Я же не гуру в Delphi а только учусь.
Вы подскажите как а я сделаю что вы скажите, я сам в этой проблеме не разберусь, опыт у меня не тот что у Вас к сожалению.
-
> ZV (20.09.2010 23:08:40) [100]
TErrorEvent описан в справке.
-
Снял лог обмена пакетами между девайсом и моим сервером и девайсом и чужим сервером при повторном подключение . Пакеты идентичны. М да легче от этого не стало, зацепится не зачто.
-
> TErrorEvent описан в справке.
Без примера я не пойму что делать с TErrorEvent . Справка на английском языке мне много не даст. Не ужели тяжело показать пример как работать с TErrorEvent ? Вы поймите что я не так хорошо владеют Delphi как Вы , и что для Вас очевидно, для меня темный лес.
-
> ZV (21.09.2010 00:32:43) [103]
То есть ты хочешь сказать, что ты даже основ не знаешь, Не умеешь работать с нумероваными типами, Тогда тебе еще рано программировать сокеты.
-
> Anatoly Podgoretsky (21.09.2010 09:37:44) [104]
Если прогноза не будет, то закрою ветку, нельзя же столько времени мусолить данный вопрос, как бесперспективная тема. Максим еще 5 постов.
-
> app (21.09.2010 09:46:45) [105]
Прогноз такой - если прогресса ...
-
> Подключение всегда по одному порту,этот параметр прошит > в памяти
Что значит "по порту" ?
У сервера номер порт фиксирован, например, 12345. А у клиента ?
Что говорит твой сервер в OnClienConnect по поводу Socket.RemotePort ? Это порт всегда один и тот же или различен при каждом коннекте ?
-
Я еще в [89] просил дать информацию по сокету и нуль, одна трепология вокруг да около.
-
> Справка на английском языке мне много не даст
Как это не даст ? Всем дает, а тебе отказывает ?) Плохо уговариваешь)
-
Прогресс есть, решил проблему таким образом в событии ServerSocket1ClientError
прописал ErrorCode:=0; Теперь сообщение об ошибке Socketa не появляется, сервер пока работает нормально, запустил на тест с постоянным отпаданием клиента и повторным коннектом, уже прошло 200 обрывов, повторный коннект проходит без проблем,сервер работает стабильно
Почему тут ни кто не написал чтобы я так сделал? Блин одна строчка кода и проблема исчезла .
> > У сервера номер порт фиксирован, например, 12345. > А у клиента ? > > Что говорит твой сервер в OnClienConnect по поводу Socket. > RemotePort ? > Это порт всегда один и тот же или различен при каждом коннекте > ?
Номер порта что у клиента что у сервера один и тот же, фиксированный. Порт один и тот же при каждом коннекте
-
> Почему тут ни кто не написал чтобы я так сделал?
А тебе тут кто-то чем-то обязан ?)
> Порт один и тот же при каждом коннекте
Ну тогда ситуация с ошибкой 10053 вполне объяснима. А вот как только клиент будет коннектиться к твоему серверу с разных портов, вот тогда ошибку эту с учетом [82] ты никогда не увидишь. И будут битые соединения висеть мертвым грузом в списке активных, пока твой сервер активен и не использует тот или иной KeepAlive-механизм для периодического обнаружения клиентских трупов)
-
> И будут битые соединения висеть мертвым грузом в списке > активных, пока твой сервер активен и не использует тот или > иной KeepAlive-механизм для периодического обнаружения клиентских > трупов)
Получается что сокет будет висеть открытым , потому что клиент отвалился и не дал команду на закрытие, а сервер не в курсе что этот сокет больше не используется и нужно его закрывать. А каким образом делать проверку не используемых сокетов? Может есть какой то параметр у сокета если он не активен определенный промежуток времени то его нужно закрыть ?
-
-
> Сергей М
<Большое спасибо, будем разбираться.
-
-
> KeepAlive , это жестко
Ну сделай "мягко", раз сишный код для тебя новые ворота - по таймеру периодически отправляй своему клиенту какую-нибудь безобидную хрень. Если схлопочешь при очередной отправке исключение, значит на том конце труп)
Я ж тебе об этом еще в [82] сказал)
|