基于TCP的文件傳輸程序_第1頁(yè)
基于TCP的文件傳輸程序_第2頁(yè)
基于TCP的文件傳輸程序_第3頁(yè)
基于TCP的文件傳輸程序_第4頁(yè)
基于TCP的文件傳輸程序_第5頁(yè)
已閱讀5頁(yè),還剩27頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、計(jì)算機(jī)網(wǎng)絡(luò)系統(tǒng)實(shí)踐報(bào)告設(shè)計(jì)題目:網(wǎng)絡(luò)文件傳輸學(xué)生姓名:鄭波學(xué) 號(hào):2013211644專業(yè)班級(jí):計(jì)算機(jī)科學(xué)與技術(shù)13-2班2015年12月一、 設(shè)計(jì)要求1、 實(shí)現(xiàn)單線程文件傳輸功能2、 在以上的基礎(chǔ)上,掌握多線程技術(shù),在文件網(wǎng)絡(luò)傳輸時(shí),可選擇單線程或多線程3、 加入異??刂茩C(jī)制,增強(qiáng)程序的魯棒性(Robust)4、 了解如何提高套接字傳輸?shù)乃俾?,以及如何加?qiáng)傳輸?shù)姆€(wěn)定性二、開發(fā)環(huán)境與工具Windows7下Microsoft Visual Stuio三、設(shè)計(jì)原理1、網(wǎng)絡(luò)傳輸協(xié)議TCP/IP協(xié)議棧中的兩個(gè)協(xié)議:TCP(Transmission Control Protocol):傳輸控制協(xié)議UDP

2、(User Datagrm Protocal):用戶數(shù)據(jù)報(bào)協(xié)議TCP是面向連接的通信協(xié)議,TCP提供兩臺(tái)計(jì)算機(jī)之間的可靠無(wú)錯(cuò)的數(shù)據(jù)傳輸。應(yīng)用程序利用TCP進(jìn)行通信時(shí),源和目標(biāo)之間會(huì)建立一個(gè)虛擬連接。該連接一旦建立,兩臺(tái)計(jì)算機(jī)之間就可以把數(shù)據(jù)當(dāng)做一個(gè)雙向字節(jié)流進(jìn)行交換。UDP是無(wú)連接的通信協(xié)議,UDP不保證可靠數(shù)據(jù)的傳輸,但能夠向若干個(gè)目標(biāo)發(fā)送數(shù)據(jù),接受發(fā)自若干個(gè)源的數(shù)據(jù)。就是說(shuō),如果一個(gè)主機(jī)向另外一臺(tái)主機(jī)發(fā)送數(shù)據(jù),這個(gè)數(shù)據(jù)就會(huì)立即發(fā)出,而不管另外一臺(tái)主機(jī)是否已準(zhǔn)備接收數(shù)據(jù)。如果另外一臺(tái)主機(jī)接收到了數(shù)據(jù),它不會(huì)確認(rèn)收到與否。本次工程目的是傳輸文件,顯然需要用TCP建立連接,而TCP連接需要“三次

3、握手”。2、三次握手 三次握手具體過(guò)程:1、客戶端主動(dòng)與服務(wù)器聯(lián)系,TCP首部控制位中的SYN設(shè)置為1,發(fā)送帶有SYN的TCP段,并把初始序號(hào)告訴對(duì)方2、服務(wù)端收到帶有SYN的報(bào)文,記錄客戶端的初始序號(hào),選擇自己的初始序號(hào),設(shè)置控制位中的SYN和ACK。因?yàn)镾YN占用一個(gè)序號(hào),所以確認(rèn)序號(hào)設(shè)置為客戶端的初始序號(hào)加1,對(duì)客戶端的SYN進(jìn)行確認(rèn)3、服務(wù)端的報(bào)文到達(dá)客戶端,客戶端設(shè)置ACK控制位,并把確認(rèn)好設(shè)為服務(wù)器的初始序號(hào)加1,以確認(rèn)服務(wù)器的SYN報(bào)文段,這個(gè)報(bào)文只是確認(rèn)消息,告訴服務(wù)器已經(jīng)成功建立了連接四、系統(tǒng)功能描述及軟件模塊劃分1、系統(tǒng)功能描述 軟件實(shí)現(xiàn)了點(diǎn)對(duì)點(diǎn)的文件傳輸。傳輸前的接收提醒

4、以及傳輸過(guò)程中的控制。 2、軟件模塊劃分 本程序可以劃分成以上三個(gè)模塊:傳輸控制模塊,文件傳輸模塊和服務(wù)連接模塊。其中:服務(wù)連接模塊用來(lái)建立客戶端到服務(wù)器的連接 文件傳輸模塊主要用兩個(gè)線程:_SendThread和_ListenThread來(lái)完成,實(shí)現(xiàn)發(fā)送和接收文件的功能。傳輸控制模塊主要通過(guò)封裝好的可串行化信息類CMessage互相傳遞兩端的文件操作消息,響應(yīng)“暫停傳輸”,“關(guān)閉連接”等功能五、設(shè)計(jì)步驟 1、服務(wù)連接模塊 先要建立起客戶端與服務(wù)器之間的連接,大致過(guò)程如下: 服務(wù)器啟動(dòng): if(m_nServerType = SERVER)/創(chuàng)建服務(wù)器套接字m_psockServer = ne

5、w CListenSocket(this);if(!m_psockServer->Create(m_wPort) /綁定端口delete m_psockServer;m_psockServer = NULL;MessageBox(GetError(GetLastError(), _T("錯(cuò)誤"), MB_ICONHAND);return ;/開啟線程,監(jiān)聽客戶端連接if(!m_psockServer->Listen() delete m_psockServer;m_psockServer = NULL;MessageBox(GetError(GetLastErr

6、or(), _T("錯(cuò)誤"), MB_ICONHAND);return ; 客戶端填入相應(yīng)的IP地址,連接服務(wù)器if(CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS)->IsBlank()MessageBox("IP 地址不能為空", "錯(cuò)誤", MB_ICONHAND);return ;/創(chuàng)建客戶端套接字m_psockClient = new CClientSocket(this);if(!m_psockClient->Create()delete m_psockClient;m_pso

7、ckClient = NULL;MessageBox(GetError(GetLastError(), _T("錯(cuò)誤"), MB_ICONHAND);return ;/與服務(wù)器建立連接CString strIPAddress;GetDlgItem(IDC_IPADDRESS)->GetWindowText(strIPAddress);if(!m_psockClient->Connect(strIPAddress, m_wPort) /Connect連接服務(wù)器,服務(wù)器用OnAccept響應(yīng)delete m_psockClient;m_psockClient = N

8、ULL;MessageBox(GetError(GetLastError(), _T("錯(cuò)誤"), MB_ICONHAND);return ;/初始化客戶端套接字m_psockClient->Init(); 服務(wù)器響應(yīng)CClientSocket* pSocket=new CClientSocket(this);/接收請(qǐng)求后獲得新的套接字,交由新的套接字處理請(qǐng)求if(m_psockServer->Accept(*pSocket) /非零則接收連接請(qǐng)求成功/初始化Accpet返回的套接字pSocket->Init();CMessage* pMsg;/檢測(cè)套接字

9、是否為空,空則還沒有連接任何客戶端if(m_psockClient=NULL)pMsg=new CMessage(CONNECT_BE_ACCEPT); pSocket->SendMsg(pMsg);/發(fā)回“這邊可以連接”消息回去,客戶端的Receive接收m_psockClient=pSocket; /若為服務(wù)器,則之前未初始化,可保存這個(gè)套接字,用來(lái)跟客戶端交互GetDlgItem(IDC_SELECT_FILE)->EnableWindow(TRUE);else pMsg=new CMessage(CONNECT_BE_REFUSE);pSocket->SendMsg(

10、pMsg); 客戶端收到連接成功消息if(pMsg->m_nType=CONNECT_BE_ACCEPT)GetDlgItem(IDC_SELECT_FILE)->EnableWindow(TRUE);return;2、傳輸控制模塊 該工程用了兩對(duì)套接字,一對(duì)用來(lái)接收傳輸控制消息,一對(duì)用來(lái)收發(fā)文件。我們這個(gè)模塊用的是第一對(duì) 在MFC中定義了一個(gè)在套接字編程中使用的CSocketFile類,可以充分發(fā)揮CSocket類的特性。CSocketFile類是CFile的派生類,主要用來(lái)在Windows Sockets編程中發(fā)送和接收序列化數(shù)據(jù)(如結(jié)構(gòu)體數(shù)據(jù))。通過(guò)把CSocketFile類

11、對(duì)象、CArchive對(duì)象和CSocket創(chuàng)建的套接字對(duì)象聯(lián)系起來(lái),可以實(shí)現(xiàn)數(shù)據(jù)的加載(接收)和存儲(chǔ)(發(fā)送)。 MFC集成CSocketFile、CSocket、CArchive可以簡(jiǎn)化網(wǎng)絡(luò)傳輸。下圖可以直觀地反應(yīng)這三者是如何結(jié)合來(lái)在客戶端和服務(wù)器之間傳輸消息的 先來(lái)看看服務(wù)器和客戶端的套接字初始化工作:m_pFile = new CSocketFile(this);m_pArchiveIn = new CArchive(m_pFile,CArchive:load);m_pArchiveOut = new CArchive(m_pFile,CArchive:store); 這樣一來(lái),當(dāng)使用m_

12、pArchiveIn對(duì)象來(lái)調(diào)用可串行化消息類CMessage的Serialize時(shí),接收方就能響應(yīng)OnReceive消息,來(lái)完成控制信息的傳遞。 本工程在主類CsendFileDlg中定義了傳輸?shù)娜N狀態(tài):m_bIsWait:已連接,正在等待傳輸文件m_bIsTransmitting: 正在傳輸文件m_bIsStop:傳輸已終止本工程定義的可串行化消息類CMessage,用來(lái)傳遞文件名m_strFileName、文件長(zhǎng)度m_dwFileSize以及當(dāng)前的傳輸狀態(tài)m_nType,大致流程如下圖:其中,我在建工程的時(shí)候,把客戶端和服務(wù)器集成在了一個(gè)界面OnReceive就用來(lái)接收兩方的消息,關(guān)鍵代

13、碼如下:CMessage* pMsg=new CMessage();pSocket->ReceiveMsg(pMsg);if(pMsg->m_nType=CONNECT_BE_ACCEPT)GetDlgItem(IDC_SELECT_FILE)->EnableWindow(TRUE);return;if(pMsg->m_nType=CONNECT_BE_REFUSE)MessageBox(_T("服務(wù)器正在和另外的客戶端連接,稍等"),_T("錯(cuò)誤"), MB_ICONHAND);delete m_psockClient;m_ps

14、ockClient=NULL;return ;if (pMsg->m_nType=DISCONNECT) MessageBox(_T("對(duì)方已經(jīng)關(guān)閉"), _T("警告"), MB_ICONHAND);if(m_psockClient != NULL)delete m_psockClient;m_psockClient = NULL;/接收請(qǐng)求if(pMsg->m_nType=REQUEST)m_bIsWait=TRUE; /忙狀態(tài)置1m_strFileName=pMsg->m_strFileName;m_dwFileSize=pMsg

15、->m_dwFileSize;CString strName,strSize;strName.Format("文件名:%s",m_strFileName);strSize.Format("文件大小:%ld字節(jié)",strSize);/這里完成了發(fā)送文件前給對(duì)方提示的功能if(MessageBox(strName+"rn"+strSize,"對(duì)方請(qǐng)求向你發(fā)送文件",MB_OKCANCEL)=IDCANCEL)CMessage* pMsg = new CMessage(REFUSE);m_psockClient-&

16、gt;SendMsg(pMsg);return;CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"所有文件(*.*)|*.*|",this);dlg.m_ofn.lpstrTitle=_T("另存為");strcpy(dlg.m_ofn.lpstrFile,m_strFileName.GetBuffer(m_strFileName.GetLength();if(dlg.DoModal()=IDOK)if(m_bIsWait=FALSE)MessageBox(_T(&

17、quot;對(duì)方已經(jīng)取消文件發(fā)送"), _T("警告"), MB_ICONEXCLAMATION);return ;m_bIsClient=FALSE; m_strPath=dlg.GetPathName();/啟動(dòng)接收文件的線程GetDlgItem(IDC_SR)->SetWindowText("已接收:");pThreadListen = :AfxBeginThread(_ListenThread, this); /服務(wù)器接收到RUEST,開啟接收文件線程 return ;if(m_bIsWait = TRUE)/告訴對(duì)方文件發(fā)送請(qǐng)求被

18、拒絕 CMessage* pMsg = new CMessage(REFUSE);m_psockClient->SendMsg(pMsg);m_bIsWait = FALSE;return ;/當(dāng)對(duì)方同意,并且已經(jīng)準(zhǔn)備好接收文件的時(shí)候if(pMsg->m_nType=ACCEPT)KillTimer(1);m_bIsWait=FALSE; /等待狀態(tài)清空/啟動(dòng)發(fā)送文件線程GetDlgItem(IDC_SR)->SetWindowText("已發(fā)送:");pThreadSend=:AfxBeginThread(_SendThread,this);return

19、;/當(dāng)發(fā)送文件請(qǐng)求被拒絕if(pMsg->m_nType=REFUSE)m_bIsWait=FALSE;MessageBox(_T("請(qǐng)求被拒絕"), _T("警告"), MB_ICONEXCLAMATION);return ;/當(dāng)對(duì)方取消文件傳輸時(shí)執(zhí)行該if語(yǔ)句里面的內(nèi)容 if(pMsg->m_nType = CANCEL)m_bIsWait = FALSE;return ; 3、文件傳輸模塊兩個(gè)線程:_ListenThread():建立新的監(jiān)聽套接字,準(zhǔn)備接收文件_SendThread(): 建立客戶端套接字,連接監(jiān)聽套接字,發(fā)送文件 當(dāng)

20、兩方建立了可靠的連接,一方選擇文件后,就會(huì)使用傳輸控制模塊給對(duì)方發(fā)送文件發(fā)送請(qǐng)求,對(duì)方的ProcessReceive接收到后查看當(dāng)前的消息狀態(tài),(上個(gè)模塊的OnReceive已經(jīng)寫得很清楚),同意接受后,開啟文件接收線程,同時(shí)給發(fā)送方返回一個(gè)準(zhǔn)備完成狀態(tài),于是,發(fā)送方開啟文件發(fā)送線程,最后完成文件的傳輸工作,同時(shí)置狀態(tài)m_bIsStop為TRUE,便于雙方傳輸控制 發(fā)送線程關(guān)鍵函數(shù)SendFilevoid CSendFileDlg:SendFile(CSocket& senSo)m_bIsTransmitting=TRUE; CFile file;if (!file.Open(m_st

21、rPath,CFile:modeRead|CFile:typeBinary)AfxMessageBox(_T("文件打開失敗");senSo.Close();return ;m_ctrlProgress.SetRange32(0,m_dwFileSize);int nSize=0,nLen=0;DWORD dwCount = 0;char bufBLOCKSIZE=0;file.Seek(0,CFile:begin);/開始傳送while(1)/每次讀取BLOCKSIZE大小nLen=file.Read(buf,BLOCKSIZE);if(nLen=0)break;/發(fā)送文

22、件內(nèi)容nSize=senSo.Send(buf,nLen);dwCount+=nSize;m_ctrlProgress.SetPos(dwCount);CString strTransfersSize;strTransfersSize.Format("%ld 字節(jié)",dwCount);/設(shè)置進(jìn)度條屬性GetDlgItem(IDC_RECEIVE_SIZE)->SetWindowText(strTransfersSize);int p=(double)dwCount)/(int)m_dwFileSize+1)*100+1;strTransfersSize.Format(

23、"%d",p);strTransfersSize+="%"/判斷用戶是否停止發(fā)送if(m_bIsStop)m_bIsStop=FALSE;break;if (nSize=SOCKET_ERROR)break;file.Close();senSo.Close();if(m_dwFileSize=dwCount)AfxMessageBox(_T("文件發(fā)送成功");elseAfxMessageBox(_T("文件發(fā)送失敗");m_ctrlProgress.SetPos(0);m_bIsTransmitting = FA

24、LSE; 接收線程關(guān)鍵函數(shù)ReceiveFilevoid CSendFileDlg:ReceiveFile(CSocket& recSo)/停止等待超時(shí)計(jì)時(shí)器KillTimer(2);m_bIsWait=FALSE;m_bIsTransmitting=TRUE; /正在傳輸置1m_ctrlProgress.SetRange32(0,m_dwFileSize);int nSize=0;DWORD dwCount=0;char bufBLOCKSIZE=0;CFile file(m_strPath,CFile:modeCreate|CFile:modeWrite);/開始接收文件while

25、 (1)/每次接收BLOCKSIZE大小的內(nèi)容nSize=recSo.Receive(buf,BLOCKSIZE);if(nSize=0)break;/寫入文件file.Write(buf,nSize);dwCount+=nSize;m_ctrlProgress.SetPos(dwCount);CString strTransfersSize;strTransfersSize.Format("%ld 字節(jié)",dwCount);GetDlgItem(IDC_RECEIVE_SIZE)->SetWindowText(strTransfersSize);int p=(dou

26、ble)dwCount)/(int)m_dwFileSize+1)*100+1;strTransfersSize.Format("%d",p);strTransfersSize+="%"GetDlgItem(IDC_PECENT)->SetWindowText(strTransfersSize)/用戶是否停止了接收if(m_bIsStop)m_bIsStop=FALSE;break;file.Close();recSo.Close();if(m_dwFileSize=dwCount)AfxMessageBox(_T("文件接收成功&quo

27、t;);elseAfxMessageBox(_T("文件接收失敗");m_ctrlProgress.SetPos(0);m_bIsTransmitting = FALSE;六、關(guān)鍵問(wèn)題及其解決方法 1、在傳輸文件前、中、后能讓程序響應(yīng)各類控制消息集成后的互通消息代碼很簡(jiǎn)單:void Serialize(CArchive& ar)if(ar.IsStoring()ar << m_nType;ar << m_strFileName;ar << m_dwFileSize;elsear >> m_nType;ar >&g

28、t; m_strFileName;ar >> m_dwFileSize; CSocket、CSocketFile、CArchive三個(gè)類的聯(lián)動(dòng),完美地解決了這個(gè)問(wèn)題,在傳輸文件的過(guò)程中,若一方有事件發(fā)生(暫停傳輸、關(guān)閉連接等等),則改變預(yù)先設(shè)定的狀態(tài)值,SendMsg給CSocketFile,觸發(fā)對(duì)方的虛函數(shù)OnReceive,從而解決通信問(wèn)題。 2、解決單線程傳輸阻塞的非“非阻塞”式方法在使用AfxBeginThread實(shí)現(xiàn)多線程的同時(shí),也增加了諸如發(fā)送超時(shí)、接收超時(shí)等判斷(使用Windows定時(shí)器SetTimer響應(yīng)OnTime來(lái)實(shí)現(xiàn)),這一定程度上增強(qiáng)了程序的魯棒性 文件的傳

29、輸時(shí)阻塞式的,所以在主線程中直接傳輸文件必然導(dǎo)致界面卡死,所以這里我用到了多線程技術(shù),為傳輸文件和接受文件分別開設(shè)線程。 _ListenThreadUINT _ListenThread(LPVOID lparam)CSendFileDlg* pDlg=(CSendFileDlg*)lparam;/創(chuàng)建服務(wù)器端套接字CSocket sockSrvr;if(!sockSrvr.Create(pDlg->m_wPort+PORT)pDlg->TransfersFailed();:MessageBox(HWND)lparam, pDlg->GetError(GetLastError(

30、), _T("錯(cuò)誤"), MB_ICONHAND|MB_OK);return -1;if(!sockSrvr.Listen() /監(jiān)聽pDlg->TransfersFailed();:MessageBox(HWND)lparam, pDlg->GetError(GetLastError(), _T("錯(cuò)誤"), MB_ICONHAND|MB_OK);return -1;/接收套接字已經(jīng)創(chuàng)建向主對(duì)話框發(fā)送自定義消息,該消息發(fā)送一個(gè)消息給發(fā)送方,可以開始傳數(shù)據(jù)pDlg->SendMessage(WM_ACCEPT_TRANSFERS);CS

31、ocket recSo;if(!sockSrvr.Accept(recSo) :MessageBox(HWND)lparam, pDlg->GetError(GetLastError(), _T("錯(cuò)誤"), MB_ICONHAND|MB_OK);return -1;sockSrvr.Close();/調(diào)用主對(duì)話框類中的ReceiveFile成員函數(shù)進(jìn)行文件的接受 pDlg->ReceiveFile(recSo);return 0; _SendThread UINT _SendThread(LPVOID lparam)CSendFileDlg* pDlg=(CS

32、endFileDlg*)lparam;/創(chuàng)建套接字CSocket sockClient;if(!sockClient.Create()pDlg->TransfersFailed();:MessageBox(HWND)lparam, pDlg->GetError(GetLastError(), _T("錯(cuò)誤"), MB_ICONHAND|MB_OK);return -1;CString strIPAddress;UINT nPort;/獲取對(duì)方地址pDlg->m_psockClient->GetPeerName(strIPAddress,nPort);

33、/連接服務(wù)器if(!sockClient.Connect(strIPAddress,pDlg->m_wPort+PORT)pDlg->TransfersFailed();:MessageBox(HWND)lparam, pDlg->GetError(GetLastError(), _T("錯(cuò)誤"), MB_ICONHAND|MB_OK);return -1;/調(diào)用主對(duì)話框類進(jìn)行文件發(fā)送pDlg->SendFile(sockClient);return 0; 3、在文件傳輸前,提前讓對(duì)方了解文件信息,以便對(duì)方判斷是否接受文件。由于本工程實(shí)現(xiàn)了“文件傳輸

34、與兩端消息響應(yīng)”的明確劃分,該功能實(shí)現(xiàn)相當(dāng)簡(jiǎn)單,只需要在發(fā)送端SelectFile之后向接收端發(fā)送一個(gè)“準(zhǔn)備發(fā)送”的消息(該消息由于CMessage的封裝,包含了文件的基本消息),該消息被接收后彈出對(duì)話框,由接收方來(lái)選擇是否接受。接收端由接收方選擇對(duì)話框選項(xiàng),根據(jù)MessageBox返回值IDOK或是IDCANCLE,若為IDOK,則發(fā)送一個(gè)Accpet消息給發(fā)送方,否則發(fā)送一個(gè)REFUSE回去,均由發(fā)送方的OnReceive虛函數(shù)處理,大致過(guò)程如下:七、設(shè)計(jì)結(jié)果1、服務(wù)器客戶端的選擇(服務(wù)器客戶端集成) 說(shuō)明:根據(jù)每個(gè)進(jìn)程實(shí)例的用戶選擇RadioBox來(lái)更改界面外觀 初始默認(rèn)服務(wù)器:Init

35、Dialog時(shí)設(shè)置按鈕文本及調(diào)用gethostname獲取本機(jī)IPv4地址及設(shè)置端口號(hào) 根據(jù)用戶選擇響應(yīng)RadioBox消息,若為客戶端,則更改界面外觀,同時(shí)內(nèi)部變量“m_bIsCilent”設(shè)置為TRUE(默認(rèn)為FALSE),便于程序的后續(xù)工作2、簡(jiǎn)單的文件傳輸及簡(jiǎn)單的傳輸控制 說(shuō)明:文件的發(fā)送專門由兩個(gè)線程完成,線程中創(chuàng)建用于文件傳輸?shù)奶捉幼?,而文件的傳輸控制則由主界面響應(yīng)消息來(lái)完成,分工明確3、設(shè)計(jì)思考題的回答套接字有基于阻塞和非阻塞的工作方式,試問(wèn)你編寫的程序是基于阻塞還是非阻塞的?各有什么優(yōu)缺點(diǎn)? 答:本程序文件傳輸基于阻塞、傳遞文件控制消息基于非阻塞。1) 阻塞傳輸具有穩(wěn)定性好,代

36、碼邏輯簡(jiǎn)單,編寫程序方便的優(yōu)點(diǎn),但是阻塞傳輸效率低2) 非阻塞傳輸相對(duì)應(yīng)的效率較高,但是編寫程序較為復(fù)雜,傳輸也更難控制 如何將上述通信改為非阻塞,避免阻塞? 答:在源代碼采用Send發(fā)送文件和Receive來(lái)接收文件的基礎(chǔ)上,改用OnReceive和OnSend來(lái)響應(yīng)文件發(fā)送和接收消息,結(jié)合MFC的CasyncSocket異步非阻塞套接字類來(lái)編程 在傳輸前能否先將要傳輸?shù)奈募南嚓P(guān)屬性現(xiàn)行報(bào)告給對(duì)方,以便對(duì)方判斷是否接受該文件的傳輸? 答:由于本工程實(shí)現(xiàn)了“文件傳輸與兩端消息響應(yīng)”的明確劃分,該功能實(shí)現(xiàn)相當(dāng)簡(jiǎn)單,只需要在發(fā)送端SelectFile之后向接收端發(fā)送一個(gè)“準(zhǔn)備發(fā)送”的消息(該消息

37、由于CMessage的封裝,包含了文件的基本消息),該消息被接收后彈出對(duì)話框,由接收方來(lái)選擇是否接受。八、軟件使用說(shuō)明 打開一個(gè)進(jìn)程實(shí)例后,一端選擇服務(wù)器(默認(rèn)為服務(wù)器),軟件會(huì)自動(dòng)調(diào)用庫(kù)函數(shù)獲取本機(jī)IPv4地址以及自動(dòng)設(shè)置端口號(hào),點(diǎn)擊【啟動(dòng)】按鈕開始監(jiān)聽客戶端的接入 客戶端打開軟件后,點(diǎn)選【客戶端】,此時(shí)IP地址控件置空,用戶輸入正在監(jiān)聽的客戶端的IP地址,必要時(shí)輸入對(duì)應(yīng)的端口號(hào),點(diǎn)選【連接】,開始申請(qǐng)連接服務(wù)器。 連接選項(xiàng)設(shè)有超時(shí)器,超時(shí)會(huì)提示連接超時(shí),成功后兩端建立連接。 連接成功后,兩端的【選擇文件】按鈕點(diǎn)亮,可以選擇文件發(fā)送。點(diǎn)擊【選擇文件】后彈出文件選擇對(duì)話框,發(fā)送方成功選擇文件,

38、點(diǎn)擊【確定】。此時(shí)啟動(dòng)發(fā)送超時(shí)器,超時(shí)顯示超時(shí)。若成功,接收方彈出文件保存對(duì)話框,接收方選擇好接收目錄后點(diǎn)擊【確定】,文件傳輸正式開始。 傳輸開始后,雙方【停止傳輸】【取消】點(diǎn)亮,雙發(fā)可以通過(guò)點(diǎn)選這兩個(gè)按鈕來(lái)進(jìn)行傳輸控制。傳輸失敗會(huì)提示失敗消息。九、參考資料1 zhuyf87.TCP三次握手.博客園博客,2012.2 高傳善,毛迪林,曹袖.計(jì)算機(jī)網(wǎng)絡(luò)教程.高等教育出版社,2008.3 孫鑫.VC+深入詳解.電子工業(yè)出版社,2006.十、驗(yàn)收時(shí)間及驗(yàn)收情況驗(yàn)收時(shí)間:2016.12.29驗(yàn)收情況:演示了文件傳輸?shù)某绦?,從建立連接單選擇文件再到傳輸文件,到終止傳輸,沒有出現(xiàn)問(wèn)題。通信方式是阻塞還是非

39、阻塞的? 答:本程序使用了兩對(duì)套接字,一對(duì)工作于阻塞方式,用于傳輸文件,由于阻塞,故開辟了線程供其傳輸,一對(duì)工作于非阻塞方式,通過(guò)響應(yīng)來(lái)實(shí)現(xiàn)客戶端服務(wù)器的消息控制。客戶端服務(wù)器建立連接的過(guò)程?答:使用MFC的CSocket類簡(jiǎn)化C/S連接:服務(wù)器Create()創(chuàng)建監(jiān)聽套接字,Listen()開始監(jiān)聽;服務(wù)器創(chuàng)建一個(gè)連接套接字,Connect()請(qǐng)求服務(wù)器連接,服務(wù)器OnAccept響應(yīng),并使用另外創(chuàng)建的套接字開始與客戶端通信。程序的魯棒性怎么樣?答:程序在創(chuàng)建套接字,連接服務(wù)器等操作時(shí)用了比較多的錯(cuò)誤檢測(cè)與提示,比如在套接字創(chuàng)建過(guò)程:對(duì)Create()的返回值進(jìn)行分析,如果是0則代表創(chuàng)建失敗

40、,立即調(diào)用GetLastError()分析錯(cuò)誤原因,并使用MessageBox彈出提醒用戶。 另外也使用了TRYCATCH塊,增強(qiáng)程序的錯(cuò)誤檢測(cè)和恢復(fù)能力。十一、設(shè)計(jì)體會(huì) 1、之前寫的程序大多都是“單機(jī)”的,這次工程的實(shí)踐讓我更加深入地了解了互聯(lián)網(wǎng)程序的編寫,認(rèn)識(shí)了Socket套接字的使用。 2、通過(guò)編寫程序,在應(yīng)用層面理解了TCP的“三次握手”,深切體會(huì)到了基于TCP連接的傳輸穩(wěn)定性。 3、在設(shè)計(jì)時(shí)遇到了阻塞和非阻塞的選擇,好在工程實(shí)現(xiàn)的時(shí)候,由于微軟對(duì)Win_Sock的封裝,結(jié)合CSocket、CSocketFile、CArchive三個(gè)類的使用,很好地簡(jiǎn)化了兩端的通信問(wèn)題,從而可以放心地

41、把傳輸數(shù)據(jù)作為阻塞方式放到新開的線程中。 4、在工程初步完成的時(shí)候,把程序放到兩臺(tái)不處于一個(gè)局域網(wǎng)內(nèi)的機(jī)子上,發(fā)現(xiàn)不能連接。通過(guò)課本的翻閱和網(wǎng)上資料的查詢,了解了NAT以及NAT穿越技術(shù),知道了許多基于互聯(lián)網(wǎng)的技術(shù)都需要用到“NAT穿孔”。 5、文件傳輸涉及到了很多的異常處理,在之前編寫的大部分程序要么沒有異常處理,要么單純地使用if else解決,在本次工程中用到了一些TRY CATCH塊,體會(huì)到了異常處理機(jī)制的重要性。路由器配置實(shí)驗(yàn)一、實(shí)驗(yàn)?zāi)康?. 認(rèn)識(shí)路由器的端口、型號(hào) 2掌握路由器的路由配置 3. 理解網(wǎng)絡(luò)互聯(lián)的基本原理 二、實(shí)驗(yàn)環(huán)境與設(shè)備 本實(shí)驗(yàn)在 PC 機(jī)上利用模擬軟件 Packe

42、t Tracer V6 進(jìn)行操作。 三、實(shí)驗(yàn)內(nèi)容 1. 路由器接口的配置 2. 靜態(tài)路由配置 3. 默認(rèn)路由配置 4. 動(dòng)態(tài)路由配置 本次實(shí)驗(yàn)的主要任務(wù)是了解路由器的基本設(shè)置,和網(wǎng)絡(luò)之間的連接關(guān)系。通過(guò) 這次的實(shí)驗(yàn)很好的掌握了各個(gè)網(wǎng)段之間的,各個(gè)路由器下的 pc 的連接情況。通 過(guò)對(duì)靜態(tài),默認(rèn),動(dòng)態(tài)路由配置,使得各個(gè)路由器下的 PC 相互通信。四、實(shí)驗(yàn)步驟1、路由器接口的配置 創(chuàng)建拓?fù)浣Y(jié)構(gòu)圖: (1) 為主機(jī) PC0,PC1,PC2 配置 IP 地址、子網(wǎng)掩碼和默認(rèn)網(wǎng)關(guān)。 配置情況如下:IP地址和子網(wǎng)掩碼的配置:(2) 為路由器的各個(gè)接口分配 IP 地址和子網(wǎng)掩碼,交換機(jī)不用配置。 配置方法入

43、下: WAN口配置:(3) 查看路由器的路由表使用命令:show ip route 顯示路由表中的路由信息。保存此時(shí)路由器顯示的路由信息,以便與后面的實(shí)驗(yàn)結(jié)果進(jìn)行比較。 (C 表示直連路由)Router0 的路由表:Router1的路由表Router2的路由表(4)測(cè)試主機(jī)之間的連通性PC0 與 PC2 的連通性: 可以看到PC0 ping不到PC2,可見PC0是不知道PC2的網(wǎng)段的PC1與PC2的連通性: 根據(jù)網(wǎng)關(guān)發(fā)回的消息,同樣PC1是ping不到PC2的2. 配置靜態(tài)路由(1)在 Router0 中添加一條到網(wǎng)絡(luò) 192.168.3.0 的靜態(tài)路由,命令如下:Router(config)#ip route 192.168.3.0 255.255.255.0 172.16.1.1(2)再去查看 Router0 路由表,與步驟(2)中的路由表進(jìn)行對(duì)比,觀察路由表的變化情況。 可以看到,路由器0多了一條S的路由信息,之后有目的為該IP的包到達(dá)路由器,路由器就能根據(jù)路由表做出路由。(3)在 Router2 中添加一條到網(wǎng)絡(luò) 192.168.1.0 的路由后,路由表如下:Router(config)#ip route 192.168.1.0 255.255.255.0

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論