Основные этапы работы с TServerSocket

Работа с сокетами в Delphi

Сокеты (от socket (англ.) — разъём, гнездо) — это программный интерфейс, обеспечивающий обмен информацией между процессами.

Одним из основных достоинств сокетного обмена информацией в сети можно назвать его гибкость. Главный принцип работы с сокетами состоит в отправке последовательности байт другому компьютеру, это может быть простое текстовое сообщение или файл.

Важно различать два типа сокетов: клиентские сокеты, и серверные сокеты.

Для работы с «клиентским» типом сокетов в Delphi существует компонент TClientSocket, с «серверными» сокетами можно работать при помощи компонента TServerSocket.

Установка компонентов

Зачастую компоненты TServerSocket и TClientSocket не входят в стандартный пакет установки Delphi, но их можно установить дополнительно.

Зайдите на вкладку компонентов «Internet», и проверьте присутствуют ли там компоненты TServerSocket и TClientSocket, если нет, то установите их. Зайдите в меню "Component/Install Packages", затем нажмите кнопку "Add". В открывшемся диалоговом окне нужно найти файл "dclsocketsXX.bpl" (он лежит в папке bin, которая находится в папке с Delphi), где XX - это числовой номер версии вашего Delphi. Найдите файл, нажмите "Открыть", а затем в окне "Install Packages" нажмите "OK". Теперь, во вкладке "Internet" появились два компонента - TServerSocket и TClientSocket.

Работа с клиентскими сокетами (TClientSocket)

1) Определение свойств Port и Host. Для успешного соединения свойствам Port и Host компонента TClientSocket необходимо присвоить некоторые значения. В свойстве Port нужно указать номер порта для подключения (1 – 65535, но лучше брать из диапозона 1001 – 65535, потому что номера до 1000 могут оказаться заняты системными службами).

Host — хост-имя или IP-адрес компьютера, с которым требуется соединиться. Например, rus.delphi.com или 192.128.0.0.

2) Открытие сокета.Будем рассматривать сокет как очередь символов, передающихся с одного компьютера на другой. Открыть сокет можно, вызвав метод Open (компонент TClientSocket) или присвоив значение True свойству Active. Тут нелишним будет поставить обработчик исключения на случай неудавшегося соединения.

Отправка/прием данных.

4) Закрытие сокета. По завершению обмена данными нужно закрыть сокет, вызвав метод Close компонента TClientSocket или присвоив значение False свойству Active.

Основные свойства компонента TClientSocket
Active Показатель того, открыт или закрыт сокет. Открыт – значение True, закрыт – значение False. Доступно для записи.
Host Хост-имя, с которым нужно соединиться
Address IP-адрес компьютера, с которым нужно соединиться. В отличие от Host, здесь может быть указан только IP. Разница состоит в том, что если в Host указано буквенное имя компьютера, то IP запросится у DNS
Port Номер порта компьютера, с которым нужно соединиться (1-65535)
ClientType Содержит тип передачи данных: ctBlocking — синхронная передача (OnRead и OnWrite не работают). Синхронный тип подключения подходит для поточного обмена данными; ctNonBlocking — асинхронная передача (отправка/приём данных может производиться при помощи событий OnRead и OnWrite)
Основные методы компонента TClientSocket
Open Открывает сокет (присвоение свойству Active значения True)
Close Закрывает сокет (присвоение свойству Active значения False)
Основные события компонента TClientSocket
OnConnect Возникает при установке подключения. В обработчике уже можно приступать к авторизации или отправке/приему данных
OnConnecting Также возникает при подключении. Отличается от OnConnect тем, что подключение еще не установлено. Чаще всего используется, например, чтобы обновить статус
OnDisconnect Событие возникает при закрытии сокета вашей программой, удаленным компьютером или из-за сбоя
OnError Событие возникает при ошибке. Во время открытия сокета это событие не поможет выловить ошибку. Во избежание появления сообщения от Windows об ошибке, лучше позаботиться о внутренней обработке исключений путём помещения операторов открытия в блок «try..except»
OnLookup Событие возникает при попытке получить IP-адрес от DNS
OnRead Событие возникает при отправке вам каких-либо данных удалённым компьютером. При вызове OnRead возможна обработка принятых данных
OnWrite Событие возникает, когда вашей программе разрешено писать данные в сокет

Для приема или отправки данных необходимо использовать методы объекта TClientSocket.Socket:

- SendBuf(var Buf; Count: Integer) - Посылка буфера через сокет. Буфером может являться любой тип, будь то структура (record), либо простой Integer. Буфер указывается параметром Buf, вторым параметром Вы должны указать размер пересылаемых данных в байтах (Count);

- SendText(const S: string) - Посылка текстовой строки через сокет.

- SendStream(AStream: TStream) - Посылка содержимого указанного потока через сокет. Пересылаемый поток должен быть открыт. Поток может быть любого типа - файловый, из ОЗУ, и т.д.

- ReceiveBuf (var Buf; Count: Integer) - Прием данных в буфер Buf, размером Count. Важно знать, что при попытке чтения большего количества данных чем доступно на данный момент – возникнет ошибка чтения с сокета. Количество данных (в байтах), доступных для чтения с сокета, можно узнать в свойстве ReceiveLength.

Для чтения простых данных с сокета можно воспользоваться свойством ReceiveText.

Работа с серверными сокетами (TServerSocket)

Сервер, основанный на сокетах, позволяет обслуживать сразу множество клиентов. Причем, ограничение на их количество вы можете указать сами (или вообще убрать это ограничение, как это сделано по умолчанию). Для каждого подключенного клиента сервер открывает отдельный сокет, по которому Вы можете обмениваться данными с клиентом.

Основные этапы работы с TServerSocket

1) Определение свойств Port и ServerType- чтобы к серверу могли нормально подключаться клиенты, нужно, чтобы порт, используемый сервером точно совпадал с портом, используемым клиентом (и наоборот). Свойство ServerType определяет тип подключения (подробнее см.ниже);

2) Открытие сокета - открытие сокета и указанного порта. Здесь выполняется автоматическое начало ожидания подсоединения клиентов (Listen);

3) Подключение клиента и обмен данными с ним - здесь подключается клиент и идет обмен данными с ним.

4) Отключение клиента - Здесь клиент отключается и закрывается его сокетное соединение с сервером.

5) Закрытие сервера и сокета - По команде администратора сервер завершает свою работу, закрывая все открытые сокетные каналы и прекращая ожидание подключений клиентов.

Следует заметить, что пункты 3-4 повторяются многократно, т.е. эти пункты выполняются для каждого нового подключения клиента.

Основные свойства компонента TServerSocket
Socket Класс TServerWinSocket, через который Вы имеете доступ к открытым сокетным каналам. Далее мы рассмотрим это свойство более подробно, т.к. оно, собственно и есть одно из главных.
ServerType Тип сервера. Может принимать одно из двух значений: stNonBlocking - синхронная работа с клиентскими сокетами. При таком типе сервера Вы можете работать с клиентами через события OnClientRead и OnClientWrite. stThreadBlocking - асинхронный тип. Для каждого клиентского сокетного канала создается отдельный процесс (Thread).
ThreadCacheSize Количество клиентских процессов (Thread), которые будут кэшироваться сервером. Здесь необходимо подбирать среднее значение в зависимости от загруженности Вашего сервера. Кэширование происходит для того, чтобы не создавать каждый раз отдельный процесс и не убивать закрытый сокет, а оставить их для дальнейшего использования.
Active Показатель того, активен в данных момент сервер, или нет. Т.е., фактически, значение True указывает на то, что сервер работает и готов к приему клиентов, а False - сервер выключен. Чтобы запустить сервер, нужно просто присвоить этому свойству значение True.
Port Номер порта для установления соединений с клиентами. Порт у сервера и у клиентов должны быть одинаковыми. Рекомендуются значения от 1025 до 65535, т.к. от 1 до 1024 - могут быть заняты системой.
Основные методы компонента TServerSocket
Open Запускает сервер. По сути, эта команда идентична присвоению значения True свойству Active
Close Останавливает сервер. По сути, эта команда идентична присвоению значения False свойству Active
Основные события компонента TServerSocket
OnClientConnect Возникает, когда клиент установил сокетное соединение и ждет ответа сервера (OnAccept)
OnClientDisconnect Возникает, когда клиент отсоединился от сокетного канала
OnClientRead Возникает, когда клиент передал серверу какие-либо данные. Доступ к этим данным можно получить через передаваемый параметр Socket: TCustomWinSocket
OnClientWrite Возникает, когда сервер может отправлять данные клиенту по сокету
OnGetSocket В обработчике этого события Вы можете отредактировать параметр ClientSocket
OnGetThread В обработчике этого события Вы можете определить уникальный процесс (Thread) для каждого отдельного клиентского канала, присвоив параметру SocketThread нужную подзадачу TServerClientThread
OnThreadStart Возникает, когда подзадача (процесс, Thread) запускается
OnThreadEnd Возникает, когда подзадача (процесс, Thread) останавливается
OnAccept Возникает, когда сервер принимает клиента или отказывает ему в соединении
OnListen Возникает, когда сервер переходит в режим ожидания подсоединения клиентов

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

См. демонстрационные проекты в папках /lab1/tcp-ip-client/ и /lab1/tcp-ip-server/

Наши рекомендации