Чтение онлайн

на главную - закладки

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

Exit;

end

else

// Как обычно, "ошибку" WSAEWOULDBLOCK просто игнорируем

if WSAGetLastError <> WSAEWOULDBLOCK then

begin

AddMessageToLog('Ошибка при получении данных от клиента ' +

Connection.ClientAddr + ': ' + GetErrorString);

RemoveConnection;

Exit;

end;

end;

if Connection.Phase = tpSendString then

begin

//
Следующий этап — отправка строки. Код примерно такой же,

// как и в предыдущем этапе, но вместо recv используется send.

// Кроме того, отсутствует проверка на Res = 0, т.к. при

// использовании TCP send никогда не возвращает 0.

Res :=

send(Connection.ClientSocket, Connection.Msg[Connection.Offset + 1],

Connection.BytesLeft, 0);

if Res > 0 then

begin

Inc(Connection.Offset, Res);

Dec(Connection.BytesLeft, Res);

// Если Connection.BytesLeft = 0, значит, строка отправлена

// полностью.

if Connection.BytesLeft = 0 then

begin

AddMessageToLog('Клиенту ' + Connection.ClientAddr +

' отправлена строка: ' + Connection.Msg);

// Очищаем строку, престо сэкономить память

Connection.Msg := '';

// Следующий этап - снова получение длины строки от клиента

Connection.Phase := tpReceiveLength;

// Получено - 0 байт

Connection.Offset := 0;

// Осталось прочитать столько, сколько занимает целое число

Connection.BytesLeft := SizeOf(Integer);

end;

end

else

if WSAGetLastError <> WSAEWOULDBLOCK then

begin

AddMessageToLog('Ошибка при отправке данных клиенту ' +

Connection.ClientAddr + ': ' + GetErrorString);

RemoveConnection;

Exit;

end;

 end;

end;

В итоге мы получили сервер, достаточно устойчивый как к подключению множества клиентов, так и к нарушению протокола со стороны клиента. Для самостоятельной работы рекомендуем подумать о том, как можно сделать UDP-чат на неблокирующих сокетах. На самом деле он мало чем будет отличаться от рассмотренного чата на основе

select
. Просто при использовании
select
проверка возможности неблокирующего чтения из сокета проверяется предварительным вызовом этой функции, а в случае неблокирующих сокетов сначала вызывается
recvfrom
, а потом проверяется, было что-то прочитано, или же операция не может быть выполнена потому, что блокировки запрещены. Во всем остальном использование
select
и неблокирующих сокетов очень похоже, причем не только в данном случае, но и вообще.

2.1.17.

Параметры сокета

Каждый сокет обладает рядом параметров (опций), которые влияют на его работу. Существуют параметры уровня сокета, которые относятся к сокету как к объекту безотносительно используемого протокола и его уровня. Впрочем, некоторые параметры уровня сокета применимы не ко всем протоколам. Здесь мы не будем рассматривать все параметры сокета, а ограничимся лишь изложением методов доступа к ним и познакомимся с некоторыми самыми интересными параметрами.

Для получения текущего значения параметров сокета предусмотрена функция

getsockopt
, для изменения —
setsockopt
. Прототипы этих функций выглядят следующим образом:

function getsockopt(s: TSocket; level, optname: Integer; optval: PChar; var optlen: Integer): Integer;

function setsockopt(s: TSocket; level, optname: Integer; optval: PChar; optlen: Integer): Integer;

Параметры у функций почти одинаковы. Первый задает сокет, параметры которого следует узнать или изменить. Второй указывает, параметр какого уровня следует узнать или изменить. Третий задает сам параметр сокета. Параметр

optval
содержит указатель на буфер, в котором хранится значение параметра, a
optlen
— размер этого буфера (разные параметры имеют различные типы и поэтому размер буфера может быть разным). Функция
getsockopt
сохраняет значение параметра в буфере, заданном указателем
optval
. Длина буфера передается через параметр
optlen
, и через него же возвращается размер, реально понадобившийся для хранения параметра. У функции
setsockopt
параметр
optval
содержит указатель на буфер, хранящий новое значение параметра сокета, a
optlen
— размер этого буфера.

Чаще всего параметры сокета имеют целый или логический тип. В обоих случаях параметр

optval
должен содержать указатель на значение типа
Integer
. Для логического типа любое ненулевое значение интерпретируется
True
, нулевое — как
False
. Два достаточно важных параметра сокета — размеры входного и выходного буфера. Это параметры уровня сокета (
SOL_SOCKET
), их номера задаются константами
SO_RCVBUF
и
SO_SNDBUF
. Например, чтобы получить размер входного буфера сокета, нужно выполнить код листинга 2.34.

Листинг 2.34. Получение размера входного буфера сокета

var

 Val, Len: Integer;

 S: TSocket;

begin

 ...

 Len := SizeOf(Integer);

 getsockopt(S, SOL_SOCKET, SO_RCBUF, @Val, Len);

После выполнения этого кода размер буфера будет содержаться в переменной

Val
.

Немного поэкспериментировав, можно обнаружить, что размер входного и выходного буфера равен 8192 байтам как для TCP, так и для UDP. Тем не менее это не мешает отправлять и получать дейтаграммы большего размера (для UDP), а также накапливать в буфере больший объем информации (для TCP). При получении данных это достигается за счет использования более низкоуровневых буферов, чем буфер самого сокета. Можно даже установить входной буфер сокета равным нулю — тогда все поступившие данные будут храниться в низкоуровневых буферах. Однако делать так не рекомендуется, т.к. при этом снижается производительность.

Поделиться:
Популярные книги

Барон играет по своим правилам

Ренгач Евгений
5. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Барон играет по своим правилам

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Герцогиня в ссылке

Нова Юлия
2. Магия стихий
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Герцогиня в ссылке

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Истинная поневоле, или Сирота в Академии Драконов

Найт Алекс
3. Академия Драконов, или Девушки с секретом
Любовные романы:
любовно-фантастические романы
6.37
рейтинг книги
Истинная поневоле, или Сирота в Академии Драконов

Кодекс Охотника. Книга VI

Винокуров Юрий
6. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга VI

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сама себе хозяйка

Красовская Марианна
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Сама себе хозяйка

Душелов. Том 3

Faded Emory
3. Внутренние демоны
Фантастика:
альтернативная история
аниме
фэнтези
ранобэ
хентай
5.00
рейтинг книги
Душелов. Том 3

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Стеллар. Заклинатель

Прокофьев Роман Юрьевич
3. Стеллар
Фантастика:
боевая фантастика
8.40
рейтинг книги
Стеллар. Заклинатель

Возвышение Меркурия. Книга 5

Кронос Александр
5. Меркурий
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 5