к странице 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
сервисы, игры
|
||||||||||
игры, программы
|
||||||||||
поздравления, уроки рисования, уроки создания сайтов
|
||||||||||
комиксы, музыка, рассказы
|
||||||||||
игра для разработки, калькулятор услуг, cms, комикс
|
||||||||||
игры для разработки, комиксы
|
||||||||||
игры шарики и ямки, комиксы про Костю Коробкина, ria xxl игра, fly snow 3d генератор эффектов снега, частиц и др. -
|
||||||||||
Создай свою игру на fle game engine -
|
||||||||||
Для создания сайта - модуль отзывов/комментариев для вашего сайта в составе megainformatic cms express files -
|
||||||||||
Уроки Flash, бесплатные Flash - игры.
|
||||||||||
Поддержка сайтом нескольких языков (multi lang), создание собственной системы личных кабинетов, соц. сети или фриланс - биржи (megainformatic cms social), создание сервиса коллективных покупок на базе megainformatic cms groupon, онлайн сервис подсчёта статистики ключевых слов в статьях вашего сайта keywords gen + описание кода данного сервиса, с возможностью бесплатно реализовать его аналог на своём собственном сайте.
megainformatic.ru/webjob/ - сервис для фриланс проектов - место встречи заказчиков и исполнителей |
||||||||||
Социальная сеть megainformatic.ru/webjob/
megainformatic.ru/webjob/ - сервис для фриланс проектов - место встречи заказчиков и исполнителей |
||||||||||
Системы управления сайтом, уроки
megainformatic cms admin - простая и компактная система для работы и управления сайтом |
||||||||||
|
||||||||||
|
||||||||||
megainformatic cms free и серия продуктов - Уроки Photoshop
Данная серия посвящена описанию приемов и методов создания изображений, с помощью инструментария программы Adobe Photoshop. Кроме того, многие описанные средства могут вам помочь при освоении и многих других программ для работы с растровой графикой - GIMP, Corel Photo Paint и других.
|
||||||||||
бесплатные игры 2d и 3d, а также эмулятор Ну, Погоди!
Это серия распространяемых бесплатно игр. Вы не только можете поиграть, но и скачать исходники, получив тем самым возможность внести изменения в игру или создать новую !!! (эмулятор Ну, Погоди! распространяется платно). |
||||||||||
серия игр про Веселого Буквоежку, и бесплатно распространяемая игра Нечто: Необъяснимое - в плену желаний
Здесь представлены новинки жанра - Говорящий Комикс, Настольная игра, А также продукт, который позволит Вам научиться создавать игры самостоятельно. Ну и конечно изюминка в своём роде - бесплатная игра - Нечто: Необъяснимое - в плену желаний |
||||||||||
Серия бесплатных онлайн уроков, посвященных 3ds max, photoshop, c++, directx, delphi и php.
Описаны практические примеры решения различных задач, возникающих при создании игр и сайтов. Продукты Набор разработчика и Ваше Визуальное Шоу распространяются платно. |
||||||||||
уроки и продукты различной тематики
Бесплатные Уроки Photoshop free, Бесплатные Уроки по программированию на delphi directx - Как создать игру Ну, Погоди!, Бесплатная Авторская музыка в формате mp3 - Музыкальные Миры, Платно распространяемый продукт megainformatic cms express - система для быстрого создания Вашего сайта на php + my sql. |
||||||||||
Проекты игр, уроки
Игра Веселый Буквоежка, уроки delphi directx 8.1 для начинающих (описываются основы 3d игр), моделируем девушку в 3d studio max, уроки музыки - пишем музыку в Fruity Loops Studio |
||||||||||
|