Вверх ↑
Этот топик читают: Гость
Ответов: 3930
Рейтинг: 620
#1: 2013-12-01 17:07:08 ЛС | профиль | цитата
Клиент и сервер TCP
Есть примеры (откомпилированные).



Версия от 27.03.2017
После обновления можете удалить файл TCPClientServer.pas (был переименован на NSTCP.pas)

СКАЧАТЬ


Зачем всё это

На форуме периодически появляются вопросы по использованию компонентов "TCP-сервер" и "TCP-клиент".
В процессе обсуждения не раз возникало ощущение, что в этих компонентах не хватает многих важных и не очень вещей.
В какой-то момент в процессе поиска информации по работе с сетью у меня сложилась полная картина того, чего мне не хватает и какими возможностями должны обладать клиент и сервер в HiAsm. И главное: каким образом это может быть реализовано.
Так были сделаны эти компоненты.

Описание особенностей

Компоненты от стандартных отличаются следующим.

Для автора схемы:

- TCPClient

1) Подключение, отправка и прием данных в синхронном/асинхронном режиме
2) Добавлено событие, сообщающее о завершении отправки
3) Отдельные события об ошибках подключения и отправки с выдачей кодов ошибок
4) Прерывание отправки данных
5) Отключение/включение приема данных без ущерба для отправки
6) События и методы имеют несколько другие названия.
7) Возможность получать асинхронные события

- TCPServer

1) Ведется учет клиентов не по IP, а по ID, что допускает одновременные независимые соединения с одного IP.
2) Существуют почти все методы TCP-клиента, применимые как к выбранному соединению, так и ко всем.
3) Возможность останавливать прием новых подключений, не прекращая обслуживать текущие.

Как клиент так и сервер могут работать в неоконных приложениях. В папке примеров есть консольные демо.

Исходный код

Компоненты реализованы с использованием параллельных потоков и блокирующих Winsock-функций вместо асинхронных через оконные сообщения.

Поскольку класс потока в KOL достаточно глючный, был сделан отдельный модуль со своим классом потока, который работает достаточно стабильно на всех компиляторах.
За счет этого также стало возможным реализовать синхронизацию потоков в неоконных проектах (у них нет переменной Applet и главной очереди сообщений, которые необходимы для синхронизации KOL-овскому потоку).
Этот поток можно использовать и в других компонентах.

Сервер создает один дополнительный поток для приема входящих подключений. Создаётся по 1 одному дополнительному потоку на каждые 64 соединения для приема данных. Для асинхронной отправки используется ещё до 5-ти потоков.

В коде достаточно широкий набор классов для использования в сторонних компонентах.

Перечень точек

TCPClient

doSend - Отправить данные Data на сервер. Повторная отправка данных невозможна до появления события onSend/onSendError
doSendAsync - Отправить данные на сервер в асинхронном режиме. Повторная отправка данных невозможна до появления события onSend/onSendError
doConnect - Подключиться к порту Port сервера с адресом IP
doDisconnect - Отключиться от сервера
doAbortSend - Прервать отправку данных (для данных, посылаемых методом doSend, вызвать этот метод можно только из параллельного потока)
doStopReceiving - Остановить прием данных (передача продолжает работать). После остановки приема данных событие onDisconnect будет возникать только как следствие некоторых ошибок при отправке данных
doStartReceiving - Возобновить прием данных после метода doStopReceiving

onReceive - Происходит при получении данных от сервера. Данные приходят порциями по выбору системы
onSend - Происходит по завершению отправки данных методами doSend и doSendAsync. Нет гарантии, что данные были полностью получены сервером на момент исполнения этого события
onConnect - Происходит при успешном подключении к серверу методом doConnect
onDisconnect - Происходит при разрыве соединения сервером или ошибках, при которых дальнейшая работа с текущим подключением невозможна
onErrorConnect - Происходит при ошибке подключения методом doConnect. Выдаёт в поток код ошибки
onErrorSend - Происходит при ошибке отправки данных. Выдаёт в поток код ошибки
onProgress - Происходит в процессе отправки и выдаёт в поток количество отправленных байтов

Data - Данные для отправки на сервер
IP - IP-адрес сервера для подключения
Port - Номер порта для подключения


TCPServer

doSend - Отослать данные указаному клиенту
doStartServer - Запускает сервер на локальном порту и ожидает подключений
doStopServer - Разрывает соединение со всеми клиентами и останавливает сервер
doAbortSend - Прерывает отправку данных указанному клиенту
doAbortSendAll - Прерывает отправку данных всем клиентам
doClose - Разорвать указанное соединение
doCloseAll - Разрывает соединение со всеми клиентами без остановки сервера
doEnumClients - Перебирает все текущие соединения и выдает их идентификаторы на onEnumClients
doSendAll - Отослать данные всем клиентам
doSendAsync - Отослать данные указаному клиенту асинхронно
doSendAllAsync - Отослать данные всем клиентам асинхронно
doStopListen - Остановить прием новых подключений. Текущие подключения продолжают обслуживаться. Для возобновления нужно вызвать doStartServer

onReceive - Происходит при получении данных от клиента
onClientConnect - Событие происходит при соединении нового клиента к серверу и выдает в поток идентификатор клиента
onClientDisconnect - Событие происходит при отсоединении клиента от сервера и выдает в поток его идентификатор
onSend - Событие происходит после завершения передачи данных методами отправки данных. Выдает в поток идентификатор клиента
onStartServer - Событие происходит при успешном запуске сервера методом doStartServer
onEnumClients - Происходит в процессе перебора клиентов по doEnumClients и выдает в поток идентификатор
onErrorStart - Событие происходит при ошибке запуска сервера методом doStartServer. Выдаёт в поток код ошибки
onErrorSend - Происходит при ошибке отправки данных. Выдаёт в поток код ошибки
onProgress - Происходит в процессе отправки данных и выдаёт в поток количество отправленных байтов для клиента CurClientID.

Data - Данные для отправки клиентам
ClientID - Идентификатор клиентского соединения для методов работы с соединением
Port - Порт сервера

Count - Возвращает количество активных соединений (клиентов)
CurClientID - Содержит текущий идентификатор соединения на момент соответствующих событий
CurIPAddress - Содержит текущий IP-адрес на момент событий onClientConnect, onEnumClients


Редактировалось 5 раз(а), последний 2017-10-03 16:49:18
карма: 19

15
Голосовали:Assasin, Andrey, Konst, ser_davkin, LainX, -= DriveR =-, Shonyi, filyaxxxcom, flud, login, Nickname, Nighthead, hin4, strannik_nebes, Gunnman
vip
#1.1контекстная реклама от партнеров
Разработчик
Ответов: 25460
Рейтинг: 2070
#2: 2013-12-01 17:19:15 ЛС | профиль | цитата
Очень интересная работа. Надо найти тестеров для доскональной проверки.
карма: 19

0
Ответов: 1370
Рейтинг: 85
#3: 2013-12-01 17:26:49 ЛС | профиль | цитата
Спасибо!
Приятно посмотреть, как всё оформенно.

карма: 4

0
Разработчик
Ответов: 25460
Рейтинг: 2070
#4: 2013-12-02 18:47:23 ЛС | профиль | цитата
Netspirit, так что, нужно тестирование или будем добавлять в пакет Вот только на вопросы отвечать будешь пока ты, да и за багами следить.
карма: 19

0
Ответов: 3930
Рейтинг: 620
#5: 2013-12-02 19:02:20 ЛС | профиль | цитата
Давай пока пусть месяца два полежат. Пусть народ попробует их в реальных приложениях.
карма: 19

0
Разработчик
Ответов: 25460
Рейтинг: 2070
#6: 2013-12-02 19:20:27 ЛС | профиль | цитата
Netspirit писал(а):
Давай пока пусть месяца два полежат

Ок
карма: 19

0
Ответов: 3930
Рейтинг: 620
#7: 2013-12-03 13:13:48 ЛС | профиль | цитата
Исправление метода ThiTCPServer._work_doSendAll - работал как SendAllAsync, поправлен пример сервера, прочие косметические исправления.
карма: 19

0
Ответов: 817
Рейтинг: 52
#8: 2013-12-26 11:39:49 ЛС | профиль | цитата
Netspirit, Добрый день!
Подскажите, а эти компоненты лишены недостатка указанного в теме http://forum.hiasm.com/forum.html?q=3&p=256326 ?
Я понимаю, что можно проверить самому, однако смогу это сделать только после НГ
карма: 1

0
Разработчик
Ответов: 4668
Рейтинг: 420
#9: 2013-12-26 11:53:46 ЛС | профиль | цитата
-= DriveR =-,
Netspirit писал(а):
Как клиент так и сервер могут работать в неоконных приложениях с помощью компонента MainLoop. В папке примеров есть консольные демо.

карма: 10
0
Ответов: 817
Рейтинг: 52
#10: 2013-12-26 16:16:08 ЛС | профиль | цитата
Assasin,
Спасибо, приятная новость.
nesco писал(а):
нужно тестирование или будем добавлять в пакет

Думаю не стОит сомневаться, надо добавлять
карма: 1

0
Разработчик
Ответов: 25460
Рейтинг: 2070
#11: 2013-12-26 17:29:46 ЛС | профиль | цитата
-= DriveR =- писал(а):
Думаю не стОит сомневаться, надо добавлять

Решение Автора -- закон

Netspirit писал(а):
Давай пока пусть месяца два полежат. Пусть народ попробует их в реальных приложениях.

карма: 19

0
Гость
Ответов: 17029
Рейтинг: 0
#12: 2013-12-28 08:50:03 правка | ЛС | профиль | цитата


Редактировалось 4 раз(а), последний 2017-06-21 01:14:34
карма: 0

0
Гость
Ответов: 17029
Рейтинг: 0
#13: 2014-01-02 17:36:47 правка | ЛС | профиль | цитата


Редактировалось 4 раз(а), последний 2017-06-21 01:14:34
карма: 0

0
Ответов: 3930
Рейтинг: 620
#14: 2014-01-03 12:02:55 ЛС | профиль | цитата
Нет. Пока что обдумываю, каким он должен быть и каковы будут его преимущества по сравнению с обычным.

Главная идея - события одного клиента будут происходить в рамках одной копии схемы, синхронизируясь только между собой. Тогда каждый клиент не будет дергать основной поток для выдачи события. С главным потоком будут синхронизированы только внешние точки контейнера.
Такая реализация требует переработки базовых классов клиента и сервера.

Если у кого будут какие-то мысли по этому поводу - высказывайте.
карма: 19

0
Гость
Ответов: 17029
Рейтинг: 0
#15: 2014-01-03 22:43:48 правка | ЛС | профиль | цитата


Редактировалось 4 раз(а), последний 2017-06-21 01:14:36
карма: 0

0
Сообщение
...
Прикрепленные файлы
(файлы не залиты)