VC FTP 서버 프로그램 분석(4)

34948 단어
다음은 데이터 전송의 중점 - CDataSocket 클래스입니다. 함수가 많지 않고 모두 비교적 중요합니다.
1. OnAccept 데이터 tcp 서버가 연결된 허함수로 프레임워크에서 호출됩니다.
 1 void CDataSocket::OnAccept(int nErrorCode) 
 2 {
 3     // Accept the connection using a temp CSocket object.
 4     CAsyncSocket tmpSocket;
 5     Accept(tmpSocket);
 6     
 7     SOCKET socket = tmpSocket.Detach();
 8     Close();
 9 
10     Attach(socket);
11 
12     m_bConnected = TRUE;
13     
14     CAsyncSocket::OnAccept(nErrorCode);
15 }

일곱 번째 줄은 플러그인 설명자 socket을 얻을 수 있습니다.8줄은 감청된 이 플러그인을 닫고, 11줄은 socket과 본 대상, 12줄, 연결 표지를 표시합니다.이런 처리 방법은 한 종류를 적게 쓴다.tcp가 socket을 감청하기 때문에, 연결된 클라이언트도 socket을 사용하여 통신해야 합니다.이렇게 하면 클라이언트가 하나밖에 없는 상황에 적합하다.
2. OnReceive 데이터 수신 처리 함수
 1 int CDataSocket::Receive()
 2 {
 3     TRACE("OnReceive
"); 4 int nRead = 0; 5 6 if (m_pControlSocket->m_nStatus == STATUS_UPLOAD) 7 { 8 if (m_File.m_hFile == NULL) 9 return 0; 10 11 byte data[PACKET_SIZE]; 12 nRead = CAsyncSocket::Receive(data, PACKET_SIZE); 13 14 switch(nRead) 15 { 16 case 0: 17 { 18 m_File.Close(); 19 m_File.m_hFile = NULL; 20 Close(); 21 // tell the client the transfer is complete. 22 m_pControlSocket->SendResponse("226 Transfer complete"); 23 // destroy this socket 24 AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, 0, 0); 25 break; 26 } 27 case SOCKET_ERROR: 28 { 29 if (GetLastError() != WSAEWOULDBLOCK) 30 { 31 m_File.Close(); 32 m_File.m_hFile = NULL; 33 Close(); 34 m_pControlSocket->SendResponse("426 Connection closed; transfer aborted."); 35 // destroy this socket 36 AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, 0, 0); 37 } 38 break; 39 } 40 default: 41 { 42 TRY 43 { 44 m_File.Write(data, nRead); 45 } 46 CATCH_ALL(e) 47 { 48 m_File.Close(); 49 m_File.m_hFile = NULL; 50 Close(); 51 m_pControlSocket->SendResponse("450 Can't access file."); 52 // destroy this socket 53 AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, 0, 0); 54 return 0; 55 } 56 END_CATCH_ALL; 57 break; 58 } 59 } 60 } 61 return nRead; 62 }

업로드 상태이면 수신한 데이터를 파일에 기록합니다.
3. PreSendFile 파일 전송과 관련된 함수
 1 BOOL CDataSocket::PrepareSendFile(LPCTSTR lpszFilename)
 2 {
 3     // close file if it's already open
 4     if (m_File.m_hFile != NULL)
 5     {
 6         m_File.Close();
 7     }
 8                                       
 9     // open source file
10     if (!m_File.Open(lpszFilename, CFile::modeRead | CFile::typeBinary))
11     {
12         return FALSE;
13     }
14     m_nTotalBytesSend = m_File.GetLength();
15 
16     if (m_pControlSocket->m_dwRestartOffset < m_nTotalBytesSend)
17     {
18         m_nTotalBytesTransfered = m_pControlSocket->m_dwRestartOffset;
19     }
20     else
21     {
22         m_nTotalBytesTransfered = 0;
23     }
24     return TRUE;
25 }

초기화 파일 설명자 m_File,m_nTotalBytesSend,m_nTotalBytesTransfered.
4. SendFile 함수는 PrepareSendFile을 호출하고 OnSend를 호출하여 파일을 보냅니다.
 1 void CDataSocket::SendFile(LPCTSTR lpszFilename)
 2 {
 3     if (!PrepareSendFile(lpszFilename))
 4     {
 5         // change status
 6         m_pControlSocket->m_nStatus = STATUS_IDLE;
 7 
 8         m_pControlSocket->SendResponse("426 Connection closed; transfer aborted.");
 9 
10         // destroy this socket
11         AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, 0, 0);
12         return;
13     }
14     OnSend(0);
15 }

5. 전송 데이터는 LIST 명령을 위해 준비된 것으로 파일 디렉터리 목록을 보냅니다.
6. OnSend는 주로 list 명령의 상황과 다운로드의 상황을 구분한다.
  1 void CDataSocket::OnSend(int nErrorCode) 
  2 {
  3     CAsyncSocket::OnSend(nErrorCode);
  4     switch(m_pControlSocket->m_nStatus)
  5     {
  6         case STATUS_LIST:
  7         {
  8             while (m_nTotalBytesTransfered < m_nTotalBytesSend)
  9             {
 10                 DWORD dwRead;
 11                 int dwBytes;
 12 
 13                 CString strDataBlock;
 14                 
 15                 dwRead = m_strData.GetLength();
 16                 
 17                 if (dwRead <= PACKET_SIZE)
 18                 {
 19                     strDataBlock = m_strData;
 20                 }
 21                 else
 22                 {
 23                     strDataBlock = m_strData.Left(PACKET_SIZE);
 24                     dwRead = strDataBlock.GetLength();
 25                 }
 26                 
 27                 if ((dwBytes = Send(strDataBlock, dwRead)) == SOCKET_ERROR)
 28                 {
 29                     if (GetLastError() == WSAEWOULDBLOCK) 
 30                     {
 31                         Sleep(0);
 32                         return;
 33                     }
 34                     else
 35                     {
 36                         TCHAR szError[256];
 37                         wsprintf(szError, "Server Socket failed to send: %d", GetLastError());
 38 
 39                         // close the data connection.
 40                         Close();
 41 
 42                         m_nTotalBytesSend = 0;
 43                         m_nTotalBytesTransfered = 0;
 44 
 45                         // change status
 46                         m_pControlSocket->m_nStatus = STATUS_IDLE;
 47 
 48                         m_pControlSocket->SendResponse("426 Connection closed; transfer aborted.");
 49 
 50                         // destroy this socket
 51                         AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, 0, 0);
 52                     }
 53                 }
 54                 else
 55                 {
 56                     m_nTotalBytesTransfered += dwBytes;
 57                     m_strData = m_strData.Mid(dwBytes);
 58                 }
 59             }
 60             if (m_nTotalBytesTransfered == m_nTotalBytesSend)
 61             {
 62                 // close the data connection.
 63                 Close();
 64 
 65                 m_nTotalBytesSend = 0;
 66                 m_nTotalBytesTransfered = 0;
 67 
 68                 // change status
 69                 m_pControlSocket->m_nStatus = STATUS_IDLE;
 70 
 71                 // tell the client the transfer is complete.
 72                 m_pControlSocket->SendResponse("226 Transfer complete");
 73                 // destroy this socket
 74                 AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, 0, 0);
 75             }
 76             break;
 77         }
 78         case STATUS_DOWNLOAD:
 79         {
 80             while (m_nTotalBytesTransfered < m_nTotalBytesSend)
 81             {
 82                 // allocate space to store data
 83                 byte data[PACKET_SIZE];
 84                 
 85                 m_File.Seek(m_nTotalBytesTransfered, CFile::begin);
 86 
 87                 DWORD dwRead = m_File.Read(data, PACKET_SIZE);
 88     
 89                 int dwBytes;
 90 
 91                 if ((dwBytes = Send(data, dwRead)) == SOCKET_ERROR)
 92                 {
 93                     if (GetLastError() == WSAEWOULDBLOCK) 
 94                     {
 95                         Sleep(0);
 96                         break;
 97                     }
 98                     else
 99                     {
100                         TCHAR szError[256];
101                         wsprintf(szError, "Server Socket failed to send: %d", GetLastError());
102 
103                         // close file.
104                         m_File.Close();
105                         m_File.m_hFile = NULL;
106 
107                         // close the data connection.
108                         Close();
109 
110                         m_nTotalBytesSend = 0;
111                         m_nTotalBytesTransfered = 0;
112 
113                         // change status
114                         m_pControlSocket->m_nStatus = STATUS_IDLE;
115 
116                         m_pControlSocket->SendResponse("426 Connection closed; transfer aborted.");
117 
118                         // destroy this socket
119                         AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, 0, 0);
120                     }
121                 }
122                 else
123                 {
124                     m_nTotalBytesTransfered += dwBytes;
125                 }
126             }
127             if (m_nTotalBytesTransfered == m_nTotalBytesSend)
128             {
129                 // close file.
130                 m_File.Close();
131                 m_File.m_hFile = NULL;
132 
133                 // close the data connection.
134                 Close();
135 
136                 m_nTotalBytesSend = 0;
137                 m_nTotalBytesTransfered = 0;
138 
139                 // change status
140                 m_pControlSocket->m_nStatus = STATUS_IDLE;
141 
142                 // tell the client the transfer is complete.
143                 m_pControlSocket->SendResponse("226 Transfer complete");
144                 // destroy this socket
145                 AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, 0, 0);
146             }
147             break;
148         }
149     }
150 }

7. OnConnect 함수 tcp 연결이 성공했을 때 프레임워크에 호출된 허함수입니다.
8. OnClose 함수는 데이터 전송이 완료되거나 수신이 완료되면 프레임워크에 호출된 허함수입니다.주로 청소를 하다.
  9、
 
 

좋은 웹페이지 즐겨찾기