WinRoute Firewall 10054 recv

Тема в разделе "WASM.NETWORKS", создана пользователем Crash, 11 авг 2007.

  1. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    Привет всем!

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

    Моя программа состоит из 3-х частей:
    1) LANPhone (координирующая, интерфейс пользователю и все такое)
    2) SendWave (ловит звук с микрофона и отправляет по сети звуковые буферы программе RecvWave на другой машине)
    3) RecvWave (принимает звуковые буферы, посланные программой SendWave на удаленной машине, и воспроизводит звук)

    LANPhone может работать как в режиме клиента (когда мы "звоним" кому-то), так и в режиме сервера (когда до нас "дозванивается" кто-то).

    У меня стоит Kerio WinRoute Firewall, правила настроены верно. Так вот, когда фаер включен, SendWave на сервере почему-то сначала работает (посылает пакеты секунд 5-10), а потом завершается. Я выяснил, что это из-за того, что функция recv в SendWave завершается с ошибкой 10054 (Удаленный хост принудительно разорвал существующее подключение).

    Если пробовать с выключенным WinRoute, то все ОК.

    Нашел в Сети почти аналогичную программу lanic, она работает без проблем и с включенным WinRoute. Не пойму, почему фаер внезапно обрубает соединение.
    В настройках вроде никаких особых ограничений нет.
     
  2. mathio

    mathio New Member

    Публикаций:
    0
    Регистрация:
    16 июн 2007
    Сообщения:
    110
    В этой ситуации можно что-то посоветовать лишь видя картину в деталях.
    Тоесть нужны либо исходники приемо-передатчиков, либо, что проще, закапчурите весь сетевой обмен(весь трафик) каким-нибудь Ethereal'ом(желательно, т.к. имею оное и смогу помочь) и приаттачьте логи сюда/либо в ЛС киньте на них линк.
     
  3. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    Вот исходник SendWave. Исходник еще сырой и неоптимизированный, поэтому просьба не ругаться.

    Заметим, что флаг fStopSendWave устанавливается в TRUE, когда recv возвращается с ошибкой. Если fStopSendWave == TRUE, то происходит процесс завершения программы.

    Код (Text):
    1. BOOL   fStopSendWave   = FALSE;
    2. DWORD  dwMainThreadId  = 0;
    3. DWORD  dwIPAddr        = 0;
    4. WORD   wPort           = 0;
    5. HANDLE hSendWaveThread = INVALID_HANDLE_VALUE;
    6. HWND   hMainWnd;
    7. BOOL   fStartWasSended = FALSE;
    8.  
    9. #define WM_USER_START WM_USER + 1024
    10. #define WM_USER_STOP  WM_USER + 1025
    11.  
    12. #define SampleRate    11025
    13. #define BitsPerSample 8
    14. #define Channels 1
    15.  
    16. #define BufferMS 500
    17. #define Buffers  4
    18.  
    19. DWORD g_dwAllocatedBuffers;
    20. DWORD g_dwSendWaveThreadId;
    21. HWAVEIN g_hWaveIn;
    22. SOCKET g_Socket;
    23.  
    24. BOOL OpenDevice() {
    25.     MMRESULT Res;
    26.     WAVEFORMATEX Format;
    27.  
    28.     g_dwAllocatedBuffers = 0;
    29.  
    30.     UINT BytesPerSample = (BitsPerSample + 7) / 8;
    31.  
    32.     Format.wFormatTag      = WAVE_FORMAT_PCM;
    33.     Format.nChannels       = Channels;
    34.     Format.wBitsPerSample  = BitsPerSample;
    35.     Format.nBlockAlign     = (WORD)(Channels * BytesPerSample);
    36.     Format.nSamplesPerSec  = SampleRate;
    37.     Format.nAvgBytesPerSec = Format.nSamplesPerSec * Format.nBlockAlign;
    38.     Format.cbSize          = 0;
    39.  
    40.     Res = waveInOpen(&g_hWaveIn, 0, &Format, g_dwSendWaveThreadId, 0, CALLBACK_THREAD);
    41.     if (Res != MMSYSERR_NOERROR) {
    42.         return FALSE;
    43.     }
    44.  
    45.     UINT BufferSize = (Format.nSamplesPerSec * BufferMS / Buffers + 500) / 1000;
    46.     if (!BufferSize) {
    47.         BufferSize++;
    48.     }
    49.     BufferSize *= Format.nBlockAlign;
    50.  
    51.     for (int N = Buffers; N > 0; N--) {
    52.         char *Buf = (char *)GlobalAlloc(GMEM_FIXED, BufferSize);
    53.         WAVEHDR *Hdr = (WAVEHDR *)LocalAlloc(LMEM_FIXED, sizeof(*Hdr));
    54.  
    55.         if (Buf && Hdr) {
    56.             Hdr->lpData = Buf;
    57.             Hdr->dwBufferLength = BufferSize;
    58.             Hdr->dwFlags = 0;
    59.             Hdr->dwLoops = 0;
    60.             Hdr->dwUser = 0;
    61.  
    62.             waveInPrepareHeader (g_hWaveIn, Hdr, sizeof (*Hdr));
    63.             Res = waveInAddBuffer (g_hWaveIn, Hdr, sizeof (*Hdr));
    64.         }
    65.  
    66.         if (Buf && Hdr && Res == MMSYSERR_NOERROR) {
    67.             g_dwAllocatedBuffers++;
    68.         } else {
    69.             if (Buf) {
    70.                 GlobalFree ((HGLOBAL)Buf);
    71.             }
    72.  
    73.             if (Hdr) {
    74.                 LocalFree ((HLOCAL)Hdr);
    75.             }
    76.             return FALSE;
    77.         }
    78.     }
    79.     return TRUE;
    80. }
    81.  
    82. VOID CloseDevice() {
    83.     waveInClose(g_hWaveIn);
    84.     closesocket(g_Socket);
    85.     SendMessage(hMainWnd, WM_CLOSE, 0, 0);
    86. }
    87.  
    88. VOID ReleaseBuffer(WAVEHDR *Hdr) {
    89.     GlobalFree((HGLOBAL)Hdr->lpData);
    90.     LocalFree((HLOCAL)Hdr);
    91.  
    92.     g_dwAllocatedBuffers--;
    93.  
    94.     if (!g_dwAllocatedBuffers) {
    95.         PostThreadMessage(g_dwSendWaveThreadId, WM_QUIT, 0, 0);
    96.     }
    97. }
    98.  
    99. DWORD WINAPI SendWaveThreadProc(LPVOID lpParam) {
    100.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
    101.  
    102.     MSG msg;
    103.     while (GetMessage(&msg, NULL, 0, 0) == TRUE) {
    104.         switch (msg.message) {
    105.         case MM_WIM_DATA: {
    106.             WAVEHDR *Hdr = (WAVEHDR *)msg.lParam;
    107.  
    108.             waveInUnprepareHeader(g_hWaveIn, Hdr, sizeof(*Hdr));
    109.             if (fStopSendWave) {
    110.                 ReleaseBuffer(Hdr);
    111.                 break;
    112.             }
    113.  
    114.             int bytesRecv;
    115.             char recvbuf[32] = "";
    116.  
    117.             if (!fStopSendWave) {
    118.                 if (send(g_Socket, (const char *)Hdr, sizeof(*Hdr), 0) == SOCKET_ERROR) {
    119.                 }
    120.  
    121.                 bytesRecv = recv(g_Socket, recvbuf, sizeof(recvbuf), 0);
    122.                 if (bytesRecv < 0) {
    123.                     // Ошибка бывает здесь: WSAGetLastError() == 10054
    124.  
    125.                     waveInPrepareHeader(g_hWaveIn, Hdr, sizeof (*Hdr));
    126.                     waveInAddBuffer(g_hWaveIn, Hdr, sizeof (*Hdr));
    127.                     fStopSendWave = TRUE;
    128.                     break;
    129.                 }
    130.             }
    131.  
    132.             if (!fStopSendWave) {
    133.                 if (send(g_Socket, (const char *)Hdr->lpData, Hdr->dwBufferLength, 0) == SOCKET_ERROR) {
    134.                 }
    135.                 bytesRecv = recv(g_Socket, recvbuf, sizeof(recvbuf), 0);
    136.                 if (bytesRecv < 0) {
    137.                     // Ошибка бывает здесь: WSAGetLastError() == 10054
    138.  
    139.                     waveInPrepareHeader(g_hWaveIn, Hdr, sizeof(*Hdr));
    140.                     waveInAddBuffer(g_hWaveIn, Hdr, sizeof(*Hdr));
    141.                     fStopSendWave = TRUE;
    142.                     break;
    143.                 }
    144.             }
    145.  
    146.             if (!fStopSendWave) {
    147.                 waveInPrepareHeader(g_hWaveIn, Hdr, sizeof(*Hdr));
    148.                 waveInAddBuffer(g_hWaveIn, Hdr, sizeof(*Hdr));
    149.             }
    150.             break;
    151.         }
    152.         }
    153.     }
    154.  
    155.     CloseDevice();
    156.     return 0;
    157. }
    158.  
    159. DWORD WINAPI Start(LPVOID lpParam) {
    160.     g_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    161.  
    162.     sockaddr_in clientService;
    163.     clientService.sin_family      = AF_INET;
    164.     clientService.sin_addr.s_addr = dwIPAddr;
    165.     clientService.sin_port        = htons(wPort);
    166.  
    167.     while (connect(g_Socket, (SOCKADDR*)&clientService, sizeof(clientService)) == SOCKET_ERROR && !fStopSendWave) {
    168.         Sleep(1);
    169.     }
    170.  
    171.     if (fStopSendWave) {
    172.         closesocket(g_Socket);
    173.         SendMessage(hMainWnd, WM_CLOSE, 0, 0);
    174.         return 0;
    175.     }
    176.  
    177.     SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
    178.  
    179.     hSendWaveThread = CreateThread(NULL, 0, SendWaveThreadProc, NULL, CREATE_SUSPENDED, &g_dwSendWaveThreadId);
    180.     if (hSendWaveThread) {
    181.         if (OpenDevice()) {
    182.             ResumeThread(hSendWaveThread);
    183.             if (waveInStart(g_hWaveIn) == MMSYSERR_NOERROR) {
    184.                 CloseHandle(hSendWaveThread);
    185.                 hSendWaveThread = INVALID_HANDLE_VALUE;
    186.                 return 0;
    187.             } else {
    188.                 CloseDevice();
    189.             }
    190.         }
    191.     }
    192.  
    193.     if (hSendWaveThread) {
    194.         TerminateThread(hSendWaveThread, 0);
    195.         CloseHandle(hSendWaveThread);
    196.     }
    197.     hSendWaveThread = INVALID_HANDLE_VALUE;
    198.     return 0;
    199. }
    200.  
    201. VOID Stop() {
    202.     if (fStartWasSended) {
    203.         fStopSendWave = TRUE;
    204.         waveInReset(g_hWaveIn);
    205.         closesocket(g_Socket);
    206.     } else {
    207.         SendMessage(hMainWnd, WM_CLOSE, 0, 0);
    208.     }
    209. }
    210.  
    211. LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    212.     switch (uMsg) {
    213.     case WM_USER_START:
    214.         dwIPAddr = lParam;
    215.         wPort    = wParam;
    216.         CloseHandle(CreateThread(NULL, 0, Start, NULL, 0, NULL));
    217.         fStartWasSended = TRUE;
    218.         break;
    219.  
    220.     case WM_USER_STOP:
    221.         Stop();
    222.         break;
    223.  
    224.     case WM_CLOSE:
    225.         PostQuitMessage(0);
    226.         break;
    227.     }
    228.     return DefWindowProc(hwnd, uMsg, wParam, lParam);
    229. }
    230.  
    231. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow) {
    232.     // Ограничиваем память процесса на всякий случай
    233.     HANDLE hJob = CreateJobObject(NULL, NULL);
    234.  
    235.     AssignProcessToJobObject(hJob, GetCurrentProcess());
    236.  
    237.     JOBOBJECT_EXTENDED_LIMIT_INFORMATION lim;
    238.  
    239.     lim.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
    240.     lim.ProcessMemoryLimit               = 1024 * 1024 * 10;
    241.     SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &lim, sizeof(lim));
    242.     // -------------------
    243.  
    244.     WSADATA wsaData;
    245.     int nWSARes = WSAStartup(MAKEWORD(2, 2), &wsaData);
    246.     if (nWSARes != NO_ERROR) {
    247.         return nWSARes;
    248.     }
    249.  
    250.     WNDCLASS lpWndClass;
    251.  
    252.     lpWndClass.cbClsExtra = 0;
    253.     lpWndClass.cbWndExtra = 0;
    254.     lpWndClass.hbrBackground = 0;
    255.     lpWndClass.hCursor = 0;
    256.     lpWndClass.hIcon = 0;
    257.     lpWndClass.hInstance = hInstance;
    258.     lpWndClass.lpfnWndProc = WindowProc;
    259.     lpWndClass.lpszClassName = _TEXT("SendWave");
    260.     lpWndClass.lpszMenuName = 0;
    261.     lpWndClass.style = 0;
    262.     RegisterClass(&lpWndClass);
    263.  
    264.     hMainWnd = CreateWindowEx(0, lpWndClass.lpszClassName, lpWndClass.lpszClassName, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
    265.  
    266.     MSG msg;
    267.     BOOL bRet;
    268.     while ((bRet = GetMessage(&msg, hMainWnd, 0, 0)) != 0) {
    269.         if (bRet == -1) {
    270.             break;
    271.         }
    272.         DispatchMessage(&msg);
    273.     }
    274.  
    275.     WSACleanup();
    276.     return 0;
    277. }
     
  4. mathio

    mathio New Member

    Публикаций:
    0
    Регистрация:
    16 июн 2007
    Сообщения:
    110
    Если честно, то по сетевому дампу быстрее и проще локализовать проблему.
     
  5. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    ОК, тогда что мне использовать?
     
  6. mathio

    mathio New Member

    Публикаций:
    0
    Регистрация:
    16 июн 2007
    Сообщения:
    110
    http://www.ethereal.com/download.html
    Нужно сделать полный лог, включающий моменты установления соединения между клиентом-сервером и до его "внезапного" обрыва. Плюс к этому желательно укажите IP адреса клиента и сервера, чтоб не тратить время.
     
  7. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    192.168.1.1 - клиент (кто "дозванивался")
    192.168.1.2 - сервер (куда "дозванивались")

    Порт 22221 используется программой LANPhone
    Порт 22222 используется RecvWave и SendWave

    При логе я поставил фильтр, чтобы отслеживались только эти IP адреса.
     
  8. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    лог: http://webfile.ru/download.php?id=1494588
     
  9. mathio

    mathio New Member

    Публикаций:
    0
    Регистрация:
    16 июн 2007
    Сообщения:
    110
    Хм, в конце лога все нормально, т.е. даже такое впечатление, что соединение не порвалось. По крайней мере нет ни FIN'ов, ни TCP ретрансмитта с какой-либо стороны в следствии неких тайм-аутов.
    Лог действительно создавался вплоть _до_ разрыва связи?(т.е. включая и разрыв)

    А вообще, у меня было предположение, что на каком-то этапе общения происходит рассинхронизация и одна из сторон "долбится" в уже закрытый порт.
     
  10. Crash

    Crash New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2004
    Сообщения:
    73
    Да, лог закрывался уже после того, как были закрыты обе программы.
    Рассинхронизация в принципе не может быть. Клиент посылает данные, а сервер отвечает. После того, как сервер ответил, клиент снова посылает и т.д.

    Тут почему-то файервол мешает. Без него все нормально.