在SingleStep中看到檢測到select中write准備就緒。即跳到connectionHandler [cpp] void RTSPClient::connectionHandler(void* instance, int /*mask*/) { RTSPClient* client = (RTSPClient*)instance; client->connectionHandler1(); } [cpp] void RTSPClient::connectionHandler1() { // Restore normal handling on our sockets: envir().taskScheduler().disableBackgroundHandling(fOutputSocketNum); envir().taskScheduler().setBackgroundHandling(fInputSocketNum, SOCKET_READABLE, (TaskScheduler::BackgroundHandlerProc*)&incomingDataHandler, this); // Move all requests awaiting connection into a new, temporary queue, to clear "fRequestsAwaitingConnection" // (so that "sendRequest()" doesn't get confused by "fRequestsAwaitingConnection" being nonempty, and enqueue them all over again). RequestQueue tmpRequestQueue(fRequestsAwaitingConnection); RequestRecord* request; // Find out whether the connection succeeded or failed: do { int err = 0; SOCKLEN_T len = sizeof err; if (getsockopt(fInputSocketNum, SOL_SOCKET, SO_ERROR, (char*)&err, &len) < 0 || err != 0) { envir().setResultErrMsg("Connection to server failed: ", err); if (fVerbosityLevel >= 1) envir() << "..." << envir().getResultMsg() << "\n"; break; } // The connection succeeded. If the connection came about from an attempt to set up RTSP-over-HTTP, finish this now: if (fVerbosityLevel >= 1) envir() << "...remote connection opened\n"; if (fHTTPTunnelingConnectionIsPending && !setupHTTPTunneling2()) break; // Resume sending all pending requests: while ((request = tmpRequestQueue.dequeue()) != NULL) { sendRequest(request); } return; } while (0); // An error occurred. Tell all pending requests about the error: resetTCPSockets(); // do this now, in case an error handler deletes "this" while ((request = tmpRequestQueue.dequeue()) != NULL) { handleRequestError(request); delete request; } } 上面的代碼中先清除掉connect Handing然後添加上read set ,檢測到connect執行成功,將上次fRequestsAwaitingConnection出列,如果有未執行的request會重新執行sendRequest執行。在上次執行sendRequest的時候那個request是option的發送請求。這裡就先再次進入sendRequest先通過commandName判斷要發送什麼命令。option中可以看到什麼都沒執行然後就是發送命令的拼接。然後就執行send將cmd發送出去。至此發送option的全部動作已經完成,下面我們再來看option命令respone的接收。 在connectionHandler1()中我們看到把fInputSocketNum加入到了SOCKET_READABLE集中,回調函數是incomingDataHandler。同樣SingleStep 中select有read的時候會調用這個回調函數。現在來看看 [cpp] void RTSPClient::incomingDataHandler(void* instance, int /*mask*/) { RTSPClient* client = (RTSPClient*)instance; client->incomingDataHandler1(); } [cpp] void RTSPClient::incomingDataHandler1() { struct sockaddr_in dummy; // 'from' address - not used int bytesRead = readSocket(envir(), fInputSocketNum, (unsigned char*)&fResponseBuffer[fResponseBytesAlreadySeen], fResponseBufferBytesLeft, dummy); handleResponseBytes(bytesRead); } readsocket沒什麼可看的,就是執行recvfrom接收字節到fResponseBuffer中。然後執行的就是handleResponseBytes,可以看到handleResponseBytes中的內容很多,主要是對response的分析。主要看到最後有這句代碼: [cpp] if (foundRequest != NULL && foundRequest->handler() != NULL) { int resultCode; char* resultString; if (responseSuccess) { if (responseCode == 200) { resultCode = 0; resultString = numBodyBytes > 0 ? strDup(bodyStart) : strDup(publicParamsStr); // Note: The "strDup(bodyStart)" call assumes that the body is encoded without interior '\0' bytes } else { resultCode = responseCode; resultString = strDup(responseStr); envir().setResultMsg(responseStr); } (*foundRequest->handler())(this, resultCode, resultString); } else { // An error occurred parsing the response, so call the handler, indicating an error: handleRequestError(foundRequest); } } 這裡面的(*foundRequest->handler())(this, resultCode, resultString);就是執行 getOptions(continueAfterOPTIONS);中的continueAfterOPTIONS。 通過對option命令的發送和接收可以看到其他的命令的發送和接收是差不多的流程,詳細過程就不一一列出。