Мучаюсь над проэктом "полное перенаправление HTTP-запроса (клиент-сервер-клиент)" — фактически аналог прокси сервера (просьба не предлагать переделать через WinInet/сделать прокси) — задача должна быть решена конкретно через Winsock и именно так. Сокеты — блокируемые, мультипоточно.
Значит, тестирую так: есть любой сайт, к примеру тестировал на http://www.gotovim.ru/ Прописываю в конфиг его домен/айпи, биндю 80 порт на локалхосте и в файл hosts прописываю 127.0.0.1 www.gotovim.ru (соответственно все запросы, которые браузер посылает на домен www.gotovim.ru приходят на 80 порт loopback ко мне в приложение, и дальше я их и обрабатываю). Обработка — пока что : получение запроса от браузера -> пересылка без изменений на сервер -> получение ответа от сервера -> без изменения передача обратно в браузер (клиенту) — то есть вообще без изменений пересылка: браузер — приложение — сервер — приложение — браузер. На данный момент это все, что требуется.
Глобальные переменные, относящиеся к коду ниже:
... далее идёт куча ненужного кода, который пока вообще закомментирован и "непереводимая игра слов на местном диалекте" (с) ....
int isResult3 = 0;
isResult3 = send(fSocketOut, recvbuf, iResult, 0);
if(isResult3)
{
#ifdef DEBUG
Errorlog(recvbuf);
Errorlog("\n-s-\n");
#endif
do
{
iResult = recv(fSocketOut, recvbuf, sizeof(recvbuf), 0);
#ifdef DEBUG
Errorlog(recvbuf);
Errorlog("\n-r-\n");
#endif
int isResult2 = 0;
unsigned int idx = 0;
unsigned long left = iResult;
while (left > 0)
{
isResult2 = send(ClientSocket, &recvbuf[idx], left, 0);
left = left - isResult2;
idx = idx + isResult2;
}
int errt;
errt = WSAGetLastError();//для отладки#ifdef DEBUG
Errorlog(recvbuf);
Errorlog("\n-s-\n");
#endif
} while (iResult != 0 || iResult != -1 || strcmp(recvbuf, "") != 0);
}
ну и ниже обработка если что-то не то с сокетом (не соединиться и прочее)
else
{
#ifdef DEBUG
Errorlog("Connect fSocketOut failed\n\n");
#endif
nClients--;
closesocket(ClientSocket);
ExitThread(0);
}
Везде использую closesocket по завершению, Значит fSocketOut — сокет, через который коннекчусь к реальному домену, сокет ClientSocket — сокет, через который браузер коннектится ко мне посылая запрос (ну и соответсвенно получает от меня ответ).
Проблема. HTML страница (текст) грузится без проблем. Картинок почти нет (буквально пару баннеров). Когда пробую отдельно загрузить картинку — грузится.
Уже много кружек кофе и гугла прошло, а воз и ныне там.
Какие ошибки были замечены при отладке:
1. Бывает что объем полученных recv данных больше, чем объём данных, переданных send (вот только сегодня узнал, что функция send оказывается может отправить и не весь буффер). Как я понял из той же отладки, цикл
while (left > 0)
{
isResult2 = send(ClientSocket, &recvbuf[idx], left, 0);
left = left - isResult2;
idx = idx + isResult2;
}
при iResult == 0 из цикла не выходит, а продолжает, равно как и при iResult == -1 и strcmp(recvbuf, "") == 0
Также после этого isResult2 часто возвращает -1.
3. Страница (именно текст) — грузится полностью, но в браузере "загрузка" не заканчивается — написано "ожидание ответа от www.gotovim.ru", а программа при этом уходит в recv который ничего не получает, а, recv, насколько мне известно — функция блокируемая. При этом в лог постоянно пишется пустой буффер recv + send.
4. Самая главная ) как сделать так, чтобы всё работало?
Начал качать исходники браузера, чтобы посмотреть как там реализован цикл "общения" клиент-сервер-клиент, однако исходники очень большие и качаться будут не быстро, судя по всему.
Код вероятно довольно кривой, но как умею... Рабочего решения не прошу, если не затруднит — подскажите, куда копать и где я ошибаюсь (не предлагайте бросить программирование )?
P.S. Когда открываю небольшую относительно страницу — все грузится и нормально работает.
23.11.11 00:41: Перенесено модератором из 'C/C++' — Кодт
при iResult == 0 из цикла не выходит, а продолжает, равно как и при iResult == -1 и strcmp(recvbuf, "") == 0 _>Также после этого isResult2 часто возвращает -1.
Условие продолжения всегда истинно.
Очевидно, что iResult не может быть 0 и -1 одновременно, чтобы обе проверки дали false.
Наверное, имелось в виду && вместо ||
Может быть, именно этот зависающий цикл и мешает нормальной работе?
при iResult == 0 из цикла не выходит, а продолжает, равно как и при iResult == -1 и strcmp(recvbuf, "") == 0 _>>Также после этого isResult2 часто возвращает -1.
К>Условие продолжения всегда истинно. К>Очевидно, что iResult не может быть 0 и -1 одновременно, чтобы обе проверки дали false. К>Наверное, имелось в виду && вместо ||
К>Может быть, именно этот зависающий цикл и мешает нормальной работе?
Вот я "косорукая свинья" (с) ну да, именно это я и хотел написать, спасибо за то, что заметили. исправил (пока что) на
} while (iResult != 0);
(потом добавлю -1, сейчас просто разобраться хочу), теперь стало в одном лучше, в другом хуже Значит факт такой, что картинки начали появляться (спасибо за помощь ещё раз). Появилась другая проблема. Зависает на 60+- секунд после загрузки первых потоков (есть огромное подозрение, что ровно на 65 — так как это конкретная цифра Time-Out на этом сайте), и после 65 секунд некоторые потоки завершаются, и начинается несколько новых (4-5), в каждом из которых запрашивается какая-то ещё не загруженная деталь вёб-страницы (картинка, итд итп). Но, это же сколько можно ждать загрузки сайта ва таком случае... Каждый тайм-аут — так и жизнь пройдет, пока загрузится. Изза этого после первого цикла вот такого (загрузка + 65 секунд ожидания + загрузка) — выходит не полностью html страница, и невооруженным глазом видно, что css ещё не подгружен (странно — он же в
<head>
прописан), контент выглядит криво. Прикладываю лог такого вот цикла загрузки с тайм-аутами (то, что пишет программа собственно) — http://files.rsdn.ru/99135/_debug.txt . Конечно бинарные данные там не разобрать, но хедеры все видны.
Ах, да. в логе "No request has been received" — это вот в этом месте:
// receiving the request
iResult = recv(ClientSocket, recvbuf, DEFAULT_BUFLEN, 0);
if (iResult > 0)
{ // Beginning dialog
...
... //весь код, что выше
...
}
else if (iResult == 0)
{
#ifdef DEBUG
sprintf_s(errormsg,"No request has been received\n\n");
Errorlog(errormsg);
#endif
nClients--;
closesocket(ClientSocket);
ExitThread(0);
}
то есть фактически завершение потоков.
Благодарю за помощь. Попробую подождать очень долго, и выяснить, загрузит он страницу хотя бы через час или нет.
Здравствуйте, my_problem, Вы писали:
_>Мучаюсь над проэктом "полное перенаправление HTTP-запроса (клиент-сервер-клиент)" — фактически аналог прокси сервера (просьба не предлагать переделать через WinInet/сделать прокси) — задача должна быть решена конкретно через Winsock и именно так. Сокеты — блокируемые, мультипоточно.
_>Значит, тестирую так: есть любой сайт, к примеру тестировал на http://www.gotovim.ru/ Прописываю в конфиг его домен/айпи, биндю 80 порт на локалхосте и в файл hosts прописываю 127.0.0.1 www.gotovim.ru (соответственно все запросы, которые браузер посылает на домен www.gotovim.ru приходят на 80 порт loopback ко мне в приложение, и дальше я их и обрабатываю). Обработка — пока что : получение запроса от браузера -> пересылка без изменений на сервер -> получение ответа от сервера -> без изменения передача обратно в браузер (клиенту) — то есть вообще без изменений пересылка: браузер — приложение — сервер — приложение — браузер. На данный момент это все, что требуется.
_>Проблема. HTML страница (текст) грузится без проблем. Картинок почти нет (буквально пару баннеров). Когда пробую отдельно загрузить картинку — грузится. _>Уже много кружек кофе и гугла прошло, а воз и ныне там. _>Какие ошибки были замечены при отладке:
_>Начал качать исходники браузера, чтобы посмотреть как там реализован цикл "общения" клиент-сервер-клиент, однако исходники очень большие и качаться будут не быстро, судя по всему.
_>Код вероятно довольно кривой, но как умею... Рабочего решения не прошу, если не затруднит — подскажите, куда копать и где я ошибаюсь (не предлагайте бросить программирование )?
Первым делом рекомендую скачать и прочесть RFC 1945 (HTTP/1.0) и RFC 2616 (HTTP/1.1).
Материал может показаться скучным, но его не так много и читается и впрямь легко, особенно
когда есть практический интерес. Список неплохих книг по HTTP я приводил здесь
.
Начал с HTTP, поскольку это — основа, без ее хорошего знания у Вас все время что-то
будет падать или зависать в бесконечном цикле. Ну и без понимания работы TCP/IP тоже никуда.
По реализации.
HTTP — асинхронный протокол. Несмотря на роли "клиент" и "сервер", запросы и ответы не
сихнронизируются друг с другом, хотя порядок доставки сохраняется. Более того, браузеры обычно
создают два и более соединений с одним веб-сервером — по первому скачивают контент, по
второму получают какой-нибудь favicon. Причем доподлинно нельзя знать, какие данные
пойдут первыми по сети. Если делать прокси, нужно научить его работать полностью асинхронно,
чтобы одни потоки не стопорились другими. Тогда все будет работать.
Я делал точно такое же перенаправление трафика в одном продукте коммерческого уровня,
только вместо hosts использовал "ядерные" технологии перехвата — в результате исходящие
коннекты попадали на локальный веб-сервер, а от него уходили во внешний мир, отфильтрованными.
Входящий трафик, само собой, тоже успешно фильтровался.
Принцип работы следующий — в центре системы находится порт завершения ввода-вывода, сокет,
находящийся в режиме прослушки, а также пул рабочих потоков.
Как только приходит коннект (это браузер, к примеру, лезет на rsdn.ru), создается
соединение с удаленным узлом, и оба новых сокета (первый нам вернула функция accept,
второй — функция connect) помещаются в общую структуру, которая отдается на обработку
свободному потоку. Дальше все просто — на первом сокете вызывается WSARecv, полученные
данные отдаются второму сокету через WSASend. То же самое происходит в обратном направлении —
получается полноценный дуплексный обмен данными и никто друг другу не мешает.
Когда одна из сторон размыкает или разрывает соединение, второй отправляется shutdown.
То есть, логика завершения связи также полностью поддерживается.
Повторю — все происходит полностью асинхронно, WSASend вызывается в одном потоке, завершиться
может в другом, результаты ее работы обработаться в третьем и т.п. В этом смысл системы.
Будьте готовы к тому, что далеко не все реализации веб-серверов и браузеров следуют
рекомендациям HTTP и к тому, что придется делать всякие подпорки, не очень красивые.
Например, в HTTP/1.1 принято, что если в ответе сервера не указана длина (Content-Length),
то признаком конца сообщения будет размыкание соединения. Однако куча серверов не делают так —
они отдают HTML-контент, в заголовках HTTP прописывают даже "Connection: close", однако
соединение оставляют открытым. Для интернет-браузера это не является проблемой, так как,
получив, скажем, XML, он в состоянии определить его конец и визуально оповестить юзера,
что содержимое загрузилось. Для прокси-серверов все сложнее — потому что тоже приходится,
как и браузер, читать контент, а тут и вопросы сжатия (gzip/deflate), и chunked-encoding,
и еще много всего. Если самому рвать соединение, то это может нарушить совместимость с
нормальными веб-серверами, не говоря уже о проблеме с TIME_WAIT, когда в этом состоянии
окажется слишком много соединений и нельзя будет вообще никуда подключаться.
В общем, работа не простая предстоит, я бы посоветовал основательно подготовиться.
Здравствуйте, okman, Вы писали:
O>Здравствуйте, my_problem, Вы писали:
_>>Мучаюсь над проэктом "полное перенаправление HTTP-запроса (клиент-сервер-клиент)" — фактически аналог прокси сервера (просьба не предлагать переделать через WinInet/сделать прокси) — задача должна быть решена конкретно через Winsock и именно так. Сокеты — блокируемые, мультипоточно.
_>>Значит, тестирую так: есть любой сайт, к примеру тестировал на http://www.gotovim.ru/ Прописываю в конфиг его домен/айпи, биндю 80 порт на локалхосте и в файл hosts прописываю 127.0.0.1 www.gotovim.ru (соответственно все запросы, которые браузер посылает на домен www.gotovim.ru приходят на 80 порт loopback ко мне в приложение, и дальше я их и обрабатываю). Обработка — пока что : получение запроса от браузера -> пересылка без изменений на сервер -> получение ответа от сервера -> без изменения передача обратно в браузер (клиенту) — то есть вообще без изменений пересылка: браузер — приложение — сервер — приложение — браузер. На данный момент это все, что требуется.
_>>Проблема. HTML страница (текст) грузится без проблем. Картинок почти нет (буквально пару баннеров). Когда пробую отдельно загрузить картинку — грузится. _>>Уже много кружек кофе и гугла прошло, а воз и ныне там. _>>Какие ошибки были замечены при отладке:
_>>Начал качать исходники браузера, чтобы посмотреть как там реализован цикл "общения" клиент-сервер-клиент, однако исходники очень большие и качаться будут не быстро, судя по всему.
_>>Код вероятно довольно кривой, но как умею... Рабочего решения не прошу, если не затруднит — подскажите, куда копать и где я ошибаюсь (не предлагайте бросить программирование )?
O>Первым делом рекомендую скачать и прочесть RFC 1945 (HTTP/1.0) и RFC 2616 (HTTP/1.1). O>Материал может показаться скучным, но его не так много и читается и впрямь легко, особенно O>когда есть практический интерес. Список неплохих книг по HTTP я приводил здесь
. O>Начал с HTTP, поскольку это — основа, без ее хорошего знания у Вас все время что-то O>будет падать или зависать в бесконечном цикле. Ну и без понимания работы TCP/IP тоже никуда.
O>По реализации. O>HTTP — асинхронный протокол. Несмотря на роли "клиент" и "сервер", запросы и ответы не O>сихнронизируются друг с другом, хотя порядок доставки сохраняется. Более того, браузеры обычно O>создают два и более соединений с одним веб-сервером — по первому скачивают контент, по O>второму получают какой-нибудь favicon. Причем доподлинно нельзя знать, какие данные O>пойдут первыми по сети. Если делать прокси, нужно научить его работать полностью асинхронно, O>чтобы одни потоки не стопорились другими. Тогда все будет работать.
O>Я делал точно такое же перенаправление трафика в одном продукте коммерческого уровня, O>только вместо hosts использовал "ядерные" технологии перехвата — в результате исходящие O>коннекты попадали на локальный веб-сервер, а от него уходили во внешний мир, отфильтрованными. O>Входящий трафик, само собой, тоже успешно фильтровался.
O>Принцип работы следующий — в центре системы находится порт завершения ввода-вывода, сокет, O>находящийся в режиме прослушки, а также пул рабочих потоков. O>Как только приходит коннект (это браузер, к примеру, лезет на rsdn.ru), создается O>соединение с удаленным узлом, и оба новых сокета (первый нам вернула функция accept, O>второй — функция connect) помещаются в общую структуру, которая отдается на обработку O>свободному потоку. Дальше все просто — на первом сокете вызывается WSARecv, полученные O>данные отдаются второму сокету через WSASend. То же самое происходит в обратном направлении - O>получается полноценный дуплексный обмен данными и никто друг другу не мешает. O>Когда одна из сторон размыкает или разрывает соединение, второй отправляется shutdown. O>То есть, логика завершения связи также полностью поддерживается. O>Повторю — все происходит полностью асинхронно, WSASend вызывается в одном потоке, завершиться O>может в другом, результаты ее работы обработаться в третьем и т.п. В этом смысл системы.
O>Будьте готовы к тому, что далеко не все реализации веб-серверов и браузеров следуют O>рекомендациям HTTP и к тому, что придется делать всякие подпорки, не очень красивые. O>Например, в HTTP/1.1 принято, что если в ответе сервера не указана длина (Content-Length), O>то признаком конца сообщения будет размыкание соединения. Однако куча серверов не делают так - O>они отдают HTML-контент, в заголовках HTTP прописывают даже "Connection: close", однако O>соединение оставляют открытым. Для интернет-браузера это не является проблемой, так как, O>получив, скажем, XML, он в состоянии определить его конец и визуально оповестить юзера, O>что содержимое загрузилось. Для прокси-серверов все сложнее — потому что тоже приходится, O>как и браузер, читать контент, а тут и вопросы сжатия (gzip/deflate), и chunked-encoding, O>и еще много всего. Если самому рвать соединение, то это может нарушить совместимость с O>нормальными веб-серверами, не говоря уже о проблеме с TIME_WAIT, когда в этом состоянии O>окажется слишком много соединений и нельзя будет вообще никуда подключаться.
O>В общем, работа не простая предстоит, я бы посоветовал основательно подготовиться.
Огромное спасибо за такой развернутый ответ и ваше потраченное время.
В принципе направление ясно, про WSASend/WSARecv как раз сидел и думал сейчас.
Однако не совсем ясно, если у меня сейчас мульти-поточный accept при каждом новом соединении создаёт поток, в который просто передает сокет, откуда к нему приконнектились в параметр, и, далее, созданный поток уже самостоятельно создает второй сокет для исходящего соединения, ну и соединяется с заданным узлом...
С начала, таких потоков одновременно обычно 5 штук (тестирую с Mozilla FF, предполагаю, что в зависимости от браузера данное поведение будет сильно меняться), про асинхронность не до конца понял... В чём плох подход создавать поток для каждого нового соединения забирая в параметр сокет, и исходящий сокет создавать в потоке? Неужели все "настолько" асинхронно, что в потоке №1 будет запрошено что-то либо
GET /images/1.jpg HTTP/1.1
, а ответ от сервера на этот запрос, уже с бинарными данными картинки, будет в потоке №3, например? Мне казалось, что обычно программы ожидают ответа на определенный запрос именно в том сокете, через который они этот запрос отправили (ну при наличии Keep-Alive подобного алгоритма)? И ещё, наверное торможу, но почему же потоки "висят" минуту + перед завершением?
Здравствуйте, my_problem, Вы писали:
_>Однако не совсем ясно, если у меня сейчас мульти-поточный accept при каждом новом соединении создаёт поток, в который просто передает сокет, откуда к нему приконнектились в параметр, и, далее, созданный поток уже самостоятельно создает второй сокет для исходящего соединения, ну и соединяется с заданным узлом...
_>С начала, таких потоков одновременно обычно 5 штук (тестирую с Mozilla FF, предполагаю, что в зависимости от браузера данное поведение будет сильно меняться), про асинхронность не до конца понял... В чём плох подход создавать поток для каждого нового соединения забирая в параметр сокет, и исходящий сокет создавать в потоке?
Так тоже можно делать.
Но моя статистика показывает, что браузеры очень активно создают и завершают соединения, и даже
когда открыто всего несколько вкладок, этих соединений легко может оказаться под сотню.
Создавать поток на каждое соединение — слишком дорого, и после определенного порога чем больше
потоков, тем хуже производительность.
Неужели все "настолько" асинхронно, что в потоке №1 будет запрошено что-то либо _>
_>GET /images/1.jpg HTTP/1.1
_>
_>, а ответ от сервера на этот запрос, уже с бинарными данными картинки, будет в потоке №3, например? Мне казалось, что обычно программы ожидают ответа на определенный запрос именно в том сокете, через который они этот запрос отправили (ну при наличии Keep-Alive подобного алгоритма)? И ещё, наверное торможу, но почему же потоки "висят" минуту + перед завершением?
Как-то путанно излагаете. Или я неправильно понимаю.
В любом случае, Ваша задача — разгрузить главный поток приложения, в котором вызывается accept,
от лишней работы и ожиданий, потому что сервер тогда станет недоступным и некоторые типичные
операции сломаются. Приняли коннект — сразу отдаем на обработку свободному потоку и быстро
возвращаемся к приему следующих соединений.
Рабочие потоки должны быть спроектированы так, чтобы они могли передавать данные от клиента (браузера)
серверу и в обратном направлении, причем одновременно. Используя синхронные сокеты, этого
достичь не получится, потому что поток будет "спать" либо на send, либо на recv, и встречные
данные "застопорятся". На первый взгляд кажется, что для HTTP это вроде как и не нужно,
так как запросы и ответы чередуются, следуя в строгом порядке друг за другом, но это только на
первый взгляд.
Именно поэтому я советую использовать асинхронные сокеты и WSASend/WSARecv, ну
а координировать их работу не обязательно портом завершения ввода/вывода, есть и другие механизмы.
Тогда у Вас получится схема, когда данные смогут беспрепятственно идти в обоих направлениях,
не мешая друг другу, а без этого некоторые сайты будут "зависать" на долгое время.
Когда я начал заниматься этими вопросами, то первое, что попытался сделать — написать
простейший веб-сервер, который бы принимал GET-запросы и отдавал ответы.
А потом стал бомбить его множеством одновременных запросов из разных браузеров и под
разными версиями Windows — оказалось, что мой сервер не работает так, как надо,
иногда повисает по непонятным причинам, иногда не может толком отдать контент, и т.д.
Потом, разбирая "по косточкам", открыл для себя много нового.
Здравствуйте, okman, Вы писали:
O>Здравствуйте, my_problem, Вы писали:
_>>Однако не совсем ясно, если у меня сейчас мульти-поточный accept при каждом новом соединении создаёт поток, в который просто передает сокет, откуда к нему приконнектились в параметр, и, далее, созданный поток уже самостоятельно создает второй сокет для исходящего соединения, ну и соединяется с заданным узлом...
_>>С начала, таких потоков одновременно обычно 5 штук (тестирую с Mozilla FF, предполагаю, что в зависимости от браузера данное поведение будет сильно меняться), про асинхронность не до конца понял... В чём плох подход создавать поток для каждого нового соединения забирая в параметр сокет, и исходящий сокет создавать в потоке?
O>Так тоже можно делать. O>Но моя статистика показывает, что браузеры очень активно создают и завершают соединения, и даже O>когда открыто всего несколько вкладок, этих соединений легко может оказаться под сотню. O>Создавать поток на каждое соединение — слишком дорого, и после определенного порога чем больше O>потоков, тем хуже производительность.
O>Неужели все "настолько" асинхронно, что в потоке №1 будет запрошено что-то либо _>>
_>>GET /images/1.jpg HTTP/1.1
_>>
_>>, а ответ от сервера на этот запрос, уже с бинарными данными картинки, будет в потоке №3, например? Мне казалось, что обычно программы ожидают ответа на определенный запрос именно в том сокете, через который они этот запрос отправили (ну при наличии Keep-Alive подобного алгоритма)? И ещё, наверное торможу, но почему же потоки "висят" минуту + перед завершением?
O>Как-то путанно излагаете. Или я неправильно понимаю. O>В любом случае, Ваша задача — разгрузить главный поток приложения, в котором вызывается accept, O>от лишней работы и ожиданий, потому что сервер тогда станет недоступным и некоторые типичные O>операции сломаются. Приняли коннект — сразу отдаем на обработку свободному потоку и быстро O>возвращаемся к приему следующих соединений.
O>Рабочие потоки должны быть спроектированы так, чтобы они могли передавать данные от клиента (браузера) O>серверу и в обратном направлении, причем одновременно. Используя синхронные сокеты, этого O>достичь не получится, потому что поток будет "спать" либо на send, либо на recv, и встречные O>данные "застопорятся". На первый взгляд кажется, что для HTTP это вроде как и не нужно, O>так как запросы и ответы чередуются, следуя в строгом порядке друг за другом, но это только на O>первый взгляд.
O>Именно поэтому я советую использовать асинхронные сокеты и WSASend/WSARecv, ну O>а координировать их работу не обязательно портом завершения ввода/вывода, есть и другие механизмы. O>Тогда у Вас получится схема, когда данные смогут беспрепятственно идти в обоих направлениях, O>не мешая друг другу, а без этого некоторые сайты будут "зависать" на долгое время.
O>Когда я начал заниматься этими вопросами, то первое, что попытался сделать — написать O>простейший веб-сервер, который бы принимал GET-запросы и отдавал ответы. O>А потом стал бомбить его множеством одновременных запросов из разных браузеров и под O>разными версиями Windows — оказалось, что мой сервер не работает так, как надо, O>иногда повисает по непонятным причинам, иногда не может толком отдать контент, и т.д. O>Потом, разбирая "по косточкам", открыл для себя много нового.
Спасибо большое ещё раз. Ну чтож, раз проще никак, буду мучать WSASend/WSARecv.
На данный момент бесконечный цикл accept'a выглядит так:
Как я понимаю, это полностью удовлетворяет условия задачи. Асинхронно надо в моём случае переделать HandShake... Этим и займусь.
Ну а функция "рабочего потока" выше постом. Хотя она конечно изменится. Спасибо за помощь.
Если я правильно понимаю, я делаю их не блокируемыми и в цикле проверяю, в каком из них на данный момент времени есть данные (клиент или сервер), и читая с этого сокета — отправляю в "противоположный".
_>Если я правильно понимаю, я делаю их не блокируемыми и в цикле проверяю, в каком из них на данный момент времени есть данные (клиент или сервер), и читая с этого сокета — отправляю в "противоположный".
Цикл — это тоже не хорошо (ну что за собеседник, скажете, — и это ему не хорошо, и то)...
Представьте себе 50 потоков, в каждом из которых крутится цикл, причем только для того,
чтобы проверить — пришли ли данные. Суть асинхронных операций в Windows в том, чтобы
отдать данные и забыть о них на время. Например, поспать [часок] в wait-функции или заняться
другой полезной работой. Когда инфраструктура завершит операцию, она даст сигнал и
результаты можно будет забрать. Для Windows это наиболее эффективная схема.
Есть такая книга — "Программирование в сетях Windows" от Э.Джонса и Д.Оланда.
В ней довольно подробно рассматриваются основные модели работы с сокетами — select,
перекрытый ввод-вывод, порты завершения, и другие. Рекомендую найти и прочесть.
Здравствуйте, okman, Вы писали:
O>Здравствуйте, my_problem, Вы писали:
O>Вот эта строчка для чего ? O>
O>WaitForSingleObject(0, 50000);
O>
_>>Если я правильно понимаю, я делаю их не блокируемыми и в цикле проверяю, в каком из них на данный момент времени есть данные (клиент или сервер), и читая с этого сокета — отправляю в "противоположный".
O>Цикл — это тоже не хорошо (ну что за собеседник, скажете, — и это ему не хорошо, и то)... O>Представьте себе 50 потоков, в каждом из которых крутится цикл, причем только для того, O>чтобы проверить — пришли ли данные. Суть асинхронных операций в Windows в том, чтобы O>отдать данные и забыть о них на время. Например, поспать [часок] в wait-функции или заняться O>другой полезной работой. Когда инфраструктура завершит операцию, она даст сигнал и O>результаты можно будет забрать. Для Windows это наиболее эффективная схема. O>Есть такая книга — "Программирование в сетях Windows" от Э.Джонса и Д.Оланда. O>В ней довольно подробно рассматриваются основные модели работы с сокетами — select, O>перекрытый ввод-вывод, порты завершения, и другие. Рекомендую найти и прочесть.
Спасибо Большое, разобрался, книжку скачал, просмотрел, прочел (не всю пока). С WSASend/WSARecv не подружился, сделал через select + FD_ISSET переводом сокетов в неблокируемый режим. Код пока ужасный, показывать стыдно, но работает безотказно (как ни странно, тьфу три раза). Продолжаю тесты гонять + переделываю остальные части программы, ибо слишком сильно изменился код.
_>Начал качать исходники браузера, чтобы посмотреть как там реализован цикл "общения" клиент-сервер-клиент, однако исходники очень большие и качаться будут не быстро, судя по всему.
исходники браузера смотреть это радикально конечно ㋡ есть легковесный прокси — 3proxy, опенсорцный. в его составе есть tcppm — выполняет тот самый функционал по тупой перекачке tcp-трафика на удаленный сервер. хоть автор и утверждает, что сорцы сложны для понимания и местами запутаны, но IMO вполне читаемы, и уж всяко понятнее исходников браузера. может будет полезным.