<?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=330489&amp;view=findpost&amp;p=2883165</guid>
        <pubDate>Tue, 26 Apr 2011 17:35:33 +0000</pubDate>
        <title>WinSock, функция select, зависание сервера</title>
        <link>https://forum.sources.ru/index.php?showtopic=330489&amp;view=findpost&amp;p=2883165</link>
        <description><![CDATA[Mr.Delphist: Правильно ли я понимаю, что хочется &quot;неблокирующих сокетов&quot;?<br>http://www.rsdn.ru/forum/network/1262011.flat.aspx]]></description>
        <author>Mr.Delphist</author>
        <category>Delphi: Сетевое программирование</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=330489&amp;view=findpost&amp;p=2878088</guid>
        <pubDate>Mon, 18 Apr 2011 13:03:45 +0000</pubDate>
        <title>WinSock, функция select, зависание сервера</title>
        <link>https://forum.sources.ru/index.php?showtopic=330489&amp;view=findpost&amp;p=2878088</link>
        <description><![CDATA[MDmitry: Есть, пробовал менять значения, не помогло :(]]></description>
        <author>MDmitry</author>
        <category>Delphi: Сетевое программирование</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=330489&amp;view=findpost&amp;p=2877963</guid>
        <pubDate>Mon, 18 Apr 2011 10:44:13 +0000</pubDate>
        <title>WinSock, функция select, зависание сервера</title>
        <link>https://forum.sources.ru/index.php?showtopic=330489&amp;view=findpost&amp;p=2877963</link>
        <description><![CDATA[Fr0sT: У select есть таймаут]]></description>
        <author>Fr0sT</author>
        <category>Delphi: Сетевое программирование</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=330489&amp;view=findpost&amp;p=2877735</guid>
        <pubDate>Mon, 18 Apr 2011 04:42:29 +0000</pubDate>
        <title>WinSock, функция select, зависание сервера</title>
        <link>https://forum.sources.ru/index.php?showtopic=330489&amp;view=findpost&amp;p=2877735</link>
        <description><![CDATA[MDmitry: Доброго времени суток.<br>
Можно ли как-нибудь сделать так, чтобы сервер не зависал, не выделяя accept в отдельную нить?<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">unit CServer;</div><div class="code_line">{ Класс сервера</div><div class="code_line">}</div><div class="code_line">&nbsp;</div><div class="code_line">interface</div><div class="code_line">&nbsp;</div><div class="code_line">uses Classes,SysUtils,WinSock,Dialogs,StdCtrls,CPredokClientServer,FGetErrorString;</div><div class="code_line">&nbsp;</div><div class="code_line">// Информация о поключившемся клиенте</div><div class="code_line">type</div><div class="code_line">&nbsp;&nbsp;PConnection=^TConnection; &nbsp; &nbsp; // Информация о поключившемся клиенте</div><div class="code_line">&nbsp;&nbsp;TConnection=record</div><div class="code_line">&nbsp;&nbsp; &nbsp;ClientAddr:string; &nbsp; &nbsp; // Строковое представление адреса клиента</div><div class="code_line">&nbsp;&nbsp; &nbsp;ClientSocket:TSocket; &nbsp;// Сокет, созданный accept для взаимодействия с клиентом</div><div class="code_line">&nbsp;&nbsp; &nbsp;Deleted:Boolean; &nbsp; &nbsp; &nbsp; // Если FALSE, то соединение с клиентом утеряно</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">type</div><div class="code_line">&nbsp;&nbsp;TServer=class(TPredokClientServer)</div><div class="code_line">&nbsp;&nbsp;private</div><div class="code_line">&nbsp;&nbsp; &nbsp;FClientSocket:TSocket; &nbsp; &nbsp; &nbsp; &nbsp;// Сокет клиента</div><div class="code_line">&nbsp;&nbsp; &nbsp;FClientSocketAddr:TSockAddr; &nbsp;// Адрес клиента</div><div class="code_line">&nbsp;&nbsp; &nbsp;FConnections:TList; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Список подключившихся клиентов</div><div class="code_line">&nbsp;&nbsp; &nbsp;FMemoLog:TMemo;</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Привязка сокета к адресу</div><div class="code_line">&nbsp;&nbsp; &nbsp;procedure PrivyazkaKAdresu(MemoLog:TMemo);</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Создание соединения с клиентом</div><div class="code_line">&nbsp;&nbsp; &nbsp;procedure SozdatSoedineniyeSKlientom;</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Принять сообщение</div><div class="code_line">&nbsp;&nbsp; &nbsp;procedure PrinyatSoobchsheniye(var Connection: TConnection);</div><div class="code_line">&nbsp;&nbsp;public</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Запуск сервера</div><div class="code_line">&nbsp;&nbsp; &nbsp;procedure StartServer(IpAddres:string;Port:word;TypeProtokol,TypeSocket:char;MemoLog:TMemo);</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;</div><div class="code_line">implementation</div><div class="code_line">&nbsp;</div><div class="code_line">// ---------- Запуск сервера ---------------------------------------------------</div><div class="code_line">// - IpAddres - ip-адрес</div><div class="code_line">// - Port - номер порта</div><div class="code_line">// - TypeProtokol - тип сокера (UDP,TCP)</div><div class="code_line">// - TypeSocket - тип сокета (С - сервер, К - клиент)</div><div class="code_line">// - MemoLog - Лог</div><div class="code_line">procedure TServer.StartServer(IpAddres:string;Port:word;TypeProtokol,TypeSocket:char;MemoLog:TMemo);</div><div class="code_line">begin</div><div class="code_line">FMemoLog:=MemoLog;</div><div class="code_line">// Создание сокета</div><div class="code_line">CreateSocket(IpAddres,Port,TypeProtokol,TypeSocket);</div><div class="code_line">// Привязка сокета к адресу</div><div class="code_line">PrivyazkaKAdresu(MemoLog);</div><div class="code_line">// Создание соединения с клиентом</div><div class="code_line">SozdatSoedineniyeSKlientom;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// ---------- Привязка сокета к адресу -----------------------------------------</div><div class="code_line">procedure TServer.PrivyazkaKAdresu;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;// Сокет, созданный с помощью функции socket не привязан ни к какому адрему.</div><div class="code_line">&nbsp;&nbsp;// Привязка осуществляется функцией bind.</div><div class="code_line">&nbsp;&nbsp;// function bind(s:TSocket; var addr:TSockAddr; namelen:Integer): Integer;</div><div class="code_line">&nbsp;&nbsp;// - s - дескриптор сокета, который привязывается к адресу</div><div class="code_line">&nbsp;&nbsp;// - addr - адрес, к которому требуется привязать сокет</div><div class="code_line">&nbsp;&nbsp;// - namelen - длина структуры, содержащей адрес</div><div class="code_line">&nbsp;&nbsp;if bind(FSocket,FSocketAddr,SizeOf(TSockAddr)) = SOCKET_ERROR</div><div class="code_line">&nbsp;&nbsp; &nbsp;then</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;MessageDlg(&#39;Ошибка при привязке сокета к адресу &#39; + GetErrorString, mtError, [mbOK], 0);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end</div><div class="code_line">&nbsp;&nbsp; &nbsp;else FMemoLog.Lines.Append(&#39;Сервер успешно запущен&#39;);</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// ---------- Создание соединения с клиентом -----------------------------------</div><div class="code_line">procedure TServer.SozdatSoedineniyeSKlientom;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;TimeOut:TimeVal; &nbsp; &nbsp; // Таймаут для функции select</div><div class="code_line">&nbsp;&nbsp;SetSockets:TFDSet; &nbsp; // Множество сокетов для функции select</div><div class="code_line">&nbsp;&nbsp;ClientAddrLen:Integer;</div><div class="code_line">&nbsp;&nbsp;NewConnection:PConnection; // Вспомогательная переменная, использующаяся при создании нового соединения</div><div class="code_line">&nbsp;&nbsp;x:word;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;FConnections:=TList.Create;</div><div class="code_line">&nbsp;&nbsp;// Перевод сокета в режим ожидания соединения</div><div class="code_line">&nbsp;&nbsp;// function listen(s:TSocket; backlog:Integer): Integer;</div><div class="code_line">&nbsp;&nbsp;// - s - дескриптор сокета, который переводится в режим ожидания</div><div class="code_line">&nbsp;&nbsp;// - backlog - размер очереди подключений (для сокета, находящегося в режиме</div><div class="code_line">&nbsp;&nbsp;// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ожидания, создаётся очередь подключений). Максимально возможный</div><div class="code_line">&nbsp;&nbsp;// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; размер очереди</div><div class="code_line">&nbsp;&nbsp;// Функция вовращает 0 в случае успешного завершения или SOCKET_ERROR в случае</div><div class="code_line">&nbsp;&nbsp;// ошибки.</div><div class="code_line">&nbsp;&nbsp;// Когда клиент вызывает функцию connect, и по указанному в ней адресу имеется</div><div class="code_line">&nbsp;&nbsp;// сокет, находящийся в режиме ожидания подключения, то информация о клиенте</div><div class="code_line">&nbsp;&nbsp;// помещается в очередь подключений этого сокета.</div><div class="code_line">&nbsp;&nbsp;if listen(FSocket, SOMAXCONN)=SOCKET_ERROR</div><div class="code_line">&nbsp;&nbsp; &nbsp;then MessageDlg(&#39;Невозможно установить сокет в режим прослушивания. &#39;+GetErrorString,mtError,[mbOK],0);</div><div class="code_line">&nbsp;&nbsp;// Устанавливаем таймаут, равный 0, чтобы select ничего не ждала, а возвращала готовность</div><div class="code_line">&nbsp;&nbsp;// сокетов на момент вызова</div><div class="code_line">&nbsp;&nbsp;Timeout.tv_sec:=0; &nbsp; &nbsp;// число секунд</div><div class="code_line">&nbsp;&nbsp;Timeout.tv_usec:=0; &nbsp; // число микросекунд</div><div class="code_line">&nbsp;&nbsp;// Начало цикла для подключения и общения с клиентами</div><div class="code_line">&nbsp;&nbsp;repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Сначала проверяем, готов ли слушающий сокет. Если он готов, это означает,</div><div class="code_line">&nbsp;&nbsp; &nbsp;// что есть подключившийся, но не обработанный функцией accept клиент</div><div class="code_line">&nbsp;&nbsp; &nbsp;// procedure FD_ZERO(var FDSet:TFDSet); - инициализирует множество FDSet</div><div class="code_line">&nbsp;&nbsp; &nbsp;FD_ZERO(SetSockets);</div><div class="code_line">&nbsp;&nbsp; &nbsp;// procedure FDSet(Socket:TSocket; var FDSet:TFDSet); - добавляет сокет Socket в множество FDSet</div><div class="code_line">&nbsp;&nbsp; &nbsp;FD_SET(FSocket,SetSockets);</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Проверка готовности сокета</div><div class="code_line">&nbsp;&nbsp; &nbsp;// function select(nfds:Integer; readfds,writefds,exceptfds:PFDSet; timeout:PTimeVal): LongInt;</div><div class="code_line">&nbsp;&nbsp; &nbsp;// - nfds - оставлен только для совместимости со старыми версиями библиотеки сокетов, в новых игнорируется</div><div class="code_line">&nbsp;&nbsp; &nbsp;// - readfds, writefds, exceptfds - указатели на множество сокетов, которые нужно проверять</div><div class="code_line">&nbsp;&nbsp; &nbsp;// &nbsp; (не будут блокировать нить readfds-recv,recvfrom; writefds-send,sento;</div><div class="code_line">&nbsp;&nbsp; &nbsp;// &nbsp; &nbsp;exceptfds - неудача попытки соединения, получения высокоуровневых данных)</div><div class="code_line">&nbsp;&nbsp; &nbsp;// - timeout - время, которое функция будет ожидать, пока хотя бы один из сокетов не будет готов к требуемой операции</div><div class="code_line">&nbsp;&nbsp; &nbsp;if select(0,@SetSockets,nil,nil,@Timeout)=SOCKET_ERROR</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;then MessageDlg(&#39;Ошибка при проверке готовности слушающего сокета. &#39; + GetErrorString, mtError, [mbOK], 0);</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Если функция select оставила сокет в множестве, значит, зафиксировано подключение клиента, и функция accept</div><div class="code_line">&nbsp;&nbsp; &nbsp;// не приведёт к блокированию нити.</div><div class="code_line">&nbsp;&nbsp; &nbsp;// procedure FD_ISSET(Socket:TSocket; FDSet:TFDSet) - определяет, входит ли Socket в множество FDSet</div><div class="code_line">&nbsp;&nbsp; &nbsp;if FD_ISSET(FSocket,SetSockets)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ClientAddrLen:=SizeOf(FClientSocketAddr);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// Ожидаем подключение клиента</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// Извлечение из очереди соединений информации соединении и создание сокета для</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// его обслуживания</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// function accept(s:TSocket; addr:PSockAddr; addrlen: PInteger): TSocket;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// - s - сокет, который находится в режиме ожидания соединения</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// - addr - адрес клиента, установившего соединение</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// - addrlen - длина буфера, в который будет помещён адрес клиента</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// В случае ошибки возвращается INVALID_SOCKET, при успешном завершении - дескриптор</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// сокета, созданного библиотекой сокетов и предназначенного для обслуживания</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// данного соединения. Этот сокет уже привязан к адресу и соединён с сокетом клиента,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// установившего соединение.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// Если на момент вызова функции accept очередь соединений пуста, то нить,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// вызвавшая её блокируется до тех пор, пока какой-нибудь клиент не полключиться</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// к серверу.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;FClientSocket:=accept(FSocket,@FClientSocketAddr,@ClientAddrLen);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if FClientSocket=INVALID_SOCKET then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MessageDlg(&#39;Ошибка при ожидании подключения клиента: &#39; + GetErrorString, mtError, [mbOK], 0);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;end</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Создаём в динамической памяти новый экземпляр TConnection и заполняем его данными, соответствующими</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// подключившемуся клиенту</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;New(NewConnection);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NewConnection.ClientSocket:=FClientSocket;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NewConnection.ClientAddr:=Format(&#39;%u.%u.%u.%u:%u&#39;, [</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Ord(FClientSocketAddr.sin_addr.S_un_b.s_b1),</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Ord(FClientSocketAddr.sin_addr.S_un_b.s_b2),</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Ord(FClientSocketAddr.sin_addr.S_un_b.s_b3),</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Ord(FClientSocketAddr.sin_addr.S_un_b.s_b4),</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ntohs(FClientSocketAddr.sin_port)]);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NewConnection.Deleted:=False;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Добавляем соединение в список</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FConnections.Add(NewConnection);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FMemoLog.Lines.Append(&#39;Зафиксировано подключение с адреса &#39;+NewConnection.ClientAddr);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if FConnections.Count&#62;0</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// Теперь проверяем готовность всех сокетов подключившихся клиентов</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;FD_ZERO(SetSockets);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for x:=0 to FConnections.Count-1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;do FD_SET(PConnection(FConnections[x])^.ClientSocket,SetSockets);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if select(0, @SetSockets, nil, nil, @Timeout) = SOCKET_ERROR</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;then MessageDlg(&#39;Ошибка при проверке готовности слушающего сокета. &#39; + GetErrorString, mtError, [mbOK], 0);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// Проверяем, какие сокеты select оставила в множестве и вызываем ...</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for x:=0 to FConnections.Count-1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;do if FD_ISSET(PConnection(FConnections[x])^.ClientSocket,SetSockets)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;then PrinyatSoobchsheniye(PConnection(FConnections[x])^); &nbsp; </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// Проверяем отключвшихся клиентов</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for x:=FConnections.Count-1 downto 0</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;do if PConnection(FConnections[x])^.Deleted</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;closesocket(PConnection(FConnections[x])^.ClientSocket);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Dispose(PConnection(FConnections[x]));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FConnections.Delete(x);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Sleep(100);</div><div class="code_line">&nbsp;&nbsp;until False;</div><div class="code_line">&nbsp;&nbsp;for x:=FConnections.Count-1 downto 0 do</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;closesocket(PConnection(FConnections[x])^.ClientSocket);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Dispose(PConnection(FConnections[x]));</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;FConnections.Free;</div><div class="code_line">&nbsp;&nbsp;FMemoLog.Lines.Append(&#39;Сервер завершил работу&#39;);</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// ---------- Принять сообщение ------------------------------------------------</div><div class="code_line">procedure TServer.PrinyatSoobchsheniye(var Connection: TConnection);</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Mes:string[255]; &nbsp; // Сообщение клиента</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;// Если выполнение функции не дойдёт до конца, это значит, что связь</div><div class="code_line">&nbsp;&nbsp;// с клиентом по тем или иным причинам потеряна. В этом случае</div><div class="code_line">&nbsp;&nbsp;// поле Deleted останется равным False, и ресурсы, выделенные для</div><div class="code_line">&nbsp;&nbsp;// данного клиента, будут освобождены. Если же функция выполнится</div><div class="code_line">&nbsp;&nbsp;// до конца, полю Deleted будет вновь присвоено значение False,</div><div class="code_line">&nbsp;&nbsp;// т.е. ресурсы не будут удалены.</div><div class="code_line">&nbsp;&nbsp;Connection.Deleted:=True;</div><div class="code_line">&nbsp;&nbsp;// Принять сообщение</div><div class="code_line">&nbsp;&nbsp;// function recv(s:TSocket; var buf,len,flags:Integer):Integer;</div><div class="code_line">&nbsp;&nbsp;// - s - сокет, который служит для передачи данных</div><div class="code_line">&nbsp;&nbsp;// - buf - буфер, в котором хранятся данные для оправки</div><div class="code_line">&nbsp;&nbsp;// - len - размер этих данных в байтах</div><div class="code_line">&nbsp;&nbsp;// - flags - указывает некоторые дополнительные опциии, которые в большинстве</div><div class="code_line">&nbsp;&nbsp;// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; случаев не нужны</div><div class="code_line">&nbsp;&nbsp;case recv(Connection.ClientSocket,Mes,SizeOf(Mes),0) of</div><div class="code_line">&nbsp;&nbsp; &nbsp;-1: // Ошибка при принятии</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;MessageDlg(&#39;Произошла ошибка при чтении &#39;+GetErrorString,mtError,[mbOK],0);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;0: &nbsp;// Клиент закрыл соединение</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;FMemoLog.Lines.Append(&#39;Клиент &#39;+Connection.ClientAddr+&#39; закрыл соединение &#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end</div><div class="code_line">&nbsp;&nbsp; &nbsp;else FMemoLog.Lines.Append(Mes);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;// Если выполнение дошло до этого места, значит, связь с клиентом</div><div class="code_line">&nbsp;&nbsp;// не потеряна, и ресурсы освобождать не надо.</div><div class="code_line">&nbsp;&nbsp;Connection.Deleted := False;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">end.</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script> <br>
<br>
<span class="tag-color tag-color-named" data-value="gray" style="color: gray"><span class='tag-size' data-value='7' style='font-size:7pt;'>Добавлено <time class="tag-mergetime" datetime="2011-04-18T04:45:26+00:00">18.04.11, 04:45</time></span></span><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">unit CPredokClientServer;</div><div class="code_line">{ Класс, который содержит функции, являющиеся общими для клиента и сервера,</div><div class="code_line">&nbsp;&nbsp;а также некоторые другие для WinSock}</div><div class="code_line">&nbsp;</div><div class="code_line">interface</div><div class="code_line">&nbsp;</div><div class="code_line">uses</div><div class="code_line">&nbsp;&nbsp;SysUtils,Dialogs,WinSock,Windows,FGetErrorString;</div><div class="code_line">&nbsp;</div><div class="code_line">type</div><div class="code_line">&nbsp;&nbsp;TPredokClientServer=class</div><div class="code_line">&nbsp;&nbsp;public</div><div class="code_line">&nbsp;&nbsp; &nbsp;FSocket:TSocket; &nbsp; &nbsp; &nbsp; // Сокет</div><div class="code_line">&nbsp;&nbsp; &nbsp;FSocketAddr:TSockAddr; // Адрес, к которому привязывается сокет</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Описание структуры TSockAddr</div><div class="code_line">&nbsp;&nbsp; &nbsp;// - sin_family - семейство протоколов (для TCP/IP - PF_INET)</div><div class="code_line">&nbsp;&nbsp; &nbsp;// - sin_port - номер порта, к которому привязывается сокет</div><div class="code_line">&nbsp;&nbsp; &nbsp;// - sin_addr.S_addr - адрес для привязки сокета.</div><div class="code_line">&nbsp;&nbsp; &nbsp;// - sin_zero - должна быть заполнена нулями (не несёт никакой смысловой</div><div class="code_line">&nbsp;&nbsp; &nbsp;// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;нагрузки, нужно только для увеличения размера структуры</div><div class="code_line">&nbsp;&nbsp; &nbsp;// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;до 16 байтов</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Создание сокета</div><div class="code_line">&nbsp;&nbsp; &nbsp;procedure CreateSocket(IpAddres:string;Port:word;TypeProtokol,TypeSocket:char);</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">implementation</div><div class="code_line">&nbsp;</div><div class="code_line">// ---------- Создание сокета --------------------------------------------------</div><div class="code_line">// - IpAddres - ip-адрес</div><div class="code_line">// - Port - номер порта</div><div class="code_line">// - TypeProtokol - тип сокера (UDP,TCP)</div><div class="code_line">// - TypeSocket - тип сокета (С - сервер, К - клиент)</div><div class="code_line">procedure TPredokClientServer.CreateSocket(IpAddres:string;Port:word;TypeProtokol,TypeSocket:char);</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;// Формируем адрес сервера, к которому надо подключиться</div><div class="code_line">&nbsp;&nbsp;// FillChar - стандартная процедура Паскаля, некоторую область памяти заданными</div><div class="code_line">&nbsp;&nbsp;// значениями. В данном случае 0</div><div class="code_line">&nbsp;&nbsp;FillChar(FSocketAddr.sin_zero,SizeOf(FSocketAddr.sin_zero),0);</div><div class="code_line">&nbsp;&nbsp;// Семейство протоколов</div><div class="code_line">&nbsp;&nbsp;FSocketAddr.sin_family:=AF_INET;</div><div class="code_line">&nbsp;&nbsp;// Ip-адрес</div><div class="code_line">&nbsp;&nbsp;// inet_addr - для преобразования адреса из строки в 32-х битное число</div><div class="code_line">&nbsp;&nbsp;case TypeSocket of</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39;К&#39;: FSocketAddr.sin_addr.S_addr := inet_addr(PChar(IpAddres));</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39;С&#39;: FSocketAddr.sin_addr.S_addr := inet_addr(PChar(IpAddres));</div><div class="code_line">&nbsp;&nbsp; &nbsp;//&#39;С&#39;: FSocketAddr.sin_addr.S_addr:=htonl(INADDR_ANY); &nbsp; &nbsp; </div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;// Для совместимости со старыми версиями Delphi приводим константу INADDR_NONE</div><div class="code_line">&nbsp;&nbsp;// к типу u_long</div><div class="code_line">&nbsp;&nbsp;if FSocketAddr.sin_addr.S_addr=u_long(INADDR_NONE)</div><div class="code_line">&nbsp;&nbsp;then</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;MessageDlg(&#39;Синтаксическая ошибка в IP-адресе&#39;,mtError,[mbOK],0);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Exit;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;// Преобразование в сетевой формат</div><div class="code_line">&nbsp;&nbsp;// Функция htons служит для преобразования номера порта из привычного нам в</div><div class="code_line">&nbsp;&nbsp;// сетевой. Если номер порта оставить нулевым, то система сама выберет для</div><div class="code_line">&nbsp;&nbsp;// сокета свободный порт с номером от 1024 до 5000</div><div class="code_line">&nbsp;&nbsp;FSocketAddr.sin_port:=htons(Port);</div><div class="code_line">&nbsp;&nbsp;// Создание сокета</div><div class="code_line">&nbsp;&nbsp;// function socket (AF,SocketType,Protocol:Integer):TSocket;</div><div class="code_line">&nbsp;&nbsp;// - AF - какой стек протоколов используется (для TCP/IP - AF_INET)</div><div class="code_line">&nbsp;&nbsp;// - SocketType - тир сокета (SOCK_STREAM - потоковый, SOCK_DGRAM - дейтаграммный)</div><div class="code_line">&nbsp;&nbsp;// - Protocol - тип протокола TCP - потоковый, UDP - дейтаграммный</div><div class="code_line">&nbsp;&nbsp;case TypeProtokol of</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39;T&#39;:FSocket:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);</div><div class="code_line">&nbsp;&nbsp; &nbsp;&#39;U&#39;:FSocket:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;if FSocket = INVALID_SOCKET then</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;MessageDlg(&#39;Ошибка при создании сокета: &#39; + GetErrorString, mtError, [mbOK], 0);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Exit;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div></ol></div></div></div></div>]]></description>
        <author>MDmitry</author>
        <category>Delphi: Сетевое программирование</category>
      </item>
	
      </channel>
      </rss>
	