| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > Отправка по tcp для начинающего |
| Автор: nullpoint 1.8.2014, 18:14 | ||
| Всем привет. Прошу объяснить все в подробностях для дурака. Такая задача стоит. Есть TCP сервер и клиент. Клиент присылает серверу сообщение msgCli, в котором первый байт - команда серверу (например, 0х15), затем 5 байт - ASCII строка с "\0". Сервер в ответ отправляет сообщение msgServ: 1й байт - команда (например, 0х45), 2й байт - команда (например, 0х42),затем 3 байта ASCII строка с "\0", затем 9 байт сообщение. Эти 9 байт получаются следующим образом:
Теперь перед отправкой мы должны отобразить на экранmsgRand в ASCII, а отправить в десятичном виде, т.е. на экран вот в таком виде показываем - 4da234f199a5bce8c1, а отправляем - 7716252241153165188232193 (данные значения взяты просто для примера). Собственно я не могу сообразить как msgRand перевести в эти два представления. Потом собрать две команды по 1 байту, ASCII строку, считанные 9 байт в одно сообщение и отправить. P.S. Это не лабораторка. Просто учусь программировать. Хотелось бы разобраться с этим. Использую Ubuntu 14.04 + QtCreator(Qt 4.7). |
| Автор: feodorv 1.8.2014, 19:32 |
| Я запутался. и никак друг с другом не сочетаются. Откуда тогда у Вас пример для 4da234f199a5bce8c1 => 7716252241153165188232193? |
| Автор: _zorn_ 1.8.2014, 19:39 |
| Есть такое подозрение, что школьник хочет замутить свой ботнет. С блекджеком соответственно. |
| Автор: feodorv 1.8.2014, 22:17 | ||||
Вот не за что не догадался бы)))
"Интовое" представление не однозначное, восстановить из него однозначно первоначальные 9 байт, скорее всего, не удастся, если не потребовать 3 "интовых" символа на один первоначальный. Но, честно говоря, я не вижу вообще никаких предпосылок для того, чтобы по сети гонять, а затем сохранять в базе, именно "интовое" представление в противовес оригинальному, девятибайтовому. Вы всегда можете сделать что-то в этом роде:
Особого смысла в этом нет, но дело Ваше))) |
| Автор: nullpoint 1.8.2014, 22:51 | ||
| feodorv, подскажите тогда как правильно сделать. Как это все передать одним сообщением "1й байт(0x45)2й байт(0x42)3 байта(ASCII с \0)9 байт(msgRand)"? И как принять от клиента сообщение и разобрать его на части? Можно же вроде вот так сделать:
И записать это в два поля БД, но вот как потом это все обратно восстановить в единое целое? |
| Автор: feodorv 2.8.2014, 07:42 | ||||||
Как обычно:
Здесь немного сложнее, так как целостное 14-байтовое сообщение может быть разбито протоколом TCP (что маловероятно, но возможно) на несколько пакетов, которые читаются отдельными recv:
Аналогично:
Девятый байт пропал. Или он не нужен? Вроде, у баз данных должен быть тип поля "сырые данные", в которое можно запихнуть произвольные данные заданной длинны. Да и текстовое поле (длинной 9 символов) у некоторых БД позволяет хранить произвольные символы, не только отображаемые на экране. Ну и в крайнем случае храните эти 9 символов в 16-ричном виде в текстовом поле длины 18, из 16-ричного вида всегда можно восстановить исходный 9-байтовый вид... |
| Автор: nullpoint 2.8.2014, 09:51 |
| feodorv, я жутко извиняюсь, не объяснил все до конца, поэтому и возникла небольшая путаница. :( Считывая из /dev/random, я таким образом генерирую ключ для клиента, т.е. мне как раз таки не нужны "сырые" байты, а нужно случайно сгенерированное число. Т.е. считанные байты я перевожу в unsigned int (7716252241153165188232193) и его отправляю клиенту, а на экран я должен вывести этот ключ в виде ASCII (4da234f199a5bce8c1). И вот тут у меня начинаются проблемы. Точно, даже не обратил внимания, что только 8 байт записал. Я имел в виду что строка ASCII с завершающим \0, а не вся она состоит из \0 |
| Автор: nullpoint 2.8.2014, 10:09 |
| Схематично сообщения клиента и сервера выглядят так: http://fastpic.ru/view/68/2014/0802/a06910af29962e6c7b8b3d98989e364e.jpg.html |
| Автор: feodorv 2.8.2014, 10:40 | ||||||||
Это сильно меняет ситуацию? Ну будет сообщение длиной 15 байт...
Всё равно не понятно, что Вам нужно. Хотите гонять "интовый" вид своих 9 байт - гоняйте, я не настаиваю, хотя этот самый "интовый" вид можно получить и на стороне клиента из сырых 9 байт. Делайте, как Вам угодно. Только тогда в формат сообщения Вы должны будете добавить длину сообщения, так как "интовое" представление не обладает фиксированной длиной (в отличие от сырого вида) (либо хитрый однократный обмен сообщениями с правильными shutdown( socket, SD_SEND)). Да и о "случайности" в таком виде можно говорить лишь условно. Как получить "интовую" строчку я уже писал:
Аналогично получается "шестнадцатиричная" строка:
|
| Автор: nullpoint 2.8.2014, 11:06 |
| feodorv, да я совсем запутался с этими вещами и поэтому не могу нормально объяснить, что нужно... Давайте я опишу лучше какую я задачу поставил себе, а вы подскажите как бы вы ее решили. Наверное, так будет лучше. Клиент присылает серверу команду (или 0х45, или 0х44) и ASCII строку с завершающим \0, каждый клиент присылает свою строку, которая не меняется, своего рода идентификатор. Сервер смотрит какую команду прислал клиент и в зависимости от команды или высылает ответ (если 0х45) или выводит на экран сообщение (если 0х44). В ответ клиенту он отсылает команду 0х45, команду 0х42, ASCII строку с \0 (3 байта), ключ (9 байт). Когда сервер принял сообщение и "увидел" что команда равна 0х45, он начинает искать в базе присланную ASCII строку, если нашел, то генерирует ключ 9 байт, отображает его на экран в виде ASCII кодов, т.е. выводит 18 символов 4da234f199a5bce8c1, и затем отправляет ключ клиенту в таком виде 0х450х42abc\07716252241153165188232193. Перед отправкой ключ записывается в БД, чтобы при следующем запуске программы, если не сгенерирован новый ключ отправить его клиенту и вывести на экран в ASCII. |
| Автор: feodorv 2.8.2014, 11:29 |
| Итак, имеем однократный обмен сообщениями. сервер При подключении клиента сервер делает recv на 5(???) байт, которые клиент обязан прислать в течении некоторого времени (если не прислал, соединение сервером закрывается). По получении этих 5 байт сервер делает:
клиент Подключается к серверу и шлёт 5-ти байтовый запрос. Если запрос с командой 0х45, то ждёт ответа неопределенной длины с ключом. Так? Зачем клиенту "интовое" представление? Что он будет с ним делать? В чем сложность? |
| Автор: nullpoint 2.8.2014, 11:51 |
Просто выводим сообщение об ошибке. Если нашли то отсылаем клиенту ключ из БД. Лучше наверное сначала сгенерировать ключ и записать его в БД и уже потом брать его оттуда и отправлять. А новый ключ генерировать по какому-нибудь другому событию (это не главное). Неважно, любое. Можно написать что ошибка клиента. Ничего не делать, ну или можно вывести сообщение об ошибке. Это значит мои непонятки пошли. Я думал что если мы отсылаем ключ, то это должно быть какое-то значение, а не непонятный набор печатных и непечатных символов. Как записать ключ в базу. Запросы я могу сделать. Проблема в том в каком виде он туда запишется и чтобы нормально его потом оттуда можно было взять. Как проверять есть ли в базе присланный клиентом идентификатор? Не буду же я последовательно каждый элемент массива сравнивать с символом строки идентификатора из базы. |
| Автор: feodorv 2.8.2014, 12:07 | ||||
Тогда при каждом обращении клиента для него будет сгенерирован новый ключ. Вы этого добиваетесь? Ну почему непонятных. Это есть значение ключа. (Правда, гонять по сети ключ в незашифрованном виде уже не хорошо, ну да ладно))) Всё зависит от того, какую БД Вы хотите использовать. Для данной задачи вполне подойдет какая-нибудь http://www.opennet.ru/man.shtml?topic=btree&category=3&russian=2, либо самописный текстовый файл, который грузится в бинарное дерево при старте сервера.
Это вопрос к БД. И даже в http://forum.vingrad.ru/forum/c-c++db-database.html Идентификатор клиента как ключевое поле? |
| Автор: nullpoint 2.8.2014, 12:16 | ||
Нет. Ключ просто будет генерироваться независимо от того сколько раз клиент обратился. Новый ключ раз в сутки будет создаваться к примеру. Мне бы сначала просто отправить без шифрования:) MySQL Можете показать как это реализовать без записи в БД? Т.е. сгенерировали ключ, отобразили его на экран в ASCII, приняли от клиента сообщение, посмотрели по базе идентификатор, отправили клиенту сообщение или вывели сообщение об ошибке, если нет такого идентификатора. |
| Автор: feodorv 6.8.2014, 22:54 | ||||||
Гм. Я не работаю с QtCreator, поэтому тупые BSD сокеты.
Только сетевой обмен, остальное сами Клиент
Сервер
|
| Автор: nullpoint 7.8.2014, 21:25 |
| feodorv, спасибо, уже сам разобрался, но с помощью вашего кода подправил свое приложение |
| Автор: feodorv 7.8.2014, 21:54 |