LINUX.ORG.RU

Реализация telnet сервера


0

0

Всем привет, скоро сессия, и вот возникли проблемы с лабой.
Нужно написать с помощью api socket, простое telnet подобное приложение, клиент-сервер.Точнее просто, удаленный shell.

Самому интересно сетевое программирование, и начал изучение по средством книги Стивенса.
Но лабу сдать нужно в короткие строки.И в связи с этим возникли некоторые вопросы.:

Вот я написал клиент, который просто передает строку серверу, и ждет ответа.
Сервер её считывает, потом подставляет её в команду system(«строка») тем самым выполняя её в консоли.
Вопрос такой - как передать вывод со стандартного потока в реальном времени ?

То есть например, я отправляю команду ping google.ru, тогда сервер ее будет выполнять до посинения, вывод команды будет бесконечен.
И как отправлять управляющие комбинации типа ctrl-c, ctrl-z и т.д. ?

Вот в обычном telnet. Создается впечатление как будто ты сидишь за удаленным компом. То есть вводишь ping google.ru и по мере ответов от гугла ты сразу же получаешь ответы у себя в клиенте. Хотелось бы сделать также.

Прошу прощения за мягко говоря идиотские вопросы.


Скачай исходники openssh и telnet, да посмотри как там это все реализовано. В чем проблема то?

Deleted
()

Попытайся взломать пентагон и украсть исходники telnet'a клиента и сервера

sdio ★★★★★
()

Вот я написал клиент, который просто передает строку серверу, и ждет ответа.
Сервер её считывает, потом подставляет её в команду system(«строка») тем самым выполняя её в консоли.
Вопрос такой - как передать вывод со стандартного потока в реальном времени ?

Но зачем? Просто запусти процесс login и подсунь ему вместо stdin, stdout и stderr свои потоки. Соответственно в stdin пишешь всё, что получил от клиента, отдаёшь клиенту всё, что пишется в stdout и stderr. Ну и ещё возможно тебе придётся ловить спецклавиши и либо транслировать их, либо отправлять соотв сигналы.

anonymous
()
Ответ на: комментарий от anonymous

Но зачем? Просто запусти процесс login и подсунь ему вместо stdin, stdout и stderr свои потоки.

Интересное решение, но как это будет выглядеть в си ? (Хотя бы примерно). Дело в том, что я пока не писал программы взаимодействующие с системой. То есть хотелось бы узнать, как например запустить процесс со своей программы, да еще и подсунуть ему свои потоки вместо стандартных ? Просто кроме функции system я ничего в стандартной библиотеке не нашел.

Видимо я сильно туплю...

demsi
() автор топика

И как отправлять управляющие комбинации типа ctrl-c, ctrl-z и т.д. ?

Тебе нужно все осилить быстро и лень будет вчитываться в протокол telnet. Объясню на пальцах, в нем используется два потока данных, управляющие символы начинаются с 255 (октет), все команды кодируются также в октетах. Для каждой команды определен свой код. Сервер/клиент со свой стороны должен уметь различать текст от управляющих символов. Поскольку данный протокол симметричный, то парсер придется писать только один раз [радость]. Я писал своего клиента на основе следующих документов:

http://pcmicro.com/netfoss/telnet.html
http://www.soslan.ru/tcp/tcp26.html
http://cpansearch.perl.org/src/JROGERS/Net-Telnet-3.03/lib/Net/Telnet.pm

Так как сервер-клиент у тебя вымышленные, то все коды (и то что они делают) тебе не придется выполнять, а это большой плюс. Основные проблемы в реальной жизни с телнет это использование tcp-буфера ОС (т.е. иногда буфер не нужно сразу очищать) и сопутствующая опция echo, когда сервер и клиент все повторяют. На это просто забей, чтобы не писать еще несколько лишних сотен строк. Сейчас это не актуально и читать/писать данные в сокет лучше сразу по 8192+ байта.

gh0stwizard ★★★★★
()
Ответ на: комментарий от gh0stwizard

И еще, если вдруг решишь повторить телнет. Алгоритм парсера пишется на основе посимвольного разбора. Никаких регепсов и других извращений не пытайся вытворять, этим только усложнишь жизнь. В одном пакете тебе может придти пачка данных причем управляющие символы могут быть где угодно: вначале строки с текстом «255 251 3 Hello World!\r\n», в середине текста «Hello 255 253 3 World!\r\n», т.е в любом месте.

Поскольку управляющий поток весьма просто отделить от данных исходя из спецификации протокола, то я делал так. Читаем данные из сокета, проверям, что первый управляющий символ (255), далее разбираем каждый код команды до тех пор пока точно не определим команду (находим либо ASCII-символ, либо 255 240). Тем самым мы точно знаем, что далее идет текст, но это не все. Проверим всю строку еще раз на наличие кода 255. Если не встречается, то парсим строку (запускаем команды, пишем результат). Если встречаем, то запоминаем отрезок текста до управляющего символа и парсим управляющий поток. Потом повторяем действия с вырезкой (+склеивание с предыдущим куском текста) и выполняем команду.

Кажется, что сложно, но на деле все очень просто и логично. Окончанием строки текста в этом протоколе всегда является «\r\n». Однако, не стоит забывать про буферизацию со стороны ОС, иногда большие данные могут разбиться на несколько пакетов, скажем по 4096 байт (по столько же байт ты читаешь с помощью read) и в первом пакете может не обнаружиться «\r\n». Это редкость, но не стоит про такую вероятность забывать (в своей версии на это можешь забить).

gh0stwizard ★★★★★
()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от gh0stwizard

И еще мелочь, особенность русской кодировки, буква «я» закодируется в 255 255. Исправить поведение парсера просто, думаю догадаешься сам :)

gh0stwizard ★★★★★
()
Ответ на: комментарий от gh0stwizard

Огромное спасибо!!! Вы мне очень помогли.

demsi
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.