Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.04.2018, 16:58   #1
vova65
Пользователь
 
Регистрация: 05.06.2011
Сообщений: 48
По умолчанию Алгоритм асинхроной обработки TCP

Имеется такой цикл обработки TCP сервера
Код:
Work_While:
 if(not Terminated)then
 begin
  
  //Прием данных от клиента (данные/отключение)
  int := Recv(...);
  if (int = INVALID_SOCKET) then begin
     if(WSAGetLastError = WSAEWOULDBLOCK)then
      goto Cont_Recv;
	  
	 //Error
	 goto Cont_Recv;
   end;
   //
   if(int <> 0)then begin
    //Получение данных от клиента
   end else begin
    //Отключение со стороны клиента 
   end;
   
  Cont_Recv:
  
   //Подключение клиента
   clientSocket := accept(...);
   if (clientSocket = INVALID_SOCKET) then
   begin
    if(WSAGetLastError = WSAEWOULDBLOCK)then
     goto No_NewClient;
    
	//Error
    goto No_NewClient;
   end;
   
   //Код обработки подключения
  
   No_NewClient:
 
  goto Work_While; 
 end;
Собственно вопрос. Как этот "алгорм" доделать чтоб цикл не свалился от ошибок памяти, а только уничтожал клиента в обработке которого произошли проблемы?

Что бы Вы суда еще добавили/ изменили чтоб добиться максимальной стабильности работы цыкла?

Крайне благодарен за ответы. И простите меня за предыдущую портянку.
vova65 вне форума Ответить с цитированием
Старый 11.04.2018, 16:59   #2
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Лучше выложите проект целиком.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 12.04.2018, 09:43   #3
vova65
Пользователь
 
Регистрация: 05.06.2011
Сообщений: 48
По умолчанию

Как только соберусь силами, немного его облагорожу и выложу.

Там вроде все работает (опираясь на многочасовые тесты). Вопрос только в стабильности. Который наверно решить только разбросом клиентов на н-количество серверов. Чтоб когда падал один, терялась часть активности клиентов и перенаправляло их на свободный сервер.

В общем, интересует стабильность. чтоб максимально (насколько это возможно) обрабатывать или хотя-бы детектировать ошибки..

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

Но пока я бомжара, надо максимум стабильности с одной железки.

Код как только, так сразу. Спасибо за отклик.
vova65 вне форума Ответить с цитированием
Старый 12.04.2018, 11:05   #4
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

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

Цитата:
Сообщение от vova65 Посмотреть сообщение
Там вроде все работает (опираясь на многочасовые тесты)
Программа вещь детерминированная и многочасовые тесты не являются показателем. Поведение программы зависит от воздействия и окружающей среды. В одних условиях она может работать как часы, в других условиях она будет постоянно падать.

Что это значит?
1) Эффект лаборатории. Пока у вас программа в стендовых испытаниях. Вы создали её домашние тепличные условия как только она выходит в мир начинаются непредвиденные отказы.
Цитата:
Сообщение от vova65 Посмотреть сообщение
Но пока я бомжара, надо максимум стабильности с одной железки.
Как практик вам советую начинайте тестировать на 2-х железках. Это совершенно изменит поведение программы. Появляется ошибки которых раньше не было.
1.2) Фрагментация памяти. При последовательном коде она не возникает, а вот при асинхронном шансы нарваться становятся больше. Особенно это проявляется когда у вас будет несколько машин, а не как сейчас пока одна. Правда у вас пока этого не разглядел - может есть, может нету.
2) Нагрузочное тестирование. В реальных условиях у вас будет несколько подключений.
Соответственно надо понимать как программа будет тормозить, а судя по таймайтам она будет тормозить. Вылетать. Причем может на 10 подключениях, а может на 100 а может и 10 000. Большые объемы передачи за рас. Много файлов, много сообщений.
3) А что будет с вашей программой если вдруг сеть начнёт терять сетевые пакеты? А ведь на обычном ПК пакеты не теряются днями. Когда как в приделах сети-города нарваться на потерю пакета можно в течение 5 минут. А при выходе в интернет и того чаще.
Как минимум это приведёт к отваливанию клиентов. И придётся на сервере чистить зомби подключения. А клиентам держать несколько соединений открытыми.


Я увидел код с потоками. Но не увидел где у вас синхронизация. Как минимум насторожил вызов одного класса из другого.
Выделение памяти у вас соответствует RAII? Вообще выделять и освобождать память лучше в главном потоке. Правда насколько понял это фоновый поток? Тогда в вашем случае допускаю что можно и в фоновом выделять, освобождать.

На вашем мести я бы разбил большой код на функции:
1) Во-первых такой код будет работать быстрее.
2) Во-вторых его проще протестировать.

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

Цитата:
Сообщение от vova65 Посмотреть сообщение
Чтоб сервера-менеджеры (которые мониторят состояние серверов-обработчиков) в крайнем случае вступали в силу и перенаправляли пользователей, перезапускали упавшие, детектили их работоспособность и все в таком духе.
Обязательно предусмотрите удалённые и самостоятельно перезапуск сервера. Но вообще основная проблема это DDOS атаки, которые приводят к отказу в обслуживании.
И защита от дурака. Если что-то может случиться то это непременно случится.
Что такое защита от дурака? К примеру двойная проверка перед удалением файлов/сообщений не знаю что у вас там. Или вывести на экран предупреждение о изменении настроек.
Черный и белый список пользователей и/или IP.

Правда это уже информационная безопасность нежели стабильность.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 15.04.2018, 00:42   #5
vova65
Пользователь
 
Регистрация: 05.06.2011
Сообщений: 48
По умолчанию

Большое спасибо за ответ.

Цитата:
Сообщение от Pavia Посмотреть сообщение
1.2) Фрагментация памяти.
Не вникал сильно в реализации менеджера памяти что виндового, что делфового. В чем там особенность?
Память (основные буферы) выделяю при старте сервера и использую самописный, незамысловатый механизм управления состоянием(занят/свободен) буферов.

Цитата:
Сообщение от Pavia Посмотреть сообщение
2) Нагрузочное тестирование.
Есть какие-то удобные и весьма функциональные инструменты для такого тестирования? А то с дуру написал своего клиента с разными сценариями работы. чтоб програть сервер по всем закаулкам логики.

Цитата:
Сообщение от Pavia Посмотреть сообщение
3) А что будет с вашей программой если вдруг сеть начнёт терять сетевые пакеты?
Это же вроде лежит на плечах WinSock библиотеки. При обнаружении потери пакета, пакет шлется заново - равно повышенной задержке. При нескольких попытках отправки пакета завершившихся потерей - отвал клиента.
Если обобщенно и в двух словах о TCP. Иначе, насколько я помню, там еще прилично нюансов с порядком пакетов, с долгим путешествием пакета который отправителем перешел в состояние потерянного и т.д, и т.п.

По поводу потоков, там их пока два, для GUI и поток для обработки сети.
Вроде сильной синхронизации пока не нужно.
Обратится к убитому потоку никто не должен (если поток какой-то магией не слетит).
А порядок записи-чтения данных в текущих моментах не нужен, коль не провтыкал что-то.

Цитата:
Сообщение от Pavia Посмотреть сообщение
1) Во-первых такой код будет работать быстрее.
2) Во-вторых его проще протестировать.
С проще, согласен. Насчет быстрее, CALL и перегон регистров в/из стек/а быстрее чем JMP?
vova65 вне форума Ответить с цитированием
Старый 15.04.2018, 01:03   #6
vova65
Пользователь
 
Регистрация: 05.06.2011
Сообщений: 48
По умолчанию

Чем можно тестировать WebSocket сервер?

Ибо у браузерах при малой задержке одно из таких извращений не шибко работает.
Код:
  var ws = [];
  var wsCount = 0;
  var limitCount = 0;
  var maxCount=3;
  //
  var iterCount = 0;
  var iterMaxCount = 20;
  function Test(){
   setInterval(function(){
    ADWeb(randomInt(0, 2),randomInt(0, 1));
   },5);
  }
  
  ws[0]=[0,0];
  ws[1]=[0,0];
  ws[2]=[0,0];
  
  function ADWeb(i,ds){
   if(ds==0){
    var SWS = function(){
	 ws[i][0] = 0;
	 //ws[i][0] = new WebSocket("ws://localhost:8081");
	 ws[wsCount] = new WebSocket("ws://192.168.1.103:8081");
	 ws[i][1] = 1;
	 if(i==0){ws[i][0].onopen = ADOpen0; ws[i][0].onclose = ADClose0;}
	 if(i==1){ws[i][0].onopen = ADOpen1; ws[i][0].onclose = ADClose1;}
	 if(i==2){ws[i][0].onopen = ADOpen2; ws[i][0].onclose = ADClose2;}
	 limitCount = limitCount+1;
	};
    if(ws[i][1] == 0){SWS();}
   }else{
    if(ws[i][1] == 2){
     ws[i][0].close();
	}
   }   
  }
  //
  function ADOpen0(){ws[0][1]=2;}
  function ADOpen1(){ws[1][1]=2;}
  function ADOpen2(){ws[2][1]=2;}
  //
  function ADClose0(){ws[0][1]=0;limitCount = limitCount-1;}
  function ADClose1(){ws[1][1]=0;limitCount = limitCount-1;}
  function ADClose2(){ws[2][1]=0;limitCount = limitCount-1;}
Опера и Хром вроде нормально. И у них onclose после закрытия соединения на уровне TCP. А вот в лисе onclose просходит на уровне WebSocket и это грозит как минимум еще некоторым временем жизни клиента на севере, хоть браузер считает что все отключено.

Отсюда и вопрос, чем бы лучше это все добро тестить? Ибо в таком варианте лиса, действительно лиса со всей ее хитростью. Тость, некоторое время все работает нормально, потом скорость подключений/отключений падает.

Уже аж подустал мучить снифер, систему логирования шагов и данных приложенния и думать где я дурак да что не учел.
vova65 вне форума Ответить с цитированием
Старый 15.04.2018, 01:21   #7
vova65
Пользователь
 
Регистрация: 05.06.2011
Сообщений: 48
По умолчанию

По делфи еще.

Как ловить ошибки памяти, насколько надежны оператива, шина, процессор. Насколько велик шанс что где-то в этой чудной троице байт 01 вдруг станет 02?

Как такое хотя бы отловить?

Допустим есть код
Код:
var a:array[0..1]of Byte;
var index:byte;
var rez:word;

procedure aAdd(index:byte);
begin
 rez:=a[index]+5;
end;

//Вызов
var i:byte;

a[0]:=1;
a[1]:=2;

i:=0;
aAdd(i);
Что будет если "i" из 0 вдруг станет 1? По выполнению кода все гладко, но результат...
Хоть это наверно и дико малій шанс, но все же. Как его определить, как побороть?

Лично у меня мысли только о доп проверках, о доп переменных, сверка входных и выходных данных.

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

Последний раз редактировалось vova65; 15.04.2018 в 01:25.
vova65 вне форума Ответить с цитированием
Старый 15.04.2018, 01:28   #8
vova65
Пользователь
 
Регистрация: 05.06.2011
Сообщений: 48
По умолчанию

DDOS атаки.

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

А в случае загрузки сетевого канала от DDOS атаки, мерятся тем у кого канал толще?) Или есть более разумные методы борьбы?
vova65 вне форума Ответить с цитированием
Старый 15.04.2018, 12:41   #9
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Цитата:
Сообщение от vova65 Посмотреть сообщение
Не вникал сильно в реализации менеджера памяти что виндового, что делфового. В чем там особенность?
В том что выделяем по 1024 кб и 1 кб. А потом бац и оказывается что эти 1 кб размазаны по всей памяти с шагом 1023 кб. Вроде бы 4095 МБ свободно, а 1 мб выделить не можешь так как все свободные куски имеют длину 1023 кб.


Цитата:
Сообщение от vova65 Посмотреть сообщение
Есть какие-то удобные и весьма функциональные инструменты для такого тестирования? А то с дуру написал своего клиента с разными сценариями работы. чтоб програть сервер по всем закаулкам логики.
Удобных не видел. да и не удобных тоже. В основам я так понял народ вручную пишет тесты. И да прогнать по всем закаулкам логики это фазинг, а нагрузочное это проверка на объемы данных.

Цитата:
Сообщение от vova65 Посмотреть сообщение
Это же вроде лежит на плечах WinSock библиотеки. При обнаружении потери пакета, пакет шлется заново - равно повышенной задержке. При нескольких попытках отправки пакета завершившихся потерей - отвал клиента.
Гладко было на бумаге, да покуда не нарвались на овраги. Дело в том что WinSock с этим не справляется.
Проблема в том что отвал клиента происходит если вообще то через 0٫5-2 часа. Для пользователя это будет выглядеть как зависшая программа. А на сервере просто будет висеть клиенты вернее они там будут копиться и копиться.


Цитата:
Сообщение от vova65 Посмотреть сообщение
Насчет быстрее, CALL и перегон регистров в/из стек/а быстрее чем JMP?
В большой функции оптимизатор не может разложить все данные по регистрам. Поэтому при jmp у вас будет ещё больше перегонов регистров в/из стек/а.


Цитата:
Сообщение от vova65 Посмотреть сообщение
Как ловить ошибки памяти, насколько надежны оператива, шина, процессор. Насколько велик шанс что где-то в этой чудной троице байт 01 вдруг станет 02?

Как такое хотя бы отловить?
Если память сломается, то это будет неустранимый сбой аппаратуры. Выйдет из строя блок или линий данных.
А что касается единичного сбоя одного бита. То вероятность отказа 1 раз в 10 лет для серверной памяти ECC коррекцией. Раз в 10 лет можно и компьютер перезагрузить.
А для обычной около 1 года.
В научных целях применяют сохранение состояние на диск и двойной расчёт что-бы сверить результаты.

А для вашей программы просто установить срок непрерывной работы 1 год. А после 1 час на профилактику - выключить компьютер включить компьютер.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Бинарные деревья. Итеративный алгоритм обработки now2 Паскаль, Turbo Pascal, PascalABC.NET 6 16.10.2014 07:28
Алгоритм обработки графических данных в ПК Notik Помощь студентам 5 16.12.2012 22:29
Алгоритм обработки матрицы max_scotch Помощь студентам 3 15.05.2012 10:32
TCP/IP параллельной обработки запросов zhenya.ya C/C++ Сетевое программирование 0 24.04.2011 21:31