<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=372387&amp;view=findpost&amp;p=3276070</guid>
        <pubDate>Mon, 18 Feb 2013 07:23:16 +0000</pubDate>
        <title>ServerSocket в режиме ThreadBlocking</title>
        <link>https://forum.sources.ru/index.php?showtopic=372387&amp;view=findpost&amp;p=3276070</link>
        <description><![CDATA[Fr0sT: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=372387&view=findpost&p=3273754'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Marchelo2012 &#064; <time class="tag-quote__quoted-time" datetime="2013-02-13T14:46:31+04:00">13.02.13, 10:46</time></span><div class='quote '>простым и неправильным путём:</div></div><br>
Ошибка. Этот путь как раз непростой, но самый правильный для сервера (тем паче с кол-вом клиентов &gt; 20). Просто почитай про асинхронный режим работы - хотя бы статью Антона Григорьева &quot;Сокеты в Delphi&quot;. Вкратце - в режиме non blocking всё управляется событиями: клиент подключился - событие, клиент отправил данные - событие. Причем событие чтения может приходить несколько раз, пока не будет переправлен весь пакет данных. Поэтому рецепт простой:<br>
1) Создать класс-наследник от TClientSocket с полем буфера, куда будут собираться прочитанные данные.<br>
2) По событию ClientRead считывать данные в буфер и проверять, всё ли сообщение принято (при этом должна быть какая-то сигнатура окончания сообщения - перевод строки, или нулевой символ, или что-то еще).<br>
3) Когда данные полностью приняты, обрабатывать сообщение, отвечать клиенту &quot;ОК&quot; и пр.]]></description>
        <author>Fr0sT</author>
        <category>Delphi: Сетевое программирование</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=372387&amp;view=findpost&amp;p=3274101</guid>
        <pubDate>Wed, 13 Feb 2013 16:59:12 +0000</pubDate>
        <title>ServerSocket в режиме ThreadBlocking</title>
        <link>https://forum.sources.ru/index.php?showtopic=372387&amp;view=findpost&amp;p=3274101</link>
        <description><![CDATA[medved_68: <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=372387&view=findpost&p=3273754'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Marchelo2012 &#064; <time class="tag-quote__quoted-time" datetime="2013-02-13T10:46:31+00:00">13.02.13, 10:46</time></span><div class='quote '>То есть все сообщения принимаются, но принимаются они &quot;урезанными&quot;.</div></div><br>
Они не &quot;урезанные&quot;. Сообщение целиком не помещено в пакет. Всего лишь. А ты принял пакет и не проверив, все ли тебе передал клиент, пихаешь его в Мемо. :D Так, как ты сам уже понял - делать нельзя. Что бы решить такого рода проблему и добавочно избежать &quot;склеивания&quot; строк и помещал в самом начале передачи блока его размер. Сервер, скачав эти байты и поместив их в переменную, скажем Интегер, уже точно ЗНАЛ, сколько ему еще осталось принять.  :D Это по первому варианту.<br>
По второму только одно - мдя....Смотри:<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=372387&view=findpost&p=3273754'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Marchelo2012 &#064; <time class="tag-quote__quoted-time" datetime="2013-02-13T10:46:31+00:00">13.02.13, 10:46</time></span><div class='quote '><div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">procedure TServerThread.ClientExecute;</div><div class="code_line">var i:integer;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Form1.Memo1.Lines.Insert(0,&#39;&#62; &#39;+ClientSocket.ReceiveText);</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script></div></div>Так из ПОТОКА работать с визуальными компонентами не то, что нельзя.... :D У потока есть процедура синхронизации - вот ее и необходимо пользовать. Разумеется, это не отменяет сказанного выше, т.к. &quot;урезание&quot; и &quot;склеивание&quot; будет происходить и в этом случае. :D Так что... :-?]]></description>
        <author>medved_68</author>
        <category>Delphi: Сетевое программирование</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=372387&amp;view=findpost&amp;p=3273754</guid>
        <pubDate>Wed, 13 Feb 2013 10:46:31 +0000</pubDate>
        <title>ServerSocket в режиме ThreadBlocking</title>
        <link>https://forum.sources.ru/index.php?showtopic=372387&amp;view=findpost&amp;p=3273754</link>
        <description><![CDATA[Marchelo2012: Добрый день, уважаемые программисты&#33; Опишу вкратце решаемую задачу.<br>
Необходим сервер приема данных (текстовые сообщения в 15-20 строк). Данные отправляют клиенты (устройства, которые <br>
<br>
связываются с сервером по каналу  GPRS). Всего их 2000-2500 шт., каждый отправляет сообщение 1 раз в 5 минут, <br>
<br>
соответственно на сервер примерно 5-20 обращений в секунду. Принятое сообщение необходимо поместить в Memo. Вроде бы задача <br>
<br>
в 3 строки, но корректно настроить работу сервера не удается. Пошел сначала простым и неправильным путём:<br>
1. ServerSocket в режиме stNonBlocking<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">procedure TForm1.ServerSocket1ClientRead(Sender: TObject;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Socket: TCustomWinSocket);</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;{От клиента получено сообщение - выводим его в Memo1}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Memo2.Lines.Insert(0,&#39;Message received from client&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Memo1.Lines.Insert(0,&#39;&#62; &#39;+Socket.ReceiveText);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if RadioButton1.Checked then begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;ServerSocket1.Socket.Connections[0].SendText(&#39;OK&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;ServerSocket1.Socket.Connections[0].Close;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div></ol></div></div></div></div><br>
В таком режиме при появлении события посылки сообщения от клиента, сообщение записывается в Memo. Но, естественно, новое <br>
<br>
соединение появляется раньше, чем происходит запись принятого текста. <br>
То есть все сообщения принимаются, но принимаются они &quot;урезанными&quot;. Ах да, забыл написать, что клиенту после приема от него <br>
<br>
сообщения надо отправить &quot;OK&quot;, чтобы устройство знало, что пакет принят и можно отключаться.<br>
2. Было принято решение использовать сервер (как вы уже догадались=)) в режиме stThreadBlocking. При небольшом количестве <br>
<br>
клиентов все работает прекрасно (вообщем то как и первый вариант), но при количестве 2000-2500 клиентов сообщения в Memo <br>
<br>
вообще пишутся пустыми, и только изредка там появляется 1-2 строки от клиента, но этого, само собой, не достаточно. Вот <br>
<br>
код:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">//описываем класс</div><div class="code_line">type</div><div class="code_line">&nbsp;&nbsp; &nbsp;TServerThread = class(TServerClientThread)</div><div class="code_line">&nbsp;&nbsp; &nbsp;procedure ClientExecute; override;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">//описываем процедуру, которая будет срабатывать при запуске &quot;нити&quot;</div><div class="code_line">procedure TServerThread.ClientExecute;</div><div class="code_line">var i:integer;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Form1.Memo1.Lines.Insert(0,&#39;&#62; &#39;+ClientSocket.ReceiveText);</div><div class="code_line">&nbsp;&nbsp; &nbsp;ClientSocket.SendText(&#39;OK&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp;ClientSocket.Close;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Terminate;</div><div class="code_line">end;</div><div class="code_line">...</div><div class="code_line">procedure TForm1.ServerSocket1GetThread(Sender: TObject;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;ClientSocket: TServerClientWinSocket;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;var SocketThread: TServerClientThread);</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Memo2.Lines.Insert(0,&#39;Get Thread&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;//создаем экземпляр класса с приоритетом реального времени</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;SocketThread:=TServerThread.Create(true, ClientSocket);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;SocketThread.Priority:=tpTimeCritical;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;SocketThread.Resume;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div></ol></div></div></div></div><br>
Подскажите, как модернизировать код, чтобы сервер справлялся с поставленной задачей? В процедуре <br>
<br>
TServerThread.ClientExecute нужно что-то дописать, чтобы сервер ждал полного сообщения от клиента, а уже потом отсылал ему <br>
<br>
&quot;OK&quot; и закрывал соединение. Финальная строка в тексте, полученном от клиента, всегда начинается с &quot;REND&quot;...<br>
<br>
p.s. не забываем, что клиенты работают по gprs, соединение соответственно не &quot;самолёт&quot;... Заранее спасибо&#33;]]></description>
        <author>Marchelo2012</author>
        <category>Delphi: Сетевое программирование</category>
      </item>
	
      </channel>
      </rss>
	