KVIrcОсновы KVS: Работаем с сокетом.

Сегодня мы попытаемся немного поработать с сокетами в KVS. Для этого напишем свой простенький telnet-клиент.

Для работы с сокетами есть специальный класс socket.
Рассмотрим некоторые его функции которые нам понадобятся.

$status() — возвращает статус нашего соединения 0 — отсоединён, 1 — вызов DNS, 2 — соединяемся, 3 — слушаем порт, 4 — соединены.
$connect(host,port) — устанавливаем соединение с хостом host порт port.
$read(length) — возвращает прочитанные данные из сокета с длиной length, если длину не установить то читается до конца.
$write(data) — пишем данные в сокет.
$dataAvailableEvent(data_length) — событие выполняемое при получении данных.
$close() — закрываем сокет.
$connectFailedEvent(reason) — событие выполняемое при ошибке соединения.
$connectEvent() — событие которое выполняется при соединении.
$disconnectEvent() — событие которое выполняется при разединении.

Скрипт у нас будет выглядеть как окно 640х480 с полями для ввода хоста, порта, кнопки соединения и полем ввода команд внизу.
Описание как всегда я буду давать как комменты в тексте скрипта.

alias(telnet)
// создаём новый класс telnet как потомок класса socket
       
class(telnet,socket)
       
{
               
constructor()
               
{
// Собираем интерфейс.
// Создаём виджет с заголовком "Telnet" и геометрией 640х480 пикселей.
                        @
%tWin = $new(widget,$$)
                        @
%tWin->$setCaption("Telnet")
                        @
%tWin->$setGeometry(0,0,640,480)

// Используем класс label для указания названий полей.
                        @
%tWin->%lHost = $new(label,@%tWin)
                        @
%tWin->%lHost->$setGeometry(5,5,35,20)
                        @
%tWin->%lHost->$setText("Host:")
                        @
%tWin->%lPort = $new(label,@%tWin)
                        @
%tWin->%lPort->$setGeometry(250,5,30,20)
                        @
%tWin->%lPort->$setText("Port:")

// Используем класс lineedit для формирования полей ввода
                        @
%tWin->%leHost = $new(lineedit,@%tWin)
                        @
%tWin->%leHost->$setGeometry(45,5,200,20)
                        @
%tWin->%lePort = $new(lineedit,@%tWin)
                        @
%tWin->%lePort->$setGeometry(285,5,200,20)

// Создаём кнопку соединения при помощи класса toolbutton.
                        @
%tWin->%btConnect = $new(toolbutton,@%tWin)
                        @
%tWin->%btConnect->$setGeometry(555,5,80,20)
                        @
%tWin->%btConnect->$setUsesTextLabel(1)
                        @
%tWin->%btConnect->$setTextLabel("Connect")

// Создаём многострочный редактор для отображения данных полученных из сокета
// и делаем его readonly
                        @
%tWin->%meOut = $new(multilineedit,@%tWin)
                        @
%tWin->%meOut->$setGeometry(5,30,630,420)
                        @
%tWin->%meOut->$setReadOnly(1)

// Создаём ещё одно поле ввода для команд.
                        @
%tWin->%leIn = $new(lineedit,@%tWin)
                        @
%tWin->%leIn->$setGeometry(5,455,630,20)

// Привязываем обработку нажатия кнопки Enter в поле ввода команд к функции отправки команды
                        objects
.connect @%tWin->%leIn "returnPressed" $$ sendData

// Привязываем нажатие кнопки соединения к функции соединения.
                        objects
.connect @%tWin->%btConnect "clicked" $$ tconnect

// Отображаем наш виджет.
                        @
%tWin->$show()
               
}
                destructor
()
               
{
                       
if(@$status() == "4")
                       
{
                                @$close
();
                       
}
               
}
                connectEvent
()
               
{
// Отображаем с чем мы соединяемся.
                        @
%tWin->%meOut->$append("[$date(H:M:S)] Connected to $$->$remoteIp():$$->$remotePort()")
               
}

                disconnectEvent
()
               
{
// Сообщение при отключении.
                        @
%tWin->%meOut->$append("[$date(H:M:S)] Disconnected ($0-)")
               
}

                connectFailedEvent
()
               
{
// Сообщение при ошибке соединения с указанием ошибки
                        @
%tWin->%meOut->$append("[$date(H:M:S)] Connect failed ($0-)")
               
}

// Обрабатываем наши данные при получении их из сокета и отображаем.
                dataAvailableEvent
()
               
{
                       
%data = $$->$read()
                        @
%tWin->%meOut->$append("[$date(H:M:S)] $str.replace(%data,"",$char(13))")
               
}

// Функция отправки данных.
                sendData
()
               
{
                       
if(@%tWin->%leIn->$text())
                       
{
                                @$write
(@%tWin->%leIn->$text()\r\n)
                                @
%tWin->%meOut->$append("[$date(H:M:S)] @%tWin->%leIn->$text()")
                                @
%tWin->%leIn->$setText("")
                       
}
               
}

// Наша собственная функция соединения с проверкой наличия имени или ip хоста и состояния соединения.
// Если есть соединение то просто отключаемся.
                tconnect
()
               
{
                        @
%host = @%tWin->%leHost->$text()
                        @
%port = @%tWin->%lePort->$text()
                       
if(@$status == "0")
                       
{
                               
if(@%host != "")
                               
{
                                       
if(@%port == "")
                                       
{
                                                @
%port = "21"
                                                @$connect
(@%host,@%port)
                                                @
%tWin->%btConnect->$setTextLabel("Disconnect")
                                                @
%tWin->%meOut->$append("[$date(H:M:S)] Соединяемся с @%host порт @%port")
                                       
}
                                       
else
                                       
{
                                                @$connect
(@%host,@%port)
                                                @
%tWin->%btConnect->$setTextLabel("Disconnect")
                                                @
%tWin->%meOut->$append("[$date(H:M:S)] Соединяемся с @%host порт @%port")
                                       
}
                               
}
                               
else
                               
{
                                        @
%tWin->%meOut->$append("[$date(H:M:S)] Не указан хост!!!")
                               
}
                       
}
                       
if(@$status() == 4)
                       
{
                                @
%tWin->%btConnect->$setTextLabel("Connect")
                                @$close
()
                       
}
               
}
       
}

// Запуск класса.
       
%telnet = $new(telnet)
}


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

Комментарии (2)

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