計(jì)算機(jī)網(wǎng)絡(luò)通信程序設(shè)計(jì)-TCP文件傳輸程序.doc
《計(jì)算機(jī)網(wǎng)絡(luò)通信程序設(shè)計(jì)-TCP文件傳輸程序.doc》由會(huì)員分享,可在線閱讀,更多相關(guān)《計(jì)算機(jī)網(wǎng)絡(luò)通信程序設(shè)計(jì)-TCP文件傳輸程序.doc(19頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
目錄 一、實(shí)驗(yàn)名稱:TCP文件傳輸程序 2 二、實(shí)驗(yàn)要求 2 三、總體規(guī)劃 2 1、網(wǎng)絡(luò)傳輸協(xié)議的選擇 2 2、TCP協(xié)議在VC++中的實(shí)現(xiàn) 2 3、傳輸數(shù)據(jù)的緩沖問(wèn)題 3 4、Socket的文件化管理 3 5、數(shù)據(jù)的串行化問(wèn)題 4 6、接收數(shù)據(jù)判斷是否傳輸完畢的方法 4 四、實(shí)驗(yàn)運(yùn)行測(cè)試 4 五、心得體會(huì) 7 六、程序源代碼 7 1、建立服務(wù)器偵聽(tīng)套接字的類CListenSocket的定義與實(shí)現(xiàn) 7 2、建立數(shù)據(jù)傳輸套接字的類CTransSocket的定義與實(shí)現(xiàn) 8 3、用于數(shù)據(jù)串行化的類CSave的定義與實(shí)現(xiàn): 8 4、主對(duì)話框CTcpDlg類的定義與實(shí)現(xiàn): 9 七、參考文獻(xiàn) 18 一、實(shí)驗(yàn)名稱:TCP文件傳輸程序 二、實(shí)驗(yàn)要求 1、設(shè)計(jì)一個(gè)應(yīng)用程序,該應(yīng)用程序能夠?qū)崿F(xiàn)網(wǎng)絡(luò)中兩臺(tái)計(jì)算機(jī)之間傳輸文件。 2、一個(gè)程序既能夠建立服務(wù)器又能夠以終端的形式連接服務(wù)器。 3、終端或者服務(wù)器既能夠發(fā)送文件又能夠接收文件。 4、傳送文件類型應(yīng)為任何類型,文件大小為任意。 三、總體規(guī)劃 1、網(wǎng)絡(luò)傳輸協(xié)議的選擇 在TCP/IP協(xié)議棧中,有兩個(gè)高級(jí)協(xié)議是我們網(wǎng)絡(luò)應(yīng)用程序編寫(xiě)者應(yīng)該了解的,它們"傳輸控制協(xié)議"(Transmission Control Protocol,簡(jiǎn)稱TCP)和"用戶數(shù)據(jù)報(bào)協(xié)議"(User Datagrm Protocol,簡(jiǎn)稱UDP)。 TCP是面向連接的通信協(xié)議,TCP提供兩臺(tái)計(jì)算機(jī)之間的可靠無(wú)錯(cuò)的數(shù)據(jù)傳輸。應(yīng)用程序利用TCP進(jìn)行通信時(shí),源和目標(biāo)之間會(huì)建立一個(gè)虛擬連接。這個(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ù)。簡(jiǎn)單地說(shuō),如果一個(gè)主機(jī)向另外一臺(tái)主機(jī)發(fā)送數(shù)據(jù),這一數(shù)據(jù)就會(huì)立即發(fā)出,而不管另外一臺(tái)主機(jī)是否已準(zhǔn)備接收數(shù)據(jù)。如果另外一臺(tái)主機(jī)收到了數(shù)據(jù),它不會(huì)確認(rèn)收到與否。 為了使兩臺(tái)計(jì)算機(jī)之間傳輸?shù)奈募?shù)據(jù)不會(huì)丟失或發(fā)生錯(cuò)誤,應(yīng)該采用TCP協(xié)議。 2、TCP協(xié)議在VC++中的實(shí)現(xiàn) 在VC++中,網(wǎng)絡(luò)協(xié)議的實(shí)現(xiàn)有以下幾種方式: a、采用WinSocket API函數(shù)。 API函數(shù)中提供了基本Socket的系統(tǒng)調(diào)用,具體實(shí)現(xiàn)方法為服務(wù)器端首先要調(diào)用socket()函數(shù)建立一個(gè)流式套接字,用bind()函數(shù)與本機(jī)的一個(gè)端口建立關(guān)聯(lián),繼續(xù)調(diào)用listen()函數(shù)將套接字置于被動(dòng)的偵聽(tīng)方式以監(jiān)聽(tīng)連接,然后調(diào)用accept()函數(shù)進(jìn)入等待狀態(tài)之后才可以接收來(lái)自客戶端的請(qǐng)求,一旦接收到客戶端通過(guò)connect發(fā)出的連接請(qǐng)求,accept將返回一個(gè)新的套接字描述符。通過(guò)此套接字描述符調(diào)用send()或recv()函數(shù)即可與客戶端進(jìn)行數(shù)據(jù)收發(fā)。待數(shù)據(jù)傳送完成,服務(wù)器客戶端調(diào)用closesocket()關(guān)閉套接字。 該方法在編程過(guò)程中需要注意socket連接的整個(gè)過(guò)程,編程工作量大,編程效率低,單卻可以加深對(duì)網(wǎng)絡(luò)協(xié)議的認(rèn)識(shí)。 程序流程示意圖如下: Socket() Bind() Listen() Accept() Socket() Connect() Send()/recv() Closesocket() Send()/recv() Closesocket() b、采用VC++中提供的MFC類,CAsyncSocket或CSocket. 兩個(gè)類都對(duì)WinSocket API進(jìn)行了封裝,CSocket對(duì)它的封裝比CAsyncSocket更深,使得對(duì)于從未接觸過(guò)WinSockets API的編程程序員,也能夠編寫(xiě)網(wǎng)絡(luò)程序。 而本程序也是采用了CSocket類進(jìn)行編程。 3、傳輸數(shù)據(jù)的緩沖問(wèn)題 本機(jī)要傳給對(duì)方的文件不是從外存直接通過(guò)網(wǎng)絡(luò)發(fā)送的,而對(duì)方發(fā)送的數(shù)據(jù)也不是直接存入外存的。而是在內(nèi)存中開(kāi)辟一塊緩沖區(qū),從外存取出的文件先存入緩沖區(qū),然后傳給socket。而從socket接收的數(shù)據(jù)也是先存入緩沖區(qū)然后再存到外存。 為了解決緩沖問(wèn)題,VC++添加了CArchive類,CArchive類專門(mén)用來(lái)管理一塊內(nèi)存單元,其大小可以自己來(lái)定義。用CArhive類既以把數(shù)據(jù)載入分配的內(nèi)存區(qū),又可以將內(nèi)存區(qū)的數(shù)據(jù)存入文件。在該類的對(duì)象初始化時(shí),需要和某個(gè)文件建立連接,這樣數(shù)據(jù)就可以載入或存儲(chǔ)了。 4、Socket的文件化管理 在大多數(shù)編程環(huán)境和編程語(yǔ)言中大多把socket看作一個(gè)特殊的文件,其傳輸過(guò)程就可以看作是對(duì)文件的讀寫(xiě)操作。而VC++也是如此。 為了便于網(wǎng)絡(luò)Socket的管理,在VC++中,可以對(duì)網(wǎng)絡(luò)Socket實(shí)現(xiàn)文件化管理。為了實(shí)現(xiàn)該功能,需要用到VC++中的類CSocketFile類,該類直接派生于CFile類,使用該類可以達(dá)到對(duì)Socket文件化管理的目的。如CSocketFile類可以與CArchive類建立連接,這樣就為Socket創(chuàng)立了一塊緩沖區(qū)。應(yīng)該注意的是雖然CSocketFile類直接從CFile類中派生過(guò)來(lái),但CFile類中的一些函數(shù)CSocket是不能調(diào)用的,如果調(diào)用,系統(tǒng)便會(huì)返回錯(cuò)誤。 5、數(shù)據(jù)的串行化問(wèn)題 從對(duì)方的計(jì)算機(jī)傳輸過(guò)來(lái)的數(shù)據(jù)存入了內(nèi)存,如何將這些數(shù)據(jù)寫(xiě)入文件呢?要發(fā)送的文件如何將其載入內(nèi)存?在這個(gè)程序里我采用了數(shù)據(jù)串行化方法。也就是通過(guò)對(duì)象的Serialize()的重載來(lái)實(shí)現(xiàn)文件的存取。我在程序中采用了通過(guò)重載CObject類中的Serialize()的方式,具體做法是:從文件中讀取文件數(shù)據(jù)存入數(shù)組,利用CArchive的重載運(yùn)算符 << ,將數(shù)組數(shù)據(jù)讀入內(nèi)存,而存數(shù)據(jù)過(guò)程與其相反。 6、接收數(shù)據(jù)判斷是否傳輸完畢的方法 文件接受數(shù)據(jù)時(shí)怎樣才能判斷已經(jīng)接受完畢呢?我采用的方法是在傳輸包上加標(biāo)記位的方法。每發(fā)送一個(gè)數(shù)據(jù)包,總在最前面加一個(gè)位m_WEnd,如果標(biāo)記為0,說(shuō)明未傳輸完畢,以后還有數(shù)據(jù)傳送過(guò)來(lái),如果標(biāo)記為1,說(shuō)明已經(jīng)傳輸完畢,可以進(jìn)行一些后續(xù)工作。而另一端,每接受一個(gè)數(shù)據(jù)包,就檢查以下該標(biāo)記位,以確定是否傳輸完畢。 四、實(shí)驗(yàn)運(yùn)行測(cè)試 1、建立服務(wù)器 用于顯示狀態(tài) 用于接收文件 用于發(fā)送文件 用于客戶端連接 用于建立服務(wù)器 2、客戶端建立連接 3、發(fā)送文件 a、客戶端發(fā)送 b、服務(wù)器端接收 4、成功發(fā)送 5、在E:盤(pán)中查找接收到的文件 此為接收到的文件 五、心得體會(huì) 在這五天的時(shí)間里我按照設(shè)計(jì)書(shū)的要求應(yīng)用網(wǎng)絡(luò)編程的相關(guān)知識(shí)編寫(xiě)了一個(gè)實(shí)現(xiàn)文件傳輸?shù)膽?yīng)用程序。在編寫(xiě)過(guò)程中,收獲頗豐。首先是對(duì)TCP協(xié)議和UDP協(xié)議有了更進(jìn)一步的認(rèn)識(shí);其次在編寫(xiě)過(guò)程中,通過(guò)翻閱書(shū)籍學(xué)習(xí)了VC++編程和MFC的相關(guān)內(nèi)容,拓展了自己的知識(shí)面,學(xué)到了很多在課堂上無(wú)法學(xué)到的東西。 當(dāng)然,由于對(duì)Socket編程畢竟還不太熟練,難免會(huì)出現(xiàn)一些問(wèn)題,現(xiàn)將這些問(wèn)題總結(jié)如下: 1、開(kāi)始時(shí)在數(shù)據(jù)串行化的設(shè)計(jì)時(shí),直接用 CArchive類的對(duì)象 << CFile類的對(duì)象 或 CArchive類的對(duì)象 >> CFile類的對(duì)象 出現(xiàn)錯(cuò)誤,查閱MSDN發(fā)現(xiàn)不能直接用 << 運(yùn)算符不能直接對(duì)CFile類的對(duì)象進(jìn)行操作。 2、接收端操作同數(shù)據(jù)的傳輸必須同步,即必須確保在接收數(shù)據(jù)時(shí),應(yīng)確保數(shù)據(jù)已經(jīng)傳送到了接收端,也就是防止因?yàn)閿?shù)據(jù)為傳送過(guò)來(lái)而導(dǎo)致的接收失敗。為了防止接收失敗而導(dǎo)致數(shù)據(jù)丟失,應(yīng)反復(fù)接收,直到接收數(shù)目符合為止。 如:i = 0; while(i < m_WNum) i = ar.Read(&Bbuf[i], m_WNum - i) + i; 所幸的是這些問(wèn)題都在參考資料和老師的幫助下得到了解決。最終圓滿的完成了課程設(shè)計(jì)任務(wù)書(shū)的要求。自身分析問(wèn)題和解決問(wèn)題的能力也得到了提升,為以后的實(shí)驗(yàn)設(shè)計(jì)奠定了良好的基礎(chǔ)。在這里要感謝老師對(duì)我的悉心指導(dǎo),您辛苦了! 六、程序源代碼 1、建立服務(wù)器偵聽(tīng)套接字的類CListenSocket的定義與實(shí)現(xiàn) 定義部分: class CListenSocket : public Csocket//該類用于服務(wù)器端的偵聽(tīng) { public: CTcpDlg *m_pSendDlg; //加該成員為了調(diào)用其內(nèi)的函數(shù)。 public: CListenSocket(CTcpDlg *pSendDlg); virtual ~CListenSocket(); public: virtual void OnAccept(int nErrorCode); }; 實(shí)現(xiàn)部分: CListenSocket::CListenSocket(CTcpDlg *pSendDlg) { m_pSendDlg = pSendDlg; } void CListenSocket::OnAccept(int nErrorCode) //當(dāng)服務(wù)器端收到客 //戶端的連接請(qǐng)求時(shí)執(zhí)行的代碼。 { CSocket::OnAccept(nErrorCode); m_pSendDlg->ProcessAccept(); } 2、建立數(shù)據(jù)傳輸套接字的類CTransSocket的定義與實(shí)現(xiàn) 定義部分: class CTransSocket : public Csocket//該類用于兩端的連接和傳輸 { public: CTcpDlg *m_pSendDlg; public: CTransSocket(CTcpDlg *pSendDlg); virtual ~CTransSocket(); public: virtual void OnReceive(int nErrorCode); }; 實(shí)現(xiàn)部分: CTransSocket::CTransSocket(CTcpDlg *pSendDlg) { m_pSendDlg = pSendDlg; } void CTransSocket::OnReceive(int nErrorCode) //當(dāng)收到發(fā)送 //端發(fā)送的數(shù)據(jù)時(shí)執(zhí)行的代碼。 { CSocket::OnReceive(nErrorCode); m_pSendDlg->SetTip(CString("有數(shù)據(jù)傳送到")); m_pSendDlg->SendOrRecv = 2; m_pSendDlg->JudgeButton(); } 3、用于數(shù)據(jù)串行化的類CSave的定義與實(shí)現(xiàn): 定義部分: class CSave : public CObject { public: WORD m_WEnd; //標(biāo)記數(shù)據(jù)傳輸是否結(jié)束,結(jié)束-0 未結(jié)束-1 意外-2 WORD m_WNum; //標(biāo)記Bbuf[]中元素的個(gè)數(shù) BYTE Bbuf[1024]; public: CSave(); virtual ~CSave(); void Init(); virtual void Serialize(CArchive &ar); }; 實(shí)現(xiàn)部分: CSave::CSave() { Init(); } void CSave::Init() //重新定義一個(gè)Init()的原因是不僅在CSave類初始 { //化時(shí)將類內(nèi)各變量值初始狀態(tài),還可以在以后也可 int i; //以。 m_WEnd = 1; //結(jié)束標(biāo)志 for(i = 0; i < 1024; i++) Bbuf[i] = 0; } void CSave::Serialize(CArchive &ar) //數(shù)據(jù)串行化 { unsigned int i = 0; if(ar.IsStoring()) { ar << m_WEnd; ar << m_WNum; for(i = 0; i < m_WNum; i++) //數(shù)組中的值發(fā)送出 ar << Bbuf[i]; } else { i = 0; ar >> m_WEnd; ar >> m_WNum; while(i < m_WNum) //收到的值存入數(shù)組 i = ar.Read(&Bbuf[i], m_WNum - i) + i; } } 4、主對(duì)話框CTcpDlg類的定義與實(shí)現(xiàn): 定義部分: class CTcpDlg : public CDialog { 系統(tǒng)定義部分省略... public: CListenSocket *m_pListenSocket; CTransSocket *m_pTransSocket; CSocketFile *m_pFile; //用于和CSocket連接 CFile *m_pBasicFile; CArchive *m_pArchiveIn; //CSocket的兩個(gè)緩沖區(qū) CArchive *m_pArchiveOut; CString m_strFileName; //用于存儲(chǔ)文件名 int SendOrRecv; //send 1; receive 2; nothing 0; int ServerClient; //Server-1,Client-2 int iEnd; //用于控制意外中斷發(fā)送信號(hào) int m_nPort; void ProcessAccept(); void ProcessRecv(); void InitConnection(); BOOL ConnectSocket(CString strIP); void SendFile(CString strFileName, WORD WEnd = 1); int ReceiveFile(CFile *m_pBasicFile,CString strFileName, DWORD *wNum); void JudgeButton(); void SetTip(CString str); public: CTcpDlg(CWnd* pParent = NULL); // standard constructor virtual ~CTcpDlg(); 系統(tǒng)控件變量定義省略... 系統(tǒng)定義函數(shù)省略... protected: afx_msg void OnBUTTONListen(); afx_msg void OnBUTTONStop(); afx_msg void OnBUTTONConnect(); afx_msg void OnBUTTONCut(); afx_msg void OnBUTTONBrowser(); afx_msg void OnBUTTONSend(); afx_msg void OnBUTTONSave(); afx_msg void OnBUTTONRecv(); }; 實(shí)現(xiàn)部分: 系統(tǒng)定義函數(shù)實(shí)現(xiàn)省略... CTcpDlg::CTcpDlg(CWnd* pParent /*=NULL*/) : CDialog(CTcpDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_pAutoProxy = NULL; m_pListenSocket = NULL; m_pTransSocket = NULL; m_pFile = NULL; m_pArchiveIn = NULL; m_pArchiveOut = NULL; m_strFileName.Empty(); m_pBasicFile = NULL; SendOrRecv = 0; iEnd = 1; } CTcpDlg::~CTcpDlg() { if (m_pAutoProxy != NULL) m_pAutoProxy->m_pDialog = NULL; delete m_pTransSocket; m_pTransSocket = NULL; delete m_pListenSocket; m_pListenSocket = NULL; delete m_pBasicFile; m_pBasicFile = NULL; delete m_pArchiveIn; delete m_pArchiveOut; m_pArchiveIn = NULL; m_pArchiveOut = NULL; delete m_pFile; m_pFile = NULL; } BOOL CTcpDlg::OnInitDialog() { 系統(tǒng)添加部分省略... CDialog::OnInitDialog(); m_nPort = 1234; m_AddCtrl.SetAddress(192,168,0,1); JudgeButton(); SetTip(CString("初始狀態(tài)")); return TRUE; } void CTcpDlg::JudgeButton() //不時(shí)地調(diào)整各按鈕的狀態(tài) { if(m_pListenSocket == NULL && m_pTransSocket == NULL) { m_Browser.EnableWindow(TRUE); m_Listen.EnableWindow(TRUE); m_Stop.EnableWindow(FALSE); m_Connect.EnableWindow(TRUE); m_Cut.EnableWindow(FALSE); m_Send.EnableWindow(FALSE); m_Save.EnableWindow(TRUE); m_FileName.EnableWindow(TRUE); m_SaveFile.EnableWindow(TRUE); m_Recv.EnableWindow(FALSE); return; m_Recv.queque(FALSE) m_Wedive.build(FALSE) m_concent.EnableWindows(FALSE) m_agent.Forbide(TRUE) m_reduce.dosore(TRUE) } else if(m_pTransSocket != NULL) { m_Listen.EnableWindow(FALSE); m_Connect.EnableWindow(FALSE); if(ServerClient == 1) { m_Cut.EnableWindow(FALSE); m_Stop.EnableWindow(TRUE); } else { m_Cut.EnableWindow(TRUE); m_Stop.EnableWindow(FALSE); } if(SendOrRecv == 1) { m_Recv.EnableWindow(FALSE); m_FileName.EnableWindow(TRUE); m_SaveFile.EnableWindow(FALSE); m_Browser.EnableWindow(TRUE); m_Save.EnableWindow(FALSE); } else if (SendOrRecv == 2) { m_Recv.EnableWindow(TRUE); m_FileName.EnableWindow(FALSE); m_SaveFile.EnableWindow(TRUE); m_Browser.EnableWindow(FALSE); m_Save.EnableWindow(TRUE); } else { m_Recv.EnableWindow(TRUE); m_FileName.EnableWindow(TRUE); m_SaveFile.EnableWindow(TRUE); m_Browser.EnableWindow(TRUE); m_Save.EnableWindow(TRUE); } m_Send.EnableWindow(TRUE); return; } else if(m_pListenSocket != NULL) { m_Browser.EnableWindow(TRUE); m_Listen.EnableWindow(FALSE); m_Stop.EnableWindow(TRUE); m_Connect.EnableWindow(FALSE); m_Cut.EnableWindow(FALSE); m_Send.EnableWindow(FALSE); m_Save.EnableWindow(TRUE); m_FileName.EnableWindow(TRUE); m_SaveFile.EnableWindow(TRUE); m_Recv.EnableWindow(FALSE); return; } } void CTcpDlg::SetTip(CString str) //調(diào)整狀態(tài)區(qū)的文字顯示 { m_EditTip.SetWindowText(str); } void CTcpDlg::ProcessAccept() //應(yīng)答客戶端的連接請(qǐng)求 { m_pTransSocket = new CTransSocket(this); if(m_pListenSocket->Accept(*m_pTransSocket)) { InitConnection(); m_pListenSocket->Close(); delete m_pListenSocket; m_pListenSocket = NULL; JudgeButton(); SetTip(CString("有客戶端連接")); } else { delete m_pListenSocket; m_pListenSocket = NULL; delete m_pTransSocket; m_pTransSocket = NULL; JudgeButton(); SetTip(CString("連接失敗")); } } void CTcpDlg::InitConnection()//初始化CSocket緩沖區(qū)及與CSocketFile { //的連接。 m_pFile = new CSocketFile(m_pTransSocket); m_pArchiveIn = new CArchive(m_pFile, CArchive::load,256*1024); m_pArchiveOut = new CArchive(m_pFile, CArchive::store,256*1024); } void CTcpDlg::OnBUTTONListen() { // TODO: Add your control notification handler code here m_pListenSocket = new CListenSocket(this); if(m_pListenSocket->Create(m_nPort)) { if(m_pListenSocket->Listen()) { JudgeButton(); SetTip(CString("服務(wù)器已啟動(dòng)")); ServerClient = 1; iEnd = 1; return; } } delete m_pListenSocket; m_pListenSocket = NULL; JudgeButton(); SetTip(CString("服務(wù)器無(wú)法啟動(dòng)")); ServerClient = 0; } void CTcpDlg::OnBUTTONStop() { iEnd = 2; delete m_pListenSocket; m_pListenSocket = NULL; delete m_pTransSocket; m_pTransSocket = NULL; JudgeButton(); SetTip(CString("停止服務(wù)")); ServerClient = 0; } void CTcpDlg::OnBUTTONConnect() { // TODO: Add your control notification handler code here BYTE a1, a2, a3, a4; int nBlank = m_AddCtrl.GetAddress(a1,a2,a3,a4); if(nBlank < 4) return; CString strIP; strIP.Format("%d.%d.%d.%d",a1,a2,a3,a4); if(ConnectSocket(strIP)) { JudgeButton(); SetTip(CString("連接成功")); ServerClient = 2; iEnd = 1; } else { JudgeButton(); SetTip(CString("連接失敗")); ServerClient = 0; iEnd = 2; } } BOOL CTcpDlg::ConnectSocket(CString strIP) { m_pTransSocket = new CTransSocket(this); if(!m_pTransSocket->Create()) { delete m_pTransSocket; m_pTransSocket = NULL; AfxMessageBox("創(chuàng)建Socket失敗"); return FALSE; } while(!m_pTransSocket->Connect(strIP,m_nPort)) { if(AfxMessageBox("連接失??!您想重新嘗試連接嗎?",MB_YESNO) == IDNO) { delete m_pTransSocket; m_pTransSocket = NULL; return FALSE; } } InitConnection(); return TRUE; } void CTcpDlg::OnBUTTONCut() { // TODO: Add your control notification handler code here iEnd = 2; delete m_pTransSocket; m_pTransSocket = NULL; JudgeButton(); SetTip(CString("強(qiáng)制斷開(kāi)連接")); ServerClient = 0; } void CTcpDlg::ProcessRecv() //與下面的ReceiveFile()共同來(lái)接收文件 { CString str; double dNum = 0; DWORD num = 0; int end = 1; TRY { m_pBasicFile = new CFile(m_strFileName, CFile::modeWrite|CFile::modeCreate); } CATCH(CFileException, e) { #ifdef _DEBUG afxDump << "File could not be created. " << e->m_cause << "\n"; SendOrRecv = 0; delete m_pBasicFile; m_pBasicFile = NULL; #endif } END_CATCH while(end == 1) { dNum = dNum + (num * sizeof(BYTE)) / 1024.0; str.Format("正在接收文件,已接收%lfK字節(jié)", dNum); SetTip(str); end = ReceiveFile(m_pBasicFile, m_strFileName, &num); } m_pBasicFile->Close(); delete m_pBasicFile; m_pBasicFile = NULL; SendOrRecv = 1; } int CTcpDlg::ReceiveFile(CFile *pBasicFile, CString strFileName, DWORD *wNum) { SendOrRecv = 2; JudgeButton(); CSave Save; TRY { Save.Serialize(*m_pArchiveIn); pBasicFile->Write(Save.Bbuf, sizeof(BYTE) * 1024); *wNum = Save.m_WNum; } CATCH(CFileException, e) { m_pArchiveOut->Abort(); SendOrRecv = 0; } END_CATCH if(Save.m_WEnd == 0 || Save.m_WEnd == 2) { if(Save.m_WEnd == 2) { if(AfxMessageBox("對(duì)方已經(jīng)斷開(kāi)連接,文件傳輸中斷!刪除文件?",MB_YESNO) ==IDYES) pBasicFile->Remove(strFileName); SendOrRecv = 0; return(2); } else if(Save.m_WEnd == 0) { AfxMessageBox("文件傳輸完畢!"); SendOrRecv = 0; return(0); } delete m_pArchiveIn; m_pArchiveIn = NULL; } return(1); } void CTcpDlg::SendFile(CString strFileName,WORD WEnd) //發(fā)送文件 { if(m_pArchiveOut != NULL) { CString str; double dNum = 0; SendOrRecv = 1; JudgeButton(); CSave Save; Save.m_WEnd = WEnd; if(!strFileName.IsEmpty()) { TRY { m_pBasicFile = new CFile(strFileName, CFile::modeRead); } CATCH( CFileException, e ) { #ifdef _DEBUG afxDump << "File could not be opened " << e->m_cause << "\n"; SendOrRecv = 0; #endif } END_CATCH TRY { while((Save.m_WNum = m_pBasicFile->Read(Save.Bbuf,1024 * sizeof(BYTE))) != 0) { Save.m_WEnd = iEnd; Save.Serialize(*m_pArchiveOut); dNum = dNum + (Save.m_WNum * sizeof(BYTE)) / 1024.0; str.Format("正在發(fā)送文件,已發(fā)送:%lfK字節(jié)",dNum); SetTip(str); Save.Init(); m_pArchiveOut->Flush(); } Save.m_WEnd = 0; Save.Serialize(*m_pArchiveOut); delete m_pArchiveOut; m_pArchiveOut = NULL; AfxMessageBox("文件傳輸完畢!"); } CATCH(CFileException, e) { m_pArchiveOut->Abort(); delete m_pArchiveOut; m_pArchiveOut = NULL; delete m_pTransSocket; m_pTransSocket = NULL; SendOrRecv = 0; JudgeButton(); CString strTemp; strTemp.Format("服務(wù)器斷開(kāi)連接了"); SetTip(strTemp); } END_CATCH delete m_pBasicFile; m_pBasicFile = NULL; SendOrRecv = 1; } else Save.Serialize(*m_pArchiveOut); } } void CTcpDlg::OnBUTTONBrowser() { CFileDialog * BrowserDlg; BrowserDlg = new CFileDialog(TRUE); BrowserDlg->DoModal(); m_strFileName = BrowserDlg->GetPathName(); m_FileName.SetWindowText(m_strFileName); delete BrowserDlg; BrowserDlg = NULL; } void CTcpDlg::OnBUTTONSend() { m_FileName.GetWindowText(m_strFileName); if(m_strFileName.IsEmpty()) { OnBUTTONBrowser(); } SendFile(m_strFileName,iEnd); } void CTcpDlg::OnBUTTONSave() { CFileDialog * SaveDlg; SaveDlg = new CFileDialog(FALSE); SaveDlg->DoModal(); m_strFileName = SaveDlg->GetPathName(); m_SaveFile.SetWindowText(m_strFileName); delete SaveDlg; SaveDlg = NULL; } void CTcpDlg::OnBUTTONRecv() { m_SaveFile.GetWindowText(m_strFileName); if(m_strFileName.IsEmpty()) OnBUTTONSave(); ProcessRecv(); } 七、參考文獻(xiàn) 《Visual C++ 6.0編程實(shí)例精解》 北京希望電子出版社 蘭蕓編著 《網(wǎng)絡(luò)編程》 西安理工大學(xué)計(jì)算機(jī)學(xué)院- 1.請(qǐng)仔細(xì)閱讀文檔,確保文檔完整性,對(duì)于不預(yù)覽、不比對(duì)內(nèi)容而直接下載帶來(lái)的問(wèn)題本站不予受理。
- 2.下載的文檔,不會(huì)出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請(qǐng)點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
9.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁(yè)顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開(kāi)word文檔。
- 特殊限制:
部分文檔作品中含有的國(guó)旗、國(guó)徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對(duì)作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- 計(jì)算機(jī)網(wǎng)絡(luò) 通信 程序設(shè)計(jì) TCP 文件傳輸 程序
鏈接地址:http://www.820124.com/p-6692245.html