BOOL MsgMng::Recv(MsgBuf *msg) { RecvBuf buf; if (!UdpRecv(&buf) || buf.size == 0) return FALSE; return ResolveMsg(&buf, msg); }
int main (int argc, char *argv[]) { int Rc; LPUDPSOCK lpSock=NULL; char szVer [128]; int nTries=0; unsigned short nPort; if (argc<2) Usage(); if (argc==3 && strcmp (argv[1], "-v")==0) Tcp4uEnableLog (LOG4U_DUMP); Tcp4uVer (szVer, sizeof szVer); printf ("Using %s\n", szVer); Tcp4uInit(); nPort = Udp4uServiceToPort ("echo"); printf ("echo port is %u\n", nPort); Rc = UdpInit (& lpSock, argv[argc-1], nPort, 0); if (Rc>=TCP4U_SUCCESS) Rc = UdpBind (lpSock, TRUE, UDP4U_CLIENT); if (Rc<TCP4U_SUCCESS) { printf ("Error %d/%d: <%s>\n", Rc, errno, Tcp4uErrorString (Rc)); return 0; } /* send 3 datagrams */ nTries++; do { Rc = UdpSend (lpSock, STRING, sizeof STRING, 0, HLOG); if (Rc>=TCP4U_SUCCESS) Rc= UdpRecv (lpSock, buf, sizeof buf, 5, HLOG); nTries++; } while (nTries <= 3 && Rc==TCP4U_TIMEOUT); if (Rc>=TCP4U_SUCCESS) printf ("Server sends %d bytes. String <%s>\n", Rc, buf); else printf ("Error %d/%d: <%s>\n", Rc, errno, Tcp4uErrorString (Rc)); if (lpSock!=NULL) UdpCleanup (lpSock); Tcp4uCleanup(); return 0; }
/** * @ingroup SnmpStack * @brief SNMP 요청 메시지를 전송한 후, 이에 대한 응답 메시지를 수신한다. * @param pclsRequest SNMP 요청 메시지 * @param pclsResponse SNMP 응답 메시지 * @returns 성공하면 true 를 리턴하고 실패하면 false 를 리턴한다. */ bool CSnmpSession::SendRecv( CSnmpMessage * pclsRequest, CSnmpMessage * pclsResponse ) { int iSendLen, iRecvLen = 0, n; bool bRes = false; if( m_hSocket == INVALID_SOCKET ) { if( Open() == false ) return false; } if( m_bTcp ) { char szSend[SNMP_MAX_PACKET_SIZE], szRecv[SNMP_MAX_PACKET_SIZE]; int iWantRecvLen = 0; iSendLen = pclsRequest->MakePacket( szSend, sizeof(szSend) ); if( iSendLen == -1 ) { CLog::Print( LOG_ERROR, "%s MakePacket error", __FUNCTION__ ); return false; } if( TcpSend( m_hSocket, szSend, iSendLen ) == false ) { CLog::Print( LOG_ERROR, "%s TcpSend error", __FUNCTION__ ); return false; } while( 1 ) { n = TcpRecv( m_hSocket, szRecv + iRecvLen, sizeof(szRecv) - iRecvLen, m_iMiliTimeout / 1000 ); if( n <= 0 ) { CLog::Print( LOG_ERROR, "%s recv error(%d)", __FUNCTION__, GetError() ); return false; } iRecvLen += n; if( iWantRecvLen <= 0 ) { iWantRecvLen = pclsResponse->GetPacketLen( szRecv, iRecvLen ); } if( iWantRecvLen > 0 ) { if( iRecvLen == iWantRecvLen ) break; } } if( pclsResponse->ParsePacket( szRecv, iRecvLen ) > 0 ) { if( m_bDebug ) { LogPacket( szRecv, iRecvLen ); } if( pclsRequest->m_iRequestId == pclsResponse->m_iRequestId || ( pclsRequest->m_iMsgId > 0 && pclsRequest->m_iMsgId == pclsResponse->m_iMsgId ) ) { bRes = true; } } } else { char szSend[SNMP_MAX_PACKET_SIZE], szRecv[SNMP_MAX_PACKET_SIZE]; struct pollfd arrPoll[1]; uint32_t iIp; uint16_t sPort; iSendLen = pclsRequest->MakePacket( szSend, sizeof(szSend) ); if( iSendLen == -1 ) { CLog::Print( LOG_ERROR, "%s MakePacket error", __FUNCTION__ ); return false; } for( int iSend = 0; iSend <= m_iReSendCount; ++iSend ) { if( UdpSend( m_hSocket, szSend, iSendLen, m_iIp, m_sPort ) == false ) { CLog::Print( LOG_ERROR, "%s UdpSend error", __FUNCTION__ ); return false; } TcpSetPollIn( arrPoll[0], m_hSocket ); POLL_START: n = poll( arrPoll, 1, m_iMiliTimeout ); if( n > 0 ) { iRecvLen = sizeof(szRecv); if( UdpRecv( m_hSocket, szRecv, &iRecvLen, &iIp, &sPort ) ) { if( pclsResponse->ParsePacket( szRecv, iRecvLen ) > 0 ) { if( m_bDebug ) { LogPacket( szRecv, iRecvLen ); } if( pclsRequest->m_iRequestId == pclsResponse->m_iRequestId || ( pclsRequest->m_iMsgId > 0 && pclsRequest->m_iMsgId == pclsResponse->m_iMsgId ) ) { bRes = true; break; } } // 원하는 응답이 수신되지 않으면 다시 수신 대기로 진입한다. goto POLL_START; } } } } return bRes; }
///////////////////////////// // Fenetre Background gestion des appels TCP // LRESULT CALLBACK TftpClientProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { DWORD nbWrt; struct tftphdr *tpr, *tps; time_t dNow; int Ark; HWND hCBWnd, hParentWnd; time (&dNow); switch (message) { ///////////////////////// // Message Windows case WM_INITCLIENT : // only one client transfer available hTftpClientSemaphore = CreateSemaphore(NULL, 1, 1, TFTP_CLIENT_SEMAPHORE); hTftpClientWnd = hWnd; hParentWnd = GetParent (hWnd); EnableWindow (GetDlgItem (hParentWnd, IDC_CLIENT_BREAK_BUTTON), FALSE); SetDlgItemText (hParentWnd, IDC_CLIENT_BLOCK, ""); // populate combo with proposed block sizes hCBWnd = GetDlgItem (hParentWnd, IDC_CB_DATASEG); for (Ark=0 ; Ark<SizeOfTab (tBlkSize); Ark++) ComboBox_AddString (hCBWnd, tBlkSize[Ark].szBlkSize); ComboBox_SetCurSel (hCBWnd, 0); // uncheck "Send full path to server" SendDlgItemMessage (hParentWnd, IDC_CLIENT_FULL_PATH, BM_SETCHECK, BST_UNCHECKED, 0); // edittext IDC_CLIENT_FILE will accept dropped file (works only because it is on the top in Z-Order DragAcceptFiles (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), TRUE); // fEditBoxProc = (WNDPROC) SetWindowLong (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), GWL_WNDPROC, (LONG) TftpClientFileNameProc); fEditBoxProc = (WNDPROC) SetWindowLongPtr (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), GWLP_WNDPROC, (LONG_PTR) TftpClientFileNameProc); // SetWindowLong (GetDlgItem (hParentWnd, IDC_CLIENT_FILE), GWL_USERDATA, (LONG) TftpClientFileNameProc); SetWindowLongPtr (GetDlgItem (hParentWnd, IDC_CLIENT_LOCALFILE), GWLP_USERDATA, (LONG_PTR) TftpClientFileNameProc); break; case WM_CLOSE : LogToMonitor ("GUI: Closing Tftp Client"); CloseHandle (hTftpClientSemaphore); CloseHandle (sTC.hFile); closesocket (sTC.s); break; case WM_COMMAND : Handle_VM_Command (hWnd, wParam, lParam); break; case WM_TIMER : KillTimer(hWnd, wParam); PostMessage (hWnd, wParam, 0, (LPARAM) -1); // pour pas confondre break; ////////////////////// // Download : fichier envoyé par le serveur case WM_CLIENT_DATA : // WSAAsyncSelect (sTC.s, hWnd, 0, 0); A SUPPRIMER KillTimer(hWnd, wParam); if (sTC.bBreak) return FALSE; sTC.nRcvd = 0; // On est reveillé par un message reçu tpr = (struct tftphdr *) sTC.BufRcv; if (WSAGETSELECTEVENT(lParam) == FD_READ) { if (! UdpRecv ()) return BadEndOfTransfer ("Error in Recv.\nError code is %d (%s)", WSAGetLastError (), LastErrorText() ); // parcours des codes retours switch (htons (tpr->th_opcode)) { case TFTP_ERROR : return BadEndOfTransfer ("Server stops the transfer.\nError #%d: %s", htons (tpr->th_code), tpr->th_msg); case TFTP_OACK : if (sTC.nCount==0) TftpProcessOACK (); break; case TFTP_DATA : // a data packet has been received. Check #block if ( htons (tpr->th_block) == (unsigned short) (sTC.nCount+1) ) { if ( !WriteFile (sTC.hFile, tpr->th_data, sTC.nRcvd - TFTP_DATA_HEADERSIZE, & nbWrt, NULL) || sTC.nRcvd-TFTP_DATA_HEADERSIZE!=nbWrt) return BadEndOfTransfer ("Error in writing file.\nError code is %d (%s)", GetLastError(), LastErrorText()); sTC.nCount++; sTC.nRetransmit = 0; // prepare Ack block tps = (struct tftphdr *) sTC.BufSnd; tps->th_opcode = htons (TFTP_ACK), tps->th_block = htons ((unsigned short) sTC.nCount); sTC.nToSend = TFTP_DATA_HEADERSIZE; // compute MD5 MD5Update (& sTC.m.ctx, tpr->th_data, nbWrt); } break; default : return BadEndOfTransfer ("Server sent illegal opcode %d", htons (tpr->th_opcode)); } // switch opcode } // il y a un message à recevoir // La comparaison marche si le paquet est le bon ou une répétition du précédent message if ( htons (tpr->th_block) == (unsigned short) sTC.nCount) { if (sTC.nRetransmit) sTC.nTotRetrans ++; if (sTC.nRetransmit++ > TFTP_RETRANSMIT) return BadEndOfTransfer ("Timeout waiting block #%d", sTC.nCount+1); send (sTC.s, sTC.BufSnd, sTC.nToSend, 0); SetTimer (hWnd, WM_CLIENT_DATA, sTC.dwTimeout, NULL); } // sTC.nRcvd ne peut être inférieur que si on a reçu un block if ( htons (tpr->th_opcode)==TFTP_DATA && sTC.nRcvd!=0 && sTC.nRcvd < sTC.nPktSize + TFTP_DATA_HEADERSIZE) return TransferOK (dNow); Statistics (dNow); break; //////////////////////// // Upload : server sends ACK case WM_CLIENT_ACK : KillTimer(hWnd, wParam); if (sTC.bBreak || sTC.s==INVALID_SOCKET) return FALSE; // socket not closed by StopTransfer tpr = (struct tftphdr *) sTC.BufRcv; if ( WSAGETSELECTEVENT(lParam) == FD_READ ) { if (! UdpRecv ()) return BadEndOfTransfer ("Error in Recv.\nError code is %d (%s)", WSAGetLastError (), LastErrorText() ); switch (htons (tpr->th_opcode)) { case TFTP_ERROR : return BadEndOfTransfer ("Server stops the transfer.\nError #%d: %s", htons (tpr->th_code), tpr->th_msg); case TFTP_OACK : if (sTC.nCount!=0) break; // ignore message TftpProcessOACK (); tpr->th_block = htons(0); // pour passer en dessous // Fall through case TFTP_ACK : if ( htons (tpr->th_block) == (unsigned short) sTC.nCount ) { // prepare Data block tps = (struct tftphdr *) sTC.BufSnd; if ( !ReadFile (sTC.hFile, tps->th_data, sTC.nPktSize, & sTC.nRcvd, NULL) ) { if (sTC.nToSend == TFTP_DATA_HEADERSIZE + sTC.nPktSize) // file was exactly N * PkSize return TransferOK (dNow); else return BadEndOfTransfer ("Error in reading file.\nError code is %d (%s)", GetLastError(), LastErrorText()); } if (sTC.nRcvd == 0) // EOF { if (sTC.nToSend < TFTP_DATA_HEADERSIZE + sTC.nPktSize) return TransferOK (dNow); } sTC.nCount++; sTC.nRetransmit = 0; tps->th_opcode = htons (TFTP_DATA), tps->th_block = htons ((unsigned short) sTC.nCount); sTC.nToSend = TFTP_DATA_HEADERSIZE + sTC.nRcvd; // compute MD5 MD5Update (& sTC.m.ctx, tps->th_data, sTC.nRcvd); } break; default : return BadEndOfTransfer ("Server sent illegal opcode %d", htons (tpr->th_opcode)); } // switch opcode } // il y a un message à recevoir // Timeout or ack of previous block else if ( htons (tpr->th_block) == (unsigned short) (sTC.nCount-1) ) { if (sTC.nRetransmit) sTC.nTotRetrans ++; if (sTC.nRetransmit++ > TFTP_RETRANSMIT) return BadEndOfTransfer ("Timeout while waiting ack block #%d", sTC.nCount); // une possibilité : on est au dernier message et le serveur TFTP n'a pas acquitté // --> on renvoie, mais sur Timeout, on signale un transfert OK if (sTC.nToSend < TFTP_DATA_HEADERSIZE + sTC.nPktSize && sTC.nRetransmit<TFTP_RETRANSMIT) return TransferOK (dNow); } send (sTC.s, sTC.BufSnd, sTC.nToSend, 0); SetTimer (hWnd, WM_CLIENT_ACK, sTC.dwTimeout, NULL); Statistics (dNow); break; } // switch message return DefWindowProc (hWnd, message, wParam, lParam); } // TftpProc