fle game engine - движок для создания игр
fle game engine - движок для создания игр


Вакансии
Игродельня
Сегодня
22 октября 2017
11:29

Теги

создание сайтов, создание игр, дизайн, игры, информатика, уроки photshop, php, c++, музыка, delphi, cms, робосайт

Статьи сайта

megainformatic - Создание изображений огня, воды, неба

megainformatic - Создание текстур горных пород и суши (урок 5)

megainformatic - Рисование персонажей (урок 6)

megainformatic - Рисование фона (урок 6 часть 2)

megainformatic - Рельефные изображения

Добавление статей на сайт под управлением megainformatic cms express

megainformatic - Воспроизведение файлов в форматах it, xm, s3m, mod

megainformatic - Воспроизведение файлов в форматах it, xm, s3m, mod - страница 2

megainformatic - Воспроизведение в игре музыки в формате XM

megainformatic - Воспроизведение файлов в формате OGG Vorbis

megainformatic - игра "Веселый Буквоежка" - инструменты разработки

megainformatic - Игра "Веселый Буквоежка" - история создания проекта

megainformatic - Как анимировать паука ?

megainformatic - Уроки Photoshop

megainformatic - Купить Уроки Photoshop - Чудеса

megainformatic - Купить Уроки Photoshop - Рисуем и Анимируем

megainformatic - Эмулятор игры Ну, Погоди!

сайт megainformatic - Говорящий Комикс Веселый Буквоежка

megainformatic - Что нужно для создания собственного сайта ?

megainformatic - Моделируем девушку в 3d используя 3ds max

megainformatic - Уроки Fruity Loops Studio - пишем свою музыку

megainformatic - Уроки Fruity Loops Studio - пишем свою музыку - урок 1 - Быстрый старт

megainformatic - Сброник статей по дизайну и компьютерной графике. Обзор.

megainformatic - Уроки 3d на delphi directx - Вывод Заставки

Добро пожаловать в систему управления сайтом megainformatic cms

megainformatic - Создание эскиза и макета страницы сайта

megainformatic - Верстка созданного макета

megainformatic - Добавление модулей обеспечивающих минимально необходимый функционал

megainformatic - Основы добавления контента на сайт, управления и поддержки сайта

megainformatic - Проверка работы сайта, установка на хостинг

megainformatic - Основы продвижения созданного сайта

megainformatic - Создание шаблонов

megainformatic - Создание интернет-магазина

megainformatic - Музыкальные миры - композиция Морозное утро - 10 версий

ЛЕТО

megainformatic - Нечто Необъяснимое - пре релиз

megainformatic cms admin

megainformatic cms admin

megainformatic - Основы создания 3d игр - проект Тайны Морских Глубин

megainformatic - уроки delphi directx 8.1 3d - Основы Вращений и Управления камерой

megainformatic cms seo

megainformatic cms admin

megainformatic - Моделируем девушку в 3d - Подготовка 2d-эскиза тела человека

megainformatic cms stat kit

megainformatic cms seo

megainformatic - Теория и практика 3d игр - О Кватернионах

megainformatic - Теория и практика 3d игр - Основы теории векторов

megainformatic - Теория и практика 3d игр - Важные замечания

megainformatic - Моделируем девушку в 3d используя 3ds max - Подготовка к моделированию ноги - готовим ширму

megainformatic - Моделируем девушку в 3d используя 3ds max - Выполняем моделирование ноги

megainformatic - Моделируем девушку в 3d используя 3ds max - Улучшаем созданную модель женской ножки

megainformatic cms stat kit

megainformatic - Подводная лодка и подводный мир

megainformatic - megainformatic cms - Форма для смены шаблонов сайта - модуль template selector

megainformatic cms social

megainformatic cms social Руководство пользователя

роман Eternity Вечность - автор Синицин Андрей megainformatic - страница 5

 

к странице 1 к странице 2 к странице 3 к странице 4 страница 5 к странице 6

 

* * *



Был найден более подходящий пример для решения задачи,
которая стояла передо мной.

c:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\netds\winsock\simple

Его мы и будем изучать далее.

А еще у меня в ходе работы возникла такая мысль:
всё что я делаю - это документирую свою деятельность в форме статей.

Если бы кому-то из непрограммисткой области пришло на ум задокументировать
какие-то свои действия и выложить на всеобщее обозрение, то
это выглядело бы по-меньшей мере странно. :)

Представьте, работник автосалона пишет:

Пришел на стэйшн, сделал то-то и то-то, чтобы раскрутить клиента
на покупку того или иного авто. И т.д.

Хотя идея, кстати говоря, не такая уж и странная.
Другие работники этой отрасли усвоив такие знания смогут
таким образом достичь каких-то результатов.

Правда в программировании результат всегда точно определен.
Это либо работающая программа делающая действия по решению
четко поставленной задачи, либо не делающая её.

Конечно с покупкой или не покупкой такой программы результат
более чем размыт.

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

И если в программировании опять же всё более-менее ясно -
хотя бы с точки зрения получения результата на уровне: Да - получилось
или Нет - не получилось.

То в продажах царит нечто напоминающее (с моей конечно точки зрения)
"танцы с бубном".

Конечно же с точки зрения непосвященного деятельность программиста -
это точно такие же "магические заклинания" и "танцы с бубном".

Но и в той и другой отрасли результат легко оценить: если программа
работает - то она дает ответ на поставленные вопросы.

Если продукт продан и прибыль получена - то это тоже очевидно.

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

Но увы. В силу определенных причин такая оценка всегда крайне субъективна -
хоть, как говорится, результат и можно оценить как Да/Нет - 

но эти самые Да и Нет крайне размыты и зависят от личных качеств субъекта
который решает что оно Да или что оно Нет.

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


Обычно тот, кто считает себя квалифицированным видя перед собой какое-то
сложное решение, почти неглядя выбирает второй вариант.

Таким образом на первый план выходят не знания, а такая составляющая
как доверие к разработчику.

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

Если же такого нет - полагаются на случай.

И вот когда проект попадает в область, когда не совсем понятно кто виноват
в невозможности его завершения, тут всё завершается очень трагично.

Конечно может не совсем уж так трагично, но всё-таки и не совсем приятно.

В любом случае, один рабочий поток разработки завершается и начинается какой-то
совершенно другой. Но это уже совершенно другая история и она того, кто попал
под "каток" совершенно уже не интересует. А если и заинтересует, то только
с точки зрения "был ли я прав или нет ?". Под правотой понимается конечно уровень
квалификации, но всё можно списать на что угодно.

На нехватку финансирования, выделенного времени и т. д.

Одним словом люди с неудачным опытом совместного сотрудничества на уровне
"заказчик-исполнитель" просто расходятся в стороны и ищут каких-то новых вариантов.

Вот и всё.

Я конечно же всегда придерживаюсь мнения: на разработку нужно тратить столько времени,
сколько просит разработчик, а не ограничивать его.

Если будут какие-то ограничения - с финансовой стороны, либо со стороны временных рамок,
либо, что чаще и бывает - и с той и с другой стороны, да еще сдобренной хорошей порцией
сложностей в самом проекте и поставленных задачах, то если Ты только начинаешь работать
с таким проектом - впору задуматься: а стоит ли браться ?

Хуже бывает если выбора уже нет, и всё может окончиться отрицательным результатом и 
отрицательным опытом сотрудничества.

К сожалению или к счастью - программирование и разработка чего-либо, каких-либо программ и
изучение связанной с ними предметной отрасли, это деятельность которая сложно поддается
однозначной оценке. Оценки и результаты могут быть самые крайне противоположные от:
легко и дешево, до сложно и дорого со всеми возможными комбинациями вышеупомянутых и 
их различными варриациями представляющими смесь того и другого.

И всё зависит от:
квалификации разработчика,
способности адекватной оценки результата со стороны заказчика
и 
конечно же доступного бюджета и временных рамок.

В каких-то других, уже более-менее устоявшихся отраслях и сферах деятельности всё
уже более-менее устоялось и цены, время, опыт уже более-менее, но хорошо известны
и легче поддаются оценке.

Примеры ?

Да вот навскидку: услуги по перевозу грузов или пассажиров; оказание услуг в образовательной
сфере; концертная деятельность; розничная продажа товаров;

А в программировании ?

Заказчик порой может придумать что-то немыслимое. Не имея даже малейшего представления
как это реализовать и вообще возможно ли это. Он просто где-то что-то услышал-увидел-ему
подсказали.

И вперед.

Дальше начинается кино.

Под названием поиск исполнителя, который сможет за бросовый бюджет и короткий срок эту идею
поставить на ноги.

Если идея более-менее программно реализуемая - то конечно результат рано или поздно будет
получен.

Но чем сложнее идея, тем сложнее и тернистее путь заказчика, который решил, не своими руками,
всё это реализовать.

А почему не своими ? Не хватает знаний, опыта, времени. Но в то же время есть свободные
средства и чаще всего постановка задачи от какого-то начальства свыше.

Тогда и начинается новое кино.

Вера в то, что всё будет хорошо, даже если всё плохо, спасает нас. Это надежда на лучшее
и на то, что всё меняется к лучшему.

Модель её использования очень проста: зачем ругаться и мучать друг друга, когда можно всё
решить мирно и спокойно ?

Если задача решается - проявляем к этому минимум восторгов, если НЕ решается - минимум
досады и разочарования. И никаких поспешных выводов и решений. Иначе всё дело можно
загубить на корню.

Это инструкция и для тех кто ищет задачу или проект и для тех, кто таковые предлагает.
Напишите себе плакат и повесьте на самом видном месте, чтобы видеть и читать это каждый день:

Искреннее и доброжелательное отношение - вот ответ на любые вопросы и любые проблемы,
которые будут решаться в этом случае как бы сами собой.

Почему так ?

Да потому что всегда тот кто хочет найти, находит. А тот кто напротив, изначально дал
себе установку на отрицательный результат - его и получит в итоге.

Не будьте врагами сами себе !

Тот кто привык что-то ругать и критиковать, в итоге и получит лишь ответную ругань и
критическую болтологию.

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

Помните - любые оценки - это известная доля субъективизма, а потому не ищите позитива там,
где сами плодите и порождаете негатив.

Начинайте изменяться начиная с прямо сейчас и прямо с себя. И только потом уже глядя
по-сторонам.

И да, запомните наконец, эту простую истину -

Искреннее и доброжелательное отношение - вот ответ на любые вопросы и любые проблемы,
которые будут решаться в этом случае как бы сами собой.

Любая неудача переносится легче, если это искренне и без злобы и лишнего, излишнего
негатива.

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

Решение всегда есть, его всегда можно найти. Но имеется в виду такое - которое
даст положительный результат, а не отказ от работы или откат от проблемы.

Положительное и позитивное возникает только там, где не ищут позитив днём с огнём,
а где это уже устоялось и считается за норму.

Только так и никак более.

Простите, но увы, я не даю рецептов, на гарантированные результаты.

Они всегда рождаются в труде и в борьбе. Сказать всегда проще, чем
сделать.

Будьте всегда людьми не только слова, но и дела.

Не воспринимайте всё вышесказанное как простую формулу или рецепт.

Ошибка именно в том, что всё пытаются воспринимать просто и "КАК ЕСТЬ".

На самом деле не всё "ПРОСТО" и не всё следует понимать "КАК ЕСТЬ".

Забудьте про такие стереотипы.

Искать позитив и генерировать его это не одно и то же.

Здоровое зерно будет расти только на здоровой почве. Даже если Вы заранее
ложите в почву здоровое зерно, не надейтесь просто на то, что раз
оно здорово, то и плоды его тоже будут здоровыми. Почва тоже должна
быть здоровой, а если нет - то должна быть оздоровлена.

Так и человек. Не может генерировать или воспринимать позитив, если
сам он изнутри не позитивен. Это будет лишь притворство и ничего
более.

Путь этот труден и извилист.

Вы наверное уже устали от такого "менторского" и "назидательного" стиля.
Умных мыслей и установок.

Добро и зло существуют и сосуществуют в тесной связи и взаимозависимости.
Одно не может быть без другого. Как день без ночи и наоборот.

Одно перетекает в другое, плавно и не плавно, существуют и сосуществуют
самые разнообразные его формы и виды. Мыслимые и немыслимые, очевидные
и совсем мало распространенные, даже уникальные, маниакальные и 
малоизученные.

Носителей настоящей истины нет. Всё решается в конкретных обстоятельствах.

Насколько обыденно и банально бы это не звучало, но сказав всё вышеуказанное,
усвоив его, всё равно знайте, что всегда есть и будут и другие
варианты правильного пути. Другие мнения и решения.

И никакое из них не будет являться истиной в последней инстанции.
Потому что её нет и быть не может.

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


Почему мы не живём вечно и нам кажется, что мы делаем что-то уже бесконечно ?

Мудрость.

Она не приходит сразу и ко всем.

Мудрыми становятся и остаются также не сразу и не все.

Все мы разные.

У каждого из нас свой путь.

Свои трудности и проблемы.

Но и свои радости и достижения.


Нет такого человека, который бы был АБСОЛЮТНО СЧАСТЛИВЫМ.

Счастье достигается тем, что постоянно его надо искать и есть неиссякаемая
надежда на то, что Мы его найдём !

На этом пожалуй я закруглюсь.

Простите если утомил Вас своими философскими или какими-либо еще высказываниями.

Просто вылилось, как говорится. 

Видимо хотелось сказать и оно свершилось.

Далее мы будем работать более предметно и опять
займёмся вышеуказанными вопросами.

Итак пример 
c:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\netds\winsock\simple

Пример включает 2 приложения:

simples - т. е. simple Server

и

simplec - т. е. simple Client

Оба приложения являются консольными. Выполнив их сборку в среде MSVS 2005 или выше
Вам нужно будет запускать их из окна коммандной строки Windows, чтобы
увидеть результат их работы.

Если любой из примеров запустить с параметром тире -

simples -
simplec -

То будут выведены возможные параметры коммандной строки для запуска данного приложения.


cd C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\
netds\winsock\simple\server\Debug

C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\netds\winsock\simple\server
\Debug>simples -
Usage
simples -p [protocol] -e [endpoint] -i [interface] [-4] [-6]
Where:
        -p protocol   - is one of "TCP" or "UDP"
        -e endpoint   - is the port to listen on
        -i interface  - is the string local address to bind to
        -4            - force IPv4
        -6            - force IPv6

Defaults are TCP,5001 and INADDR_ANY and IN6ADDR_ANY (if IPv6 present)


Кстати, чтобы не набирать в коммандной строке длинные строки, можно один раз набрать их
в текстовом редакторе, например в Блокноте, а потом просто копировать и вставлять
в окно коммандной строки.

Для примера я запустил сервер с такими параметрами


C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\netds\winsock\simple\server
\Debug>simples -p TCP -e 80 -i 127.0.0.2
socket 0x7c bound to address 127.0.0.2 and port 80


	
Т. е. задал для сервера использование протокола TCP, подключил к порту 80 и привязал к
ip - 127.0.0.2

Сервер работает и остается в памяти пока не будет нажата комбинация клавиш [Ctrl] + [C].
Он ожидает запросов от клиента.


Клиент, это приложение simplec.

Запускается с такими параметрами -
	
simplec -p  -n  -e  -l 


Значит надо указать те же параметры, что были указаны у simples, чтобы клиент мог успешно
подключиться.
simplec -p TCP -n 127.0.0.2 -e 80 -l 10


Запуск simplec с указанными параметрами осуществляем в отдельном окне коммандной строки
Windows.


C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\netds\winsock\simple\client
\Debug>simplec -p TCP -n 127.0.0.2 -e 80 -l 10
Client attempting connection to: 127.0.0.2 port: 80
Connection established...
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 0]] from server
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 1]] from server
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 2]] from server
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 3]] from server
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 4]] from server
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 5]] from server
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 6]] from server
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 7]] from server
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 8]] from server
wrote 40 bytes
read 40 bytes, data [This is a small test message [number 9]] from server


Отправка/получение тестовых данных происходит 10 раз подряд (циклически), поскольку
я указал при запуске simplec параметр -l 10.

Как работает сервер simples Мы рассматривать здесь не будем, т. к. это не
нужно для моей непосредственной задачи. У меня серверная часть реализована не на
c++, а на php.

Вы, при желании и наличии такой необходимости, можете сами изучить исходный код
simples взяв его из Windows SDK 7.0.
О том, где скачать его и как с ним работать я уже рассматривал ранее.

Как лучше к этому подойти Вы сейчас и узнаете на примере изучения simplec.


Основная проблема с которой Вы возможно столкнетесь, по крайней мере с ней
сталкивался я, это работа со строками.

В примере simplec используются обычные символьные строки char. Но большинство
Windows - приложений работают с unicode.

Для работы с unicode, а точнее чтобы от него не зависеть, нужно использовать
так называемые generic строки - там где вы явно задаете строку применять оператор _T


CString cs_str = _T("Simple string sample");



Если указывать L


CString cs_str = L"Simple string sample";


То сразу будет использоваться unicode, независимо от кодировки, которая задана в настройках
 проекта.

Если же использовать _T - то в зависимости от настройки проекта будут применяться либо ANSI
строки, либо unicode.

В большинстве приложений Windows всегда используется unicode. Но на низком уровне, с которым
работает
Windows Sockets 2 ведется работа с каждым байтом информации отдельно. Поэтому вопрос
кодировки
и преобразований из одной кодировку в другую очень важен, и когда Вы будете разрабатывать
свои приложения с использование Windows Sockets 2 API, то волей-неволей столкнетесь
с проблемой
использования строк и их различных видов.

Основные ошибки какие могут быть - это утечки памяти - memory Leaks и Access Violation.
Когда какая-то память выделяется, но
не освобождается, или идёт обращение к участку памяти, в непредусмотренном адресном
пространстве.


Как добиться наилучшего понимания ? Вам нужно будет плотно работать с приложением в
режиме отладки Debug, а также писать небольшие простенькие прилоежния - я их называю
ТЕСТОВЫЕ. В таких приложениях по возможности размещаем проблемный код.

Если он связан с другим кодом, упрощаем его так, чтобы он получился как можно
меньшим. Там где, например подразумевается выполнение какого-то большого блока
кода для получения заранее предвиденного результата - просто используем
готовое значение для подстановки - тогда можно будет и не включать в ТЕСТОВОЕ
приложение этот БОЛЬШОЙ КУСОК кода.

В тестовых приложениях можно экспериментировать - чтобы лучше понять ту или 
иную особенность, которая не совсем понятна или вызывает ошибку.

Поскольку вариантов работы может быть множество, а правильный, естественно
никто вам не укажет, нужны будут собственные эксперименты с кодом.

И без ТЕСТОВЫХ приложений тут никак не обойтись.

Приведу небольшой пример, который продемонстрирует какие вопросы
могут возникать и как они решаются опытным путём.

Документация и мануалы всегда дают какой-то пример, но чтобы
его лучше понять нужно писать собственный код и экспериментировать.

Например у нас объявлена символьная строка char -


char            hoststr[NI_MAXHOST],


NI_MAXHOST это системная константа равная 1025.

Чтобы очистить строку от неинициализированных данных применяем функцию -


SecureZeroMemory(&hoststr, sizeof(hoststr));


Но может возникнуть 2 вопроса:

Почему &hoststr, а не просто hoststr ?


Т. е. так - 


SecureZeroMemory(hoststr, sizeof(hoststr));



И почему sizeof(hoststr), а не strlen(hoststr) ?

Т. е. так -


SecureZeroMemory(hoststr, strlen(hoststr));



Такой код -


SecureZeroMemory(&hoststr, sizeof(hoststr));



Будет правильным, только если строка определена как
массив элементов char -



char            hoststr[NI_MAXHOST],


Но если имеется такой массив -


char *hoststr = "localhost";


Или 


char *hoststr;


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


В этом случае - char *hoststr - это уже не массив, а указатель на массив и очищать его
нужно не так -


SecureZeroMemory(&hoststr, strlen(hoststr));


А так -


SecureZeroMemory(hoststr, strlen(hoststr));


Потому что &hoststr - так мы очистим не массив, т. е. не значения которые хранятся
в буфере строки, а значение указателя - он станет равным 0 или NULL. При
этом считается, что его память была освобождена.

И тут возникает сразу 2 ошибки:

1) Memory Leaks - утечки памяти - потому что указателю было присвоено NULL значение,
без предшествующего освобождения буфера оператором delete [] hoststr;  //только
если буфер создавался динамически -


char *hoststr = new char[ request_str_symbols_count ];


request_str_symbols_count - подразумевается, что это некоторая числовая константа.

2) Поскольку hoststr был обнулен, то попытка обращения к нему вызовет ошибку
Access Violation - поскольку память уже недоступна в переменной hoststr.



И второй вопрос - о разнице между sizeof и strlen -



SecureZeroMemory(&hoststr, sizeof(hoststr));
SecureZeroMemory(&hoststr, strlen(hoststr));


Разница здесь в том, что функция sizeof - возвращает длину всей выделенной памяти для буфера 
hoststr в байтах, а strlen возвращает длину строки hoststr - количество символов до первого
втретившегося символа \0.

Понятно, что когда hoststr еще только был объявлен, но не очищен, там содержатся
какие-то неинициализированные данные, т. е. по сути мусор. И неизвестно есть ли
там символ \0 - символ конца строки. А если и есть - то непредсказуемо - в какой позиции
он находится.


Так что выполняя команду 


SecureZeroMemory(&hoststr, sizeof(hoststr));


Над буфером hoststr (буфер - это синоним строки - какой-то участок памяти, просто когда
мы говорим строка - то подразумеваем, что в памяти содержатся символьные данные
представляющие какую-то читаемую текстовую строку, но буфер в более общем смысле
может содержать любые двоичные данные - а не только текст), мы тем самым
инициализируем весь выделенный ей участок памяти нулевыми значениями.


Но команда - 


SecureZeroMemory(&hoststr, strlen(hoststr));


Является логически неправильной, т. к. будет очищена в лучшем случае часть строки
до первого встретившегося 0 байта. Ну а может быть, что такого символа
вообще не окажется в неинициализированных данных, тогда hoststr останется
неинициализированной.


Конечно если строка уже была инициализирована - например туда уже было
помещено значение строки, тогда команда будет иметь эффект. Но опять же
очищен будет не весь буфер, а только часть его до первого символа
нуль-терминатора (т. е. \0 ).


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

Например, от обилия таких вопросов, я даже спросил себя:
Ну почему, почему в C++ работа со строками так сложна и неочевидна,
не всегда ясно и понятно что происходит и почему возникает ошибка
в том или ином месте.

Ошибки как я уже говорил те же самые - Access violation и memory leaks.

Ответ звучит просто - возьмите язык php - он делался по-сути для
удобной работы со строками ! Потому что вся информация, которую
в php приходится обрабатывать и выводить - это, как правило,
строковые данные.

Так что, как видите, для работы со строками существует ЦЕЛЫЙ ЯЗЫК php !!!
Так что понятно, что c++ не может охватить всех нюансов, особенно
если Вы о них даже не знаете.

Поэтому не надо пенять на язык, а надо сжать зубы, запастись
терпением и дальше искать ответ на свои вопросы в тестовых
приложениях и экспериментах.




Теперь можно приступать к изучению кода -

c:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\netds\winsock\simple\
client\simplec.cpp


Функция с которой начинается исполнение - 
int __cdecl main


Сначала запустить сервер -

Открываем окно коммандной строки Windows - Пуск - Программы -
Служебные Windows - Коммандная строка

cd C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\netds\winsock\simple\
server\Debug

simples -p TCP -e 80 -i 127.0.0.2

Не закрываем окно.


Теперь работаем с приложением клиентом - simplec


simplec -p TCP -n 127.0.0.2 -e 80 -l 10

Я буду запускать клиент из MSVS в режиме отладки,
поэтому эти параметры укажу в -

Command Arguments как описывалось на странице 4
-p TCP -n 127.0.0.2 -e 80 -l 10

c:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\netds\winsock\simple\
client\simplec.cpp

Итак шагаем по коду в режиме отладки (как это делать тоже уже описывалось
на странице 4)


Сначала в цикле обрабатываются введенные агрументы коммандной строки -

    // Parse the command line
    if (argc >1)
    {
        for (i=1; i < argc; i++)
		
		
	Отладочные значения могут оказаться такими -
	
address_family = 0
		
		
socket_type = 1


server_name = 0x007f4d6d "127.0.0.2"
//т. е. через параметр server_name мы задаем url по которому надо обращаться к серверу
//для решения вашей задачи можно подставить любой сервер,
для примера я использую megainformatic.ru


port = 0x007f4d7a "80"
//для megainformatic.ru также нужно будет использовать этот порт


maxloop = 10
//количество итераций отправки данных клиентом.



Небольшое отступление.

В чём отличие в применении символов & и * в языке c++ ?

Символ * - это указатель на адрес переменной, а не на её значение, если символ
звездочки применяется к параметру функции -

пример -


SearchCRLF(const char * strData, size_t data_length, size_t * found_at)


в данном случае переменные strData и found_at представляющие параметры
функции SearchCRLF будут указателями на адрес - или передаются по-ссылке
(имеют ссылочный тип).

strData при этом указывает на адрес массива из элементов типа char

Поскольку объявлена как 


char * strData


Ключевое слово const означает, что данные указателя
являются неизменными -
т. е. изменяться внутри функции не будут (иначе это вызовет ошибку).

Таким образом, в операциях присваивания strData может находиться только
по правую сторону от знака =.

Необходимость ключевого слова const вызвана тем, что
если мы опустим его - 

будет считаться, что данные в strData можно изменять.

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


Поскольку все char строки являются массивами, то негласно считается, что


char * strData


и


char strData[100];


По-сути одно и то же - только в первом случае указатель является адресом
на блок данных, размер которого неизвестен, а значит может меняться
динамически.

Во-втором случае - блок представляет адрес на данные заранее известного размера -
из 100 символов (или байт), поскольку размер char - это размер 1 байта
в памяти.


Посмотрим на второй параметр функции -


size_t * found_at



прежде чем, попасть в функцию, параметр может быть определен так -


size_t search_result = -1;

//...

//и где-то дальше он передается в функцию

SearchCRLF(strData, strDataSize, &search_result);



Как видим при search_result появился значок &

Он как раз и означает, что в функцию будет передано не значение переменной search_result,
а указатель (адрес), по которому хранится данное значение.

Поскольку функция была объявлена так -


void SearchCRLF(const char * strData, size_t data_length, size_t * found_at)
{
	//...
	
	//то мы можем изменять значение параметра found_at тем самым вернув из
	//нашей функции измененный результат
	
	*fount_at = 0; //так мы изменяем значение параметра found_at переданного по ссылке
	//(указатель на адрес как было указано выше)
}


Чем это отличается от варианта 

void SearchCRLF(const char * strData, size_t data_length, size_t found_at)
{


?


А тем, что если параметр found_at передается по-значению, то внутри функции
мы его изменить не можем.

Таким образом, в операциях присваивания внутри тела функции,
он может появляться только с правой стороны  -


void SearchCRLF(const char * strData, size_t data_length, size_t found_at)
{

	//...

	size_t some_var = found_at; //вот так
	
	//а вот так мы его уже изменить не сможем - будет ошибка
	found_at = 1;
	
}


Как видим в этом и состоит необходимость применения слова const для
строковых данных из символов char.

Для простых типов, таких как size_t - представляющих беззнаковое целое число,
применение оператора * автоматически подразумевает, что параметр
передается по-ссылке, а значит может быть изменен в теле функции.

Если * нет - значит передается значение.

В случае со строками это не является очевидным - строки в любом случае
представляют из себя массивы, а значит хранят указатель на адрес массива,
а не вереницу значений его элементов.

Поэтому когда мы указываем слово const -


const char * strData


Подразумеваем, что строка будет передаваться как бы "по-значению" и изменить
её будет нельзя.

Ну а когда const не указан - можно.


Вот такое небольшое отступление.

Далее мы продолжим изучение примера simplec.


Для решения стоявшей передо мной задачи нужна была всего 1 итерация.
Либо несколько - в случае ошибки соединения с сервером - это тоже
нужно будет предусмотреть и реализовать.


Далее всё идёт обычным порядком описанном в мануале по Win Sock 2
(где и как его прочитать я также упоминал в 
Windows Sockets 2, ping, Windows SDK 7, чем открыть hxs файл - страница 4) -


    // Load Winsock
    if ((retval = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
    {
	
	
	//...
	
	// Make sure the wildcard port wasn't specified
	//тут убеждаемся не используется ли порт по-умолчанию - если задан 0 для него
    if (_strnicmp(port, "0", 1) == 0)
        Usage(argv[0]);

	Для нас важен именно 80 порт т. к. simples я запустил именно с 80 портом
	
	Да и megainformatic.ru также слушает этот - 80 порт.
	
	    retval = getaddrinfo(
                        server_name,
                        port,
                        &hints,
                        &results
                        );
//? определяется имя сервера если задан его ip и наоборот.
// Нужно будет проверить это задав сервер как megainformatic.ru
						
	
	
	
	Если всё нормально и ошибок нет -
	
	начинаются попытки коннекта -
	
	
	while (addrptr)
    {
        conn_socket = socket(addrptr->ai_family, addrptr->ai_socktype,
			addrptr->ai_protocol);

	//...
	
	retval = getnameinfo(
					addrptr->ai_addr,
					(socklen_t)addrptr->ai_addrlen,
					hoststr,
					NI_MAXHOST,
					servstr,
					NI_MAXSERV,
					NI_NUMERICHOST | NI_NUMERICSERV
					);			
					
					//ага, вот оно ! тут пытаемся получить данные если
					//задано именно доменное имя
	
//...


    // Make sure we got a connection established
    if (conn_socket == INVALID_SOCKET)
    {
        printf("Unable to establish connection...\n");
        goto cleanup;
    }
    else
    {
        printf("Connection established...\n");
    }

Если ошибок нет - в консоль выведет	Connection established...

Т. е. соединение успешно установлено.


Далее происходит самое главное и интересное, ради чего собственно всё и делалось -


    //
    // cook up a string to send
    //
    loopcount = 0;
    for (;;)
    {
	
		//в буффер заносим некоторый текст, который будем передавать серверу
		//в моей основной задаче этот текст - это запрос у сервера данных:
		//например такой: 

GET /?page=474 HTTP/1.1\r\n
Host: megainformatic.ru\r\n
Connection: Close\r\n


Таким образом, на примере приложения simple из Windows SDK 7
можно изучить все необходимые шаги для базовой работы с Windows Sockets 2,
аналог которого есть в языке php и называется fsockopen -

о нём я рассказывал в статье -
Работа с сокетами fsockopen из php

На этом ползволю себе закруглиться, т. к. более подробно
изучить пример simple Вы сможете сами - скачав Windows SDK 7.



к странице 1 к странице 2 к странице 3 к странице 4 страница 5 к странице 6

 

Оставленные комментарии



fle game engine - движок для создания игр
fle game engine - движок для создания игр


Something: Unexplained 2 captive of desires / Нечто: Необъяснимое 2 в плену желаний
Костя Коробкин Комикс Коллекционное издание - 6 комиксов, 81 страница, 220 mp3 треков
megainformatic Размещение баннерной рекламы у нас
Время загрузки: 0,0796