컴퓨터 지식 네트워크 - 컴퓨터 지식 - 200포인트, C네트웍 통신, 마스터, 실무경력 있으신 분들은 참여해주세요! !

200포인트, C네트웍 통신, 마스터, 실무경력 있으신 분들은 참여해주세요! !

친구들! ! ! 다음과 같아야 할 것 같습니다.

CSocket은 CAsyncSocket을 기반으로 MFC에서 파생된 동기식 차단 소켓 캡슐화 클래스입니다. CAsyncSocket을 동기화된 소켓으로 바꾸고 동일한 소켓 이벤트에 응답하려면 어떻게 해야 합니까? 실제로는 매우 간단합니다. Connect()가 WSAEWOULDBLOCK 오류를 반환하면 CSocket은 OnConnect() 및 OnReceive()의 이벤트 터미널 함수에서 기다리지 않습니다. 먼저 소켓 이벤트가 이러한 이벤트 함수에 어떻게 도달하는지 이해해야 합니다. 이러한 이벤트 처리 함수는 CSocketWnd 창 개체에 의해 다시 호출되며 창 개체는 소켓에서 이벤트를 수신하고 스레드 메시지 큐에 의해 배포됩니다. 즉, 소켓 이벤트는 먼저 CSocketWnd 창 개체에 메시지로 전송됩니다. 이 메시지는 스레드 메시지 대기열을 통해 배포되어야 합니다. 마지막으로 CSocketWnd 창 개체는 수신 후 해당 콜백 함수(OnConnect() 등)를 호출합니다. 이 메시지.

따라서 CSocket이 Connect()를 호출한 후 WSAEWOULDBLOCK 오류를 반환하면 메시지 추출을 위해 즉시 PumpMessage(...) 함수를 호출합니다. 이는 현재 스레드의 메시지 큐에서 관심 있는 메시지를 검색하는 것입니다. 다음과 같은 상황이 발생합니다. 1. 사용자가 사용 중인 소켓에서 보낸 WM_SOCKET_NOTIFY 메시지와 해당 FD_XXX 이벤트가 추출됩니다(메시지 큐에서 제거). 2. 메시지가 추출됩니다(메시지 큐에서 제거). ). 제거), 사용자가 사용 중인 소켓에서 전송한 WM_SOCKET_NOTIFY 메시지 및 해당 FD_Close 이벤트는 True를 반환합니다. 3 PumpMessage(..)에 의해 설정된 타이머의 WM_TIMER 메시지를 추출합니다. TimeOut 이벤트는 CSocket의 멤버 변수인 m_nTimeOut=2000ms이며 True를 반환합니다. 4. 사용자가 CancelBlockingCall()을 호출하고 오류 코드를 WSAEINTR(중단됨)로 설정한 후 False를 반환했습니다. 5. 사용자는 소켓에서 보낸 WM_SOCKET_NOTIFY를 받지 못했습니다. 사용자는 메시지와 해당 FD_XXX 이벤트를 사용하지만 동일한 스레드에 있는 다른 소켓의 WM_SOCKET_NOTIFY 메시지와 해당 메시지를 얻은 경우 이 메시지는 나중에 처리하기 위해 보조 대기열에 추가됩니다. 이 스레드의 메시지 대기열에 다른 메시지가 있는지 확인(꺼내는 것이 아니라 확인)을 시작합니다. 있는 경우 가상 함수 OnMessagePending()을 호출하여 이러한 메시지를 처리합니다(OnMessagePending() 사용자는 차단할 때 사용자가 처리하려는 메시지), 그렇지 않은 경우 WaitMessage()를 호출하여 메시지 도착을 기다리기 시작합니다. 코드 설명은 다음과 같습니다. A Connect의 차단 구현은 Accept, receive와 동일하므로 먼저 Connect를 살펴보겠습니다. , receiveFrom, Send, SendTo 그것들은 모두 약간 다릅니다. 실제로 Connect(...) 대신 ConnectHelper(...)가 무엇인지 궁금할 것입니다. ) 실제로 다음과 같이 호출합니다: BOOL CAsyncSocket: :Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen) { return ConnectHelper(lpSockAddr, nSockAddrLen) } //ConnectHelper(...)는 가상 함수입니다. //CAsyncSocket, Csocket에서 상속됨 //이것이 CSocket이 Public BOOL에서 상속된 이유입니다. CSocket::ConnectHelper(...) { //호출되면 먼저 현재 진행 중인 차단 작업이 있는지 확인합니다. //그렇다면 반환합니다. 즉시 오류 코드를 설정합니다... ...... m_nConnectError = -1 //CAsyncSocket을 한 번만 호출합니다. ConnectHelper( ... ) if( !CA

syncSocket::ConnectHelper(...) ) { //Connect(...)는 자체적으로 서버와 3단계 핸드셰이크를 수행해야 하기 때문에 //즉, 패킷을 보내고 응답을 기다려야 합니다(이것은 //연결과 데이터 전송이 관련되어 작동하는 소켓 API가 차단되는 이유) //그래서 CAsyncSocket::ConnectHelper(...)는 즉시 반환되고 //오류를 WSAEWOULDBLOCK으로 설정합니다(이 함수를 호출하면 차단이 발생합니다). if( WSAGetLastError() == WSAEWOULDBLOCK ) { //스레드 메시지 큐에서 FD_CONNECT 메시지를 보려면 메시지 루프에 들어가십시오. //FD_CONNECT 메시지를 수신하십시오(m_nConnectError는 PumpMessage에서 수정됩니다). // 또는 WM_TIMER/FD_CLOSE( true를 반환하지만 m_nConnectError는 수정되지 않습니다.), / /계속해서 PumpMessage를 호출하여 메시지 또는 오류를 가져온 다음 소켓_error를 반환합니다. while( PumpMessages( FD_CONNECT ) ) { if (m_nConnectError != -1) { WSASetLastError(m_nConnectError) ; return (m_nConnectError == 0); } } // end while } return false; } return true } //m_nTimeOut=2000ms 시간으로 PumpMessages에 타이머가 설정됩니다. //이 시간 내에 메시지가 수신되지 않으면 BOOL CSocket::PumpMessages( UINT uStopFlag ) { //이 함수를 입력하면 소켓의 현재 상태를 차단으로 설정합니다. BOOL bBlocking = TRUE; amp; ........ ................................. ......... CWinThread* pThread = AfxGetThread(); // bBlocking은 // 사용자가 Connect() 호출을 취소할지 여부, 즉 CancelBlockingCall()을 호출할지 여부를 결정하는 데 사용됩니다. while( bBlocking ) { //#define WM_SOCKET_NOTIFY 0x0373 //#define WM_SOCKET_DEAD 0x0374 MSG msg; //in 여기서는 WM_SOCKET_NOTIFY 및 WM_SOCKET_DEAD 메시지를 사용합니다. if (::PeekMessage(amp;msg, pState-gt;m_hSocketWindow, WM_SOCKET_NOTIFY , WM_소켓

_DEAD, PM_REMOVE)) { if (msg.message == WM_SOCKET_NOTIFY amp; amp; (SOCKET)msg.wParam == m_hSocket) { //PumpMessage의 두 번째 사례입니다. if (WSAGETSELECTEVENT(msg.lParam) == FD_CLOSE ) { break;} //PumpMessage의 첫 번째 경우입니다. if(WSAGETSELECTEVENT(msg.lParam) == uStopFlag) {......break;} } //PumpMessage의 다섯 번째 경우입니다. if (msg. wParam != 0 || msg.lParam != 0) CSocket::AuxQueueAdd(msg.message, msg.wParam, msg.lParam) } //이것은 PumpMessage의 세 번째 경우입니다. else if (:: PeekMessage(amp; msg, pState-gt;m_hSocketWindow, WM_TIMER, WM_TIMER, PM_REMOVE)) { break;} //PeekMessage의 여섯 번째 경우입니다. if (bPeek amp;amp; ::PeekMessage(amp;msg, NULL, 0, 0, PM_NOREMOVE )) { if (OnMessagePending()) { } else { WaitMessage(); ..... } } }//end while ////PumpMessage의 네 번째 사례입니다. if (!bBlocking ) { WSASetLastError(WSAEINTR) ; return FALSE; } m_pbBlocking = NULL; //다른 소켓 메시지를 처리하기 위해 //Create CSocketWnd 스레드의 메시지 큐로 보냅니다: PostMessage(pState-gt; m_hSocketWindow, WM_SOCKET_NOTIFY, 0 , 0); TRUE; } B 수신(..)을 살펴보세요. //실제로 CSocket 구현에서는 응용 프로그램이 스레드에서 소켓을 생성할 수 없다고 판단한 다음 //특별히 수신할 새 스레드를 생성합니다. FD_Read 이벤트를 얻을 수 있습니다. //이 스레드에서는 CSocketWnd 개체가 생성되지 않았기 때문에 CSocketWnd로 보낸 메시지를 받을 수 없습니다. //(Windows에서는 메시지 본문이 window입니다.) //Re

ceive와 Connect의 구현 방법의 가장 큰 차이점은 //Connect는 지속적으로 PumpMessage(..)를 호출하고 //그리고 Receiver는 지속적으로 자신을 호출한다는 것입니다 int CSocket::Receive(void* lpBuf, int nBufLen, int nFlags) { if ( m_pbBlocking != NULL) { WSASetLastError(WSAEINPROGRESS); return FALSE; } int nResult; while ((nResult = CAsyncSocket::Receive(lpBuf, nBufLen, nFlags)) == SOCKET_ERROR) { if (GetLastError() == WSAEWOULDBLOCK) /FD_READ가 추출되면///FD_CLOSE///WM_TIMER//, CAsyncSocket을 다시 호출합니다::Receive(...) if (!PumpMessages(FD_READ)) return SOCKET_ERROR } else return SOCKET_ERROR } return nResult; CSocket에 대한 내 견해를 요약하겠습니다. 1. CancelBlockingCall을 호출하여 차단된 스레드를 종료하는 방법을 해결하지만 멀티 스레딩 모드는 CSocket에 전혀 적합하지 않습니다. 2. CSocket과 CAsyncSocket은 Windows 메시지 모드를 사용하여 전경을 결합합니다. 인터페이스 처리 및 백그라운드 처리 모든 네트워크 통신은 메시지 전달 모델에 통합되지만 백그라운드 네트워크가 너무 바빠지면 프런트 엔드 처리가 고려되지 않을 수 있으므로 CSocket은 작은 작업만 수행할 수 있습니다. /p>

위에 명시되어 있는 MSDN과 Sun Xin의 VC 비디오를 자세히 살펴보시기 바랍니다! !

上篇: 10 에서 산 컴퓨터 호스트는 이제 중고를 팔 수 있습니다. 얼마를 쓸 수 있습니까? 리스트를 작성해 주세요. 。 下篇: HGVS 규칙에 따른 변종 명명 (2) DNA 수준에서 다양한 돌연변이 유형의 "고치 풀기" |
관련 내용