sockets

Тема в разделе "WASM.NETWORKS", создана пользователем bug1z, 3 дек 2011.

  1. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    Добрый день. Интересует такой вопрос:

    Как можно отправлять сообщения клиенту с заданным интервалом?

    То есть например мне нужно отправить три сообщением с интервалом в 30 секунд.

    если я сделаю
    send(...);
    Sleep(...);
    send(...);
    Sleep(...);
    send(...);
    closesocket(...);

    то recv примет их всех 1м разом, а мне нужно, чтоб сообщения у клиента выводились с интервалом в 30 секунд. как такое сделать?
     
  2. Kaimi

    Kaimi Андрей

    Публикаций:
    0
    Регистрация:
    15 апр 2010
    Сообщения:
    120
    Закрывать-открывать сокет между отправками?
     
  3. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    я достаю сокет с помощью accept() и передаю его в отдельный поток. если я его закрою с помощью closesocket() как его снова открыть из этого же потока?
     
  4. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    bug1z
    Организовать "рукопожатие" между клиентом и сервером.
    Отсылает - ждем подтверждение - отсылаем - ждем подтверждение - ...
     
  5. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    а можно поподробнее?
    вы имеете в виду ф-ю shutdown?
     
  6. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    вставил после каждого слипа stutdown с параметром SD_BOTH - не помогло.
    есть еще соображения как решить эту проблему?
     
  7. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    UDP, т.к. TCP на серваке по 30сек висеть в ожидании - разрыв ресурсов. Второй вариант как выше и говорили - клиент
    connect()
    send( reconnect_timeout )
    recv();
    close_socket();
    Sleep(30000);
    connect()
    send();
    recv();
    closesocket();
    ...

    это для посылки серверу сообщений (см. TCP протокол) "я больше не буду ничего отправлять" или "я больше не собираюсь ничо принимать"
    *я = сокет.
     
  8. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    сделал вторым вариантом, с реконнектом. работает. спасибо.
    хотелось бы еще узнать: такие программы как The Bat, они ведь тоже не постоянно подключены, а реконектятся время от времени, забирают почту?
     
  9. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    а вы запустите wireshark и вопросы отпадут сами.
     
  10. rpy3uH

    rpy3uH New Member

    Публикаций:
    0
    Регистрация:
    14 сен 2006
    Сообщения:
    503
    там совсем другая история, протокол другой. коннект, запросы, ответы, дисконнект.
     
  11. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Вообще странно. С чего это так?
    Когда-то давно я писал чатовый сервак на чистых TCP-сокетах. Клиенты (java-апплеты) держали постоянные TCP-коннекты к серваку на C++. Как кто-то из клиентов присылал сообщение, или если встроенный бот его генерил - оно тут же отправлялось всем подключенным клиентам. Никаких дисконнектов. Как надо - тут же разослалось. Пока не надо - все висят, ждут. Правда протокол там был типа (длина/сообщение).
     
  12. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    Есть еще один вопрос. Сервер создает некое изображение(HBITMAP), затем преобразовывает его в png и отправляет клиенту. как это лучше организовать? Сохранять изображение на винт, затем читать в массив байтов и отправлять, или же есть варианты получше?
     
  13. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    bug1z
    Зачем сохранять на винт? Можно и в поток GDI+. Пример сохранения снимка окошка в файл:
    Код (Text):
    1. HDC hMainDialogDC = GetWindowDC(hMainDialog);
    2. RECT windowRect; GetWindowRect(hMainDialog, &windowRect);
    3. DWORD width = windowRect.right-windowRect.left, height = windowRect.bottom - windowRect.top;
    4. HBITMAP hCopyBMP = CreateCompatibleBitmap(hMainDialogDC, width, height);
    5. HDC hCopyDC = CreateCompatibleDC(hMainDialogDC);
    6. SelectObject(hCopyDC, hCopyBMP);
    7.     PrintWindow(hMainDialog, hCopyDC, 0);
    8.  
    9.     Gdiplus::GdiplusStartupInput gdipSI;
    10.     Gdiplus::ImageCodecInfo *codecInfo;
    11.     Gdiplus::GpBitmap *bmpCopyBMP;
    12.     DWORD gdipToken, dwEncNum, dwEncSize, iEnc = -1;
    13.  
    14.     gdipSI.GdiplusVersion = 1;
    15.     Gdiplus::GdiplusStartup(&gdipToken, &gdipSI, NULL);
    16.         Gdiplus::DllExports::GdipCreateBitmapFromHBITMAP(hCopyBMP, 0, &bmpCopyBMP);
    17.             Gdiplus::DllExports::GdipGetImageEncodersSize((PUINT)&dwEncNum, (PUINT)&dwEncSize);
    18.             codecInfo = (Gdiplus::ImageCodecInfo *)HeapAlloc(GetProcessHeap(), 0, dwEncSize);
    19.                 Gdiplus::DllExports::GdipGetImageEncoders(dwEncNum, dwEncSize, codecInfo);
    20.                 for (DWORD i = 0; i < dwEncNum; i++)
    21.                     if (!lstrcmp(codecInfo[i].MimeType, _T("image/png")))
    22.                     {
    23.                         iEnc = i;
    24.                         break;
    25.                     }
    26.                 if (iEnc >= 0)
    27.                 {
    28.                     Gdiplus::GpBitmap *bmpCopyBMPBuf = NULL;
    29.                     Gdiplus::DllExports::GdipCreateBitmapFromScan0(width, height, 0, PixelFormat24bppRGB, NULL, &bmpCopyBMPBuf);
    30.                     Gdiplus::GpGraphics *g = NULL;
    31.                     Gdiplus::DllExports::GdipGetImageGraphicsContext(bmpCopyBMPBuf, &g);
    32.                     Gdiplus::DllExports::GdipDrawImageI(g, bmpCopyBMP, 0, 0);
    33.  
    34.                     Gdiplus::DllExports::GdipSaveImageToFile(bmpCopyBMPBuf, _T("dbgscreen.png"), &codecInfo[iEnc].Clsid, NULL);
    35.  
    36.                     Gdiplus::DllExports::GdipDisposeImage(bmpCopyBMPBuf);
    37.                 }
    38.             HeapFree(GetProcessHeap(), 0, codecInfo);
    39.         Gdiplus::DllExports::GdipDisposeImage(bmpCopyBMP);
    40.     Gdiplus::GdiplusShutdown(gdipToken);
    41. DeleteDC(hCopyDC);
    42. DeleteObject(hCopyBMP);
    43. ReleaseDC(hMainDialog, hMainDialogDC);
    Аналогично вместо GdipSaveImageToFile можно использовать GdipSaveImageToStream (предварительно создав поток вызовом CreateStreamOnHGlobal). Тогда сохраняться будет в память.
     
  14. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    спасибо, с этим разобрался. появился еще вопрос:
    принимаю файл по N байт(recv()). Последняя порция придет меньше, но рекв будет считывать именно N байт, что в итоге приведет к мусору в файле. как избавится от этой неприятности?
     
  15. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    bug1z
    Это ещё почему? Если придёт меньше, то и возвращено будет меньше.
     
  16. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    Ясно, это я налажал. Разобрался вроде, но не до конца.
    Данные принимаются нормально, но не всегда. Гуглил-гуглил, похоже, что сервак шлет быстрее, чем принимает клиент. если вставить после сенда в сервере Sleep(10) - то все ок.
    Есть возможность решить проблему без слипа?
     
  17. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    bug1z
    Если это TCP (судя по теме, так и есть), то в него встроен механизм flow control, а также всевозможные коррекции с прозрачными для пользователя ретрансмиссиями и прочими наворотами, поэтому, если такая ситуация и возникает, то она разруливается без участия пользователя, и соответственно никаких проблем возникнуть не должно.
     
  18. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    Понятно. Но я вернулся к тому, с чего начинал(уж простите за такое обилие вопросов).
    По некоторым причинам реконект не подойдет - необходимо удерживать постоянное соединение клиента и сервера.
    Но здесь взвращаюсь к посту номер один. Возможно это сделать используя TCP?
    То есть после send() у меня recv() "висит" до тех пор, пока не будет закрыто соединение.
    Что то читал про асинхронные сокеты, которые якобы не дожидаются пока завершится передача данных. В эту сторону копать?
     
  19. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    bug1z
    Как уже сказал Dmitry_Milk, такой проблемы тоже нет. Не будет протокол ждать, пока соединение закроют, чтобы вернуть управление из recv. Точнее такое возможно, только если Вы при вызове recv указали большой буфер и флаг MSG_WAITALL. Но блин. Сами же тогда и виноваты.
     
  20. bug1z

    bug1z New Member

    Публикаций:
    0
    Регистрация:
    27 дек 2008
    Сообщения:
    228
    Он ждет новой порции сообщений, почему то.

    Я в цикле передаю небольшое сообщение(6 байт) с интервалом в 50000мс.
    Но recv() все равно не возвращает управление, а ждет пока пройдет 50000мс и получает новое сообщение добавляя его в тот же буфер. Почему так происходит?