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

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

Жанры

О чём не пишут в книгах по 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). При получении данных это достигается за счет использования более низкоуровневых буферов, чем буфер самого сокета. Можно даже установить входной буфер сокета равным нулю — тогда все поступившие данные будут храниться в низкоуровневых буферах. Однако делать так не рекомендуется, т.к. при этом снижается производительность.

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

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

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

An ordinary sex life

Астердис
Любовные романы:
современные любовные романы
love action
5.00
рейтинг книги
An ordinary sex life

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь

Защитник

Кораблев Родион
11. Другая сторона
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Защитник

Неестественный отбор.Трилогия

Грант Эдгар
Неестественный отбор
Детективы:
триллеры
6.40
рейтинг книги
Неестественный отбор.Трилогия

Метаморфозы Катрин

Ром Полина
Фантастика:
фэнтези
8.26
рейтинг книги
Метаморфозы Катрин

Сирота

Ланцов Михаил Алексеевич
1. Помещик
Фантастика:
альтернативная история
5.71
рейтинг книги
Сирота

Хозяйка Междуречья

Алеева Елена
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Хозяйка Междуречья

В теле пацана 4

Павлов Игорь Васильевич
4. Великое плато Вита
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
В теле пацана 4

Ротмистр Гордеев 2

Дашко Дмитрий
2. Ротмистр Гордеев
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Ротмистр Гордеев 2

Неожиданный наследник

Яманов Александр
1. Царь Иоанн Кровавый
Приключения:
исторические приключения
5.00
рейтинг книги
Неожиданный наследник

Курсант: назад в СССР 2

Дамиров Рафаэль
2. Курсант
Фантастика:
попаданцы
альтернативная история
6.33
рейтинг книги
Курсант: назад в СССР 2

Сердце Дракона. Двадцатый том. Часть 2

Клеванский Кирилл Сергеевич
Сердце дракона
Фантастика:
фэнтези
5.00
рейтинг книги
Сердце Дракона. Двадцатый том. Часть 2

Треск штанов

Ланцов Михаил Алексеевич
6. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Треск штанов