Автор
|
Тема: Сокеты, Sockets, Proxi, Threads and MFC
|
server_mouse |
опубликован 19-11-2001 13:12 MSK
Привет всем.Есть клиент связывающийся сразу со многими серверами. Каждое новое соединение запускаю в новом потоке. Все сокеты без MFC. Каждый поток в вечном цикле ожидает некоторого события для завершения и события от сокета. Или на более понятном языке ;)) DWORD WINAPI CCafe::SockThread(LPVOID ts) { sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //... Всякая инициализация сокета.... hEvent = WSACreateEvent(); ::WSAEventSelect(sock, hEvent, FD_CONNECT|FD_READ|FD_CLOSE); connect(sock,(struct sockaddr *)&sin, sizeof(struct sockaddr); for(;;) //Вечный цикл ожидания манны небесной { if(WaitForSingleObject(CloseEvent,0)==WAIT_OBJECT_0) {//Пора сворачивоть работу.... shutdown(sock,2); closesocket(sock); WSACloseEvent(hEvent); return 0; } if( WSA_WAIT_FAILED != ::WSAWaitForMultipleEvents(1, &hEvent, false,50,false)) { //Ну а здесь собственно обработчик сетевых событий... } }//for(;;) }//Thread Так вот, нужно что б в потоке работал CAsyncSoket. Я-то смогу зациклить поток, но обработчик того-же OnConnect() никогда не вызывается. Как 'передать управление' классу CAsyncSocket что бы он проверил свои сетевые события?
Наверное есть более красивое решение проблемы. Я просто хочу заюзать MFC-класс для того, что бы потом включить поддержку прокси.
|
lamo
|
опубликован 19-11-2001 18:09 MSK
тяжелый случай. подскаска намбер ван - мфц нах.зы. опохмеляться надо. |
Demo_S
|
опубликован 22-11-2001 22:16 MSK
2lamo Пришли что-нить похожее на чистом апи (или не очень чистом):)) я не к тому, что неудобно или трудно. протсо мне интерестно посмотреть как это будет на апи. |
Flex Ferrum
|
опубликован 23-11-2001 12:08 MSK
А прокси какого уровня иы хочешь юзать? SOCKS или HTTP? Кстати, и зачем СAsyncSocket? Чем блокирующий не устраивает? А вообще совет такой - один раз посидеть попарится с нормальной библиотекой сокетов, завернутой на stl::iostream - и никаких проблем в будущем :))) По поводу AsyncSocket: мне кажется, что в твоем случае OnConnect и не должно вызываться - у тебя сокет клиентский, из чего следует, что он работает синхронно с программой (клиент-то точно знает, когда он подключается к серверу:)) - это первое. Второе - эти события будут вызываться только под GUI приложением с очередью обработки сообщений - покрайней мере так я понял из исходников.2Demo_S: А по моему, это чистый АПИ и есть... |
not available
|
опубликован 25-11-2001 03:39 MSK
Не делай thread членом класса - все будет работать |
Valery
|
опубликован 26-11-2001 15:56 MSK
2Flex Ferrum: на мыло не ответил, сюда повторюсь: что за библиотеку сокетов ты упоминаешь закрученную на stl::iostream ? |
vladz
|
опубликован 26-11-2001 18:23 MSK
2Flex Ferrum: Гляньте еще разок на код.. "..hEvent = WSACreateEvent();.. WSAEventSelect(.." это к GUI не имеет никакого отношения, это же не WSAAsyncSelect2server_mouse: А вот OnConnect-а действительно не будет :) |
server_mouse
|
опубликован 26-11-2001 23:55 MSK
2Flex Ferrum: Чесно говоря в исходники MFC не лазил, но полагаю, что вызов перегруженых методов типа OnConnect(), OnClose, OnReceive() идёт примерно тем же методом что и у меня в исходе -- запускается нить которая ждёт сетевых событий. Речь не о WM_SOCKET_NOTIFY. Оно действительно может приходить только окну. На то и WM.2vladz : Не совсем понял то, что намылил....
|
server_mouse
|
опубликован 27-11-2001 12:01 MSK
2not available : В чём разница между static-методом класса и глобальной ф-цией?2Demo_S: МФЦ тут и не пахнет... ;)
|
Flex Ferrum
|
опубликован 27-11-2001 15:08 MSK
vladz: RTFM! WSA.... - API-шные функции из библиотеки Winsock2 и к MFC никакого отношения не имеют.server_mouse: А зря - они есть истина :))) А вот и ответ на вопрос: int PASCAL CSocket::ProcessAuxQueue() { _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState; if (pState->m_plistSocketNotifications->IsEmpty()) return 0; int nCount = 0; while(!pState->m_plistSocketNotifications->IsEmpty()) { nCount++; MSG* pMsg = (MSG*)pState->m_plistSocketNotifications->RemoveHead(); ASSERT(pMsg != NULL); if (pMsg->message == WM_SOCKET_NOTIFY) { CAsyncSocket::DoCallBack(pMsg->wParam, pMsg->lParam); } else { ASSERT(CAsyncSocket::LookupHandle((SOCKET)pMsg->wParam, TRUE) != NULL); CAsyncSocket::DetachHandle((SOCKET)pMsg->wParam, TRUE); } delete pMsg; } return nCount; } void PASCAL CSocket::AuxQueueAdd(UINT message, WPARAM wParam, LPARAM lParam) { _AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState; MSG* pMsg = new MSG; pMsg->message = message; pMsg->wParam = wParam; pMsg->lParam = lParam; pState->m_plistSocketNotifications->AddTail(pMsg); } BOOL CSocket::PumpMessage(...) { // ... if (::PeekMessage(&msg, pState->m_hSocketWindow, WM_SOCKET_NOTIFY, WM_SOCKET_DEAD, PM_REMOVE)) { if (msg.message == WM_SOCKET_NOTIFY && (SOCKET)msg.wParam == m_hSocket) { if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE) { break; } if (WSAGETSELECTEVENT(msg.lParam) == uStopFlag) { if (uStopFlag == FD_CONNECT) m_nConnectError = WSAGETSELECTERROR(msg.lParam); break; } } if (msg.wParam != 0 |
Demo_S
|
опубликован 27-11-2001 23:32 MSK
гм, то что WSA... эт апи в винде я в принципе знаю. Я неправильно спросил... меня интересовало как сделать это _только_ с помощью send,recv,accept,select... то есть чтоб программа одинаково работала под вынь и под уних... (в смысле после компиляции в соответствующей системе) или такое невозможно? |
Flex Ferrum
|
опубликован 28-11-2001 14:59 MSK
Могу тебя огорчить - никак. В смысле, что без WSA не обойдешься. "Это и будет твоей системно-зависимой частью" (с) не я :))). Например, errno в винде никогда тебе не вернет ошибку работы с сокетом. |