Добрый день. Интересует такой вопрос: Как можно отправлять сообщения клиенту с заданным интервалом? То есть например мне нужно отправить три сообщением с интервалом в 30 секунд. если я сделаю send(...); Sleep(...); send(...); Sleep(...); send(...); closesocket(...); то recv примет их всех 1м разом, а мне нужно, чтоб сообщения у клиента выводились с интервалом в 30 секунд. как такое сделать?
я достаю сокет с помощью accept() и передаю его в отдельный поток. если я его закрою с помощью closesocket() как его снова открыть из этого же потока?
bug1z Организовать "рукопожатие" между клиентом и сервером. Отсылает - ждем подтверждение - отсылаем - ждем подтверждение - ...
вставил после каждого слипа stutdown с параметром SD_BOTH - не помогло. есть еще соображения как решить эту проблему?
UDP, т.к. TCP на серваке по 30сек висеть в ожидании - разрыв ресурсов. Второй вариант как выше и говорили - клиент connect() send( reconnect_timeout ) recv(); close_socket(); Sleep(30000); connect() send(); recv(); closesocket(); ... это для посылки серверу сообщений (см. TCP протокол) "я больше не буду ничего отправлять" или "я больше не собираюсь ничо принимать" *я = сокет.
сделал вторым вариантом, с реконнектом. работает. спасибо. хотелось бы еще узнать: такие программы как The Bat, они ведь тоже не постоянно подключены, а реконектятся время от времени, забирают почту?
Вообще странно. С чего это так? Когда-то давно я писал чатовый сервак на чистых TCP-сокетах. Клиенты (java-апплеты) держали постоянные TCP-коннекты к серваку на C++. Как кто-то из клиентов присылал сообщение, или если встроенный бот его генерил - оно тут же отправлялось всем подключенным клиентам. Никаких дисконнектов. Как надо - тут же разослалось. Пока не надо - все висят, ждут. Правда протокол там был типа (длина/сообщение).
Есть еще один вопрос. Сервер создает некое изображение(HBITMAP), затем преобразовывает его в png и отправляет клиенту. как это лучше организовать? Сохранять изображение на винт, затем читать в массив байтов и отправлять, или же есть варианты получше?
bug1z Зачем сохранять на винт? Можно и в поток GDI+. Пример сохранения снимка окошка в файл: Код (Text): HDC hMainDialogDC = GetWindowDC(hMainDialog); RECT windowRect; GetWindowRect(hMainDialog, &windowRect); DWORD width = windowRect.right-windowRect.left, height = windowRect.bottom - windowRect.top; HBITMAP hCopyBMP = CreateCompatibleBitmap(hMainDialogDC, width, height); HDC hCopyDC = CreateCompatibleDC(hMainDialogDC); SelectObject(hCopyDC, hCopyBMP); PrintWindow(hMainDialog, hCopyDC, 0); Gdiplus::GdiplusStartupInput gdipSI; Gdiplus::ImageCodecInfo *codecInfo; Gdiplus::GpBitmap *bmpCopyBMP; DWORD gdipToken, dwEncNum, dwEncSize, iEnc = -1; gdipSI.GdiplusVersion = 1; Gdiplus::GdiplusStartup(&gdipToken, &gdipSI, NULL); Gdiplus::DllExports::GdipCreateBitmapFromHBITMAP(hCopyBMP, 0, &bmpCopyBMP); Gdiplus::DllExports::GdipGetImageEncodersSize((PUINT)&dwEncNum, (PUINT)&dwEncSize); codecInfo = (Gdiplus::ImageCodecInfo *)HeapAlloc(GetProcessHeap(), 0, dwEncSize); Gdiplus::DllExports::GdipGetImageEncoders(dwEncNum, dwEncSize, codecInfo); for (DWORD i = 0; i < dwEncNum; i++) if (!lstrcmp(codecInfo[i].MimeType, _T("image/png"))) { iEnc = i; break; } if (iEnc >= 0) { Gdiplus::GpBitmap *bmpCopyBMPBuf = NULL; Gdiplus::DllExports::GdipCreateBitmapFromScan0(width, height, 0, PixelFormat24bppRGB, NULL, &bmpCopyBMPBuf); Gdiplus::GpGraphics *g = NULL; Gdiplus::DllExports::GdipGetImageGraphicsContext(bmpCopyBMPBuf, &g); Gdiplus::DllExports::GdipDrawImageI(g, bmpCopyBMP, 0, 0); Gdiplus::DllExports::GdipSaveImageToFile(bmpCopyBMPBuf, _T("dbgscreen.png"), &codecInfo[iEnc].Clsid, NULL); Gdiplus::DllExports::GdipDisposeImage(bmpCopyBMPBuf); } HeapFree(GetProcessHeap(), 0, codecInfo); Gdiplus::DllExports::GdipDisposeImage(bmpCopyBMP); Gdiplus::GdiplusShutdown(gdipToken); DeleteDC(hCopyDC); DeleteObject(hCopyBMP); ReleaseDC(hMainDialog, hMainDialogDC); Аналогично вместо GdipSaveImageToFile можно использовать GdipSaveImageToStream (предварительно создав поток вызовом CreateStreamOnHGlobal). Тогда сохраняться будет в память.
спасибо, с этим разобрался. появился еще вопрос: принимаю файл по N байт(recv()). Последняя порция придет меньше, но рекв будет считывать именно N байт, что в итоге приведет к мусору в файле. как избавится от этой неприятности?
Ясно, это я налажал. Разобрался вроде, но не до конца. Данные принимаются нормально, но не всегда. Гуглил-гуглил, похоже, что сервак шлет быстрее, чем принимает клиент. если вставить после сенда в сервере Sleep(10) - то все ок. Есть возможность решить проблему без слипа?
bug1z Если это TCP (судя по теме, так и есть), то в него встроен механизм flow control, а также всевозможные коррекции с прозрачными для пользователя ретрансмиссиями и прочими наворотами, поэтому, если такая ситуация и возникает, то она разруливается без участия пользователя, и соответственно никаких проблем возникнуть не должно.
Понятно. Но я вернулся к тому, с чего начинал(уж простите за такое обилие вопросов). По некоторым причинам реконект не подойдет - необходимо удерживать постоянное соединение клиента и сервера. Но здесь взвращаюсь к посту номер один. Возможно это сделать используя TCP? То есть после send() у меня recv() "висит" до тех пор, пока не будет закрыто соединение. Что то читал про асинхронные сокеты, которые якобы не дожидаются пока завершится передача данных. В эту сторону копать?
bug1z Как уже сказал Dmitry_Milk, такой проблемы тоже нет. Не будет протокол ждать, пока соединение закроют, чтобы вернуть управление из recv. Точнее такое возможно, только если Вы при вызове recv указали большой буфер и флаг MSG_WAITALL. Но блин. Сами же тогда и виноваты.
Он ждет новой порции сообщений, почему то. Я в цикле передаю небольшое сообщение(6 байт) с интервалом в 50000мс. Но recv() все равно не возвращает управление, а ждет пока пройдет 50000мс и получает новое сообщение добавляя его в тот же буфер. Почему так происходит?