Читаем О чём не пишут в книгах по Delphi полностью

Сначала модифицируем UDP-чат (см. разд. 2.1.10) таким образом, чтобы он использовал один сокет и для отправки, и для получения сообщений (пример SelectChat на компакт-диске). Вторая нить нам теперь не понадобится, всё будет делать главная форма. Процедуры создания сокета и отправки сообщений изменений не претерпели, главное дополнение — это то, что на форме появился таймер, в обработчике события OnTimer которого мы будем проверять с помощью select, пришло ли сообщение для сокета (листинг 2.24). С помощью таких простейших модификаций мы получили чат, который работает без распараллеливания и использует всего один сокет. Работать с таким чатом стало намного проще, потому что теперь ответ нужно посылать на тот же порт, с которого пришло сообщение, а не запоминать, какой порт для отправки какому из экземпляров чата соответствует.

Примечание

Несмотря на эти изменения, новая версия UDP-чата может обмениваться сообщениями со старой, т. к. протокол обмена остался неизменным.

Листинг 2.24. Проверка готовности сокетов при обработке сообщения от таймера

// Реакция на таймер. С периодичностью, заданной таймером,

// проверяем, не пришли ли сообщения, и если пришли,

// получаем их.

procedure TChatForm.TimerChatTimer(Sender: TObject);

var

 // Множество сокетов для функции select.

 // Будет содержать только один сокет FSocket.

 SocketSet: TFDSet;

 // Тайм-аут для функции select

 Timeout: TTimeVal;

 // Буфер для получения сообщения.

 // Размер равен максимальному размеру UDP-дейтаграммы

 Buffer: array[0..65506] of Byte;

 Msg: string;

 // Адрес, с которого пришло сообщение

 RecvAddr: TSockAddr;

 RecvLen, AddrLen: Integer;

begin

 // Инициализируем множество сокетов,

 // т. е. очищаем его от случайного мусора

 FD_ZERO(SocketSet);

 // Добавляем в это множество сокет FSocket

 FD_SET(FSocket, SocketSet);

 // Устанавливаем тайм-аут равным нулю, чтобы

 // функция select ничего не ждала, а возвращала

 // готовность сокетов на момент вызова.

 Timeout.tv_sec:= 0;

 Timeout.tv_usec:= 0;

 // Проверяем готовность сокета для чтения

 if select(0, @SocketSet, nil, nil, @Timout) = SOCKET_ERROR then

 begin

AddMessageToLog('Ошибка при проверке готовности сокета: ' + GetErrorString);

 Exit;

 end;

 // Проверяем, оставила ли функция select сокет в множестве.

 //Если оставила, значит, во входном буфере сокета есть данные.

 if FD_ISSET(FSocket, SocketSet) then

 begin

AddrLen:= SizeOf(RecvAddr); // Получаем дейтаграмму

RecvLen:=

 recvfrom(FSocket, Buffer, SizeOf(Buffer), 0, RecvAddr, AddrLen);

 // Так как UDP не поддерживает соединение, ошибку при вызове recvfrom

// мы можем получить, только если случилось что-то совсем

 // экстраординарное.

 if RecvLen < 0 then

 begin

AddMessageToLog('Ошибка при получении сообщения: ' +

GetErrorString);

 Exit;

 end;

// Устанавливаем нужный размер строки

SetLength(Msg, RecvLen);

 // и копируем в неё дейтаграммы из буфера

if RecvLen > 0 then Move(Buffer, Msg[1], RecvLen);

 AddMessageToLog('Сообщение с адреса ' + inet_ntoa(RecvAddr.sin_port) +

 ':' + IntToStr(ntohs(RecvAddr.sin_port)) + ': ' + Msg);

Перейти на страницу:

Похожие книги

1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных