基于TCP的簡單一對一聊天程序設(shè)計_第1頁
基于TCP的簡單一對一聊天程序設(shè)計_第2頁
基于TCP的簡單一對一聊天程序設(shè)計_第3頁
基于TCP的簡單一對一聊天程序設(shè)計_第4頁
基于TCP的簡單一對一聊天程序設(shè)計_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

一、課程設(shè)計題目:通過套接字連接進(jìn)行一對一聊天通信二、實驗要求:實現(xiàn)一個一對一的聊天程序。根本過程如下:效勞器首先啟動,創(chuàng)立套接字后等待客戶的連接;客戶啟動以后,創(chuàng)立套接字,然后和效勞器建立連接;連接建立后,客戶機(jī)和效勞器可以通過建立的套接字連接進(jìn)行通信。效勞器和客戶端可以是一臺電腦的兩個進(jìn)程,也可以分別部署在兩臺電腦上。三、原理概述:套接字Socket是一種雙向的通信接口,可以通過這個端口與任何一個具有Socket端口的計算機(jī)通信,套接字是網(wǎng)絡(luò)通信的根底。Socket在Windows以句柄的形式被創(chuàng)立。使用Socket進(jìn)行網(wǎng)絡(luò)通信必須包含下面的幾種信息:雙方認(rèn)可的協(xié)議,本地主機(jī)的IP地址,本地進(jìn)程的協(xié)議端口,對方主機(jī)的IP地址,對方進(jìn)程的協(xié)議端口。Socket可分為:1數(shù)據(jù)報套接字〔DatagramSockets〕——對于在TCP/IP上實現(xiàn)的WinSock,數(shù)據(jù)報套接字使用用戶數(shù)據(jù)報協(xié)議〔UDP〕。數(shù)據(jù)報套接字提供了一種不可靠的、非連接的數(shù)據(jù)包通信方式。2流式套接字〔StreamSockets〕——流式套接字使用傳輸控制協(xié)議〔TCP〕。流式套接字可以將數(shù)據(jù)按順序無重復(fù)地發(fā)送到目的地,它提供的是一種可靠的、面向連接的數(shù)據(jù)傳輸方式。不管是對單個的數(shù)據(jù)報,還是對數(shù)據(jù)包,流式套接字都提供了一種流式數(shù)據(jù)傳輸。VC++對網(wǎng)絡(luò)編程的支持有socket支持,Winlnet支持,MAPI和ISAPI支持等。其中WindowsSocketsAPI是TCP/IP網(wǎng)絡(luò)環(huán)境里,也是Internet上進(jìn)行開發(fā)最為通用的API。IP地址:IPAddress就是依照TCP/IP協(xié)議分配給本地主機(jī)的網(wǎng)絡(luò)地址,就向兩個進(jìn)程要通訊,任一進(jìn)程要知道通訊對方的位置,位置如何來確定,就用對方的IP端口號:用來標(biāo)識本地通訊進(jìn)程,方便OS提交數(shù)據(jù).就是說進(jìn)程指定了對方進(jìn)程的網(wǎng)絡(luò)IP,但這個IP只是用來標(biāo)識進(jìn)程所在的主機(jī),如何來找到運行在這個主機(jī)的這個進(jìn)程呢,就用端口號.連接:指兩個進(jìn)程間的通訊鏈路.一個完整的網(wǎng)間進(jìn)程通信需要由兩個進(jìn)程組成,并且只能使用同一種高層協(xié)議。也就是說,不可能通信的一端用TCP協(xié)議,而另一端用UDP協(xié)議。因此一個完整的網(wǎng)間通信需要一個五元組來標(biāo)識:協(xié)議,本地地址,本地端口號,遠(yuǎn)地地址,遠(yuǎn)地端口號這樣一個五元組,叫做一個相關(guān)association,即兩個協(xié)議相同的半相關(guān)才能組合成一個適宜的相關(guān),或完全指定組成一連接。在TCP/IP網(wǎng)絡(luò)應(yīng)用中,通信的兩個進(jìn)程間相互作用的主要模式是客戶/效勞器模式(Client/Servermodel),即客戶向效勞器發(fā)出效勞請求,效勞器接收到請求后,提供相應(yīng)的效勞??蛻?效勞器模式的建立基于以下兩點:首先,建立網(wǎng)絡(luò)的起因是網(wǎng)絡(luò)中軟硬件資源、運算能力和信息不均等,需要共享,從而造就擁有眾多資源的主機(jī)提供效勞,資源較少的客戶請求效勞這一非對等作用。其次,網(wǎng)間進(jìn)程通信完全是異步的,相互通信的進(jìn)程間既不存在父子關(guān)系,又不共享內(nèi)存緩沖區(qū),因此需要一種機(jī)制為希望通信的進(jìn)程間建立聯(lián)系,為二者的數(shù)據(jù)交換提供同步,這就是基涌紀(jì)紀(jì)戶/效勞器模式的TCP/IP。四.設(shè)計方案:設(shè)計原理圖:解決方案基于TCP連接Socket聊天程序基于該連接的聊天程序需要至少具備一個效勞器端〔Server〕和一個客戶端〔Client〕。在本程序中,一個用戶作為Server端,另一個用戶作為Client端。也就是說,作為Server端的用戶,需要首先啟動程序,等待Client端的連接請求。當(dāng)TCP連接握手以后,雙方方可進(jìn)行交互。在本程序中Server端并不是單獨存在。它也可以向他的Client端發(fā)送消息。當(dāng)Client端與Server端握手以后,Server端需要首先發(fā)起會話;Client端在收到消息后再回復(fù)一條消息給Server端;同樣,Server端在收到消息后再回復(fù)一條消息給Client端……以此類推。五.程序編寫:Server.h代碼如下:#include<Afxwin.h>#include<stdio.h>#include<winsock2.h>#include<conio.h>#include<list>#include<iostream>usingnamespacestd;classCChatServer{public: CChatServer(); ~CChatServer(); boolIsConnected(){returnm_bIsConnected;}//返回連接狀態(tài) voidStartListenClient();//Listentoclient intSendMessagePort(stringsMessage);//向所有客戶端發(fā)消息 intRecClient(SOCKETsRecSocket);//接收客戶端數(shù)據(jù)private: boolm_bIsConnected;//true-connectedfalse-notconnected intm_iServerPort; list<SOCKET>m_vClientList;//Allsocketconnectedtoclient SOCKETm_SClient; SOCKETm_SListenClient;//socketlisteningforclientcalls};Server.cpp代碼如下:#include"server.h"CChatServerCServerObj;UINTServerRecThread(LPVOIDpParam)//接收數(shù)據(jù)的工作線程{ SOCKETsRecSocket=(SOCKET)pParam; while(1) { if(CServerObj.RecClient(sRecSocket)) break; } return0;}UINTServerListenThread(LPVOIDpParam)//監(jiān)聽端口建立連接的工作線程{ while(1) CServerObj.StartListenClient(); return0;}CChatServer::CChatServer()//對象CChatServer的構(gòu)造函數(shù){cout<<"StartingupTCPChatserver\n"; m_bIsConnected=false;WSADATAwsaData;sockaddr_inlocal;intwsaret=WSAStartup(0x101,&wsaData);//應(yīng)用程序調(diào)用的第一個WindowsSockets函數(shù).//它允許應(yīng)用程序或DLL指明WindowsSocketsAPI的版本號及獲得特定WindowsSockets實現(xiàn)的細(xì)節(jié).if(wsaret!=0){return;}local.sin_family=AF_INET;local.sin_addr.s_addr=INADDR_ANY;local.sin_port=htons((u_short)8084);m_SListenClient=socket(AF_INET,SOCK_STREAM,0);//創(chuàng)立一個套接字,返回套接字描述字if(m_SListenClient==INVALID_SOCKET){return;}if(bind(m_SListenClient,(sockaddr*)&local,sizeof(local))!=0)//把本地協(xié)議的地址賦予一個套接字{return;}if(listen(m_SListenClient,10)!=0)//監(jiān)聽該端口{return;} m_bIsConnected=true;return;}CChatServer::~CChatServer()//對象CChatServer的析構(gòu)函數(shù){closesocket(m_SListenClient);//關(guān)閉該端口WSACleanup();}voidCChatServer::StartListenClient(){sockaddr_infrom;intfromlen=sizeof(from);m_SClient=accept(m_SListenClient,(structsockaddr*)&from,&fromlen);//產(chǎn)生與客戶進(jìn)行TCP連接通信的套接字并返回已連接客戶端的協(xié)議地址 if(m_SClient!=INVALID_SOCKET) m_vClientList.push_back(m_SClient); AfxBeginThread(ServerRecThread,(void*)m_SClient);//啟動接收線程,用m_SClient套接字與客戶端通話}intCChatServer::SendMessagePort(stringsMessage)//向各個客戶端發(fā)送效勞器數(shù)據(jù){ intiStat=0; list<SOCKET>::iteratoritl; if(m_vClientList.size()==0) return0; for(itl=m_vClientList.begin();itl!=m_vClientList.end();itl++) { iStat=send(*itl,sMessage.c_str(),sMessage.size()+1,0); if(iStat==-1) m_vClientList.remove(*itl); } if(iStat==-1) return1; return0;}intCChatServer::RecClient(SOCKETsRecSocket)//接收客戶端數(shù)據(jù)成員函數(shù){chartemp[4096]; intiStat; iStat=recv(sRecSocket,temp,4096,0); if(iStat==-1) { m_vClientList.remove(sRecSocket); return1; } else { cout<<":"<<temp<<"\n"; SendMessagePort(temp); return0; } return0;}intmain(intargc,char*argv[]){intnRetCode=0; charbuf[4096]; cout<<"Thisaplicationactasachatserver.\n"; cout<<"Messagesfromanypcwillbebroadcastedtoallconnectedpcs.\n"; cout<<"Connecttotheserverpcport8084\n";cout<<"PressONLYENTERtoquit.\n"; cout<<"=================================================\n"; if(!CServerObj.IsConnected())//判斷監(jiān)聽端口是否建立 { cout<<"\nFailedtoinitialiseserversocket"; cout<<"\nBye"; getch(); return1; } AfxBeginThread(ServerListenThread,0);//啟動監(jiān)聽端口建立連接的工作線程 while(gets(buf)) { if(strlen(buf)==0) break; if(CServerObj.SendMessagePort(buf)) { cout<<"Probleminconnectingtoserver.Checkwhetherserverisrunning\n"; break; } } cout<<"readytoseegoodbye:"; getch();returnnRetCode;}Client.h#include<Afxwin.h>#include<stdio.h>#include<winsock2.h>#include<conio.h>#include<iostream>usingnamespacestd;classCIPMessage{public: CIPMessage(); ~CIPMessage(); voidInit(stringsIpAddress,intiPort); intSendMessagePort(stringsMessage); intRecMessagePort(); boolIsConnected(){returnm_bIsConnected;}private: boolm_bIsConnected;//true-connectedfalse-notconnected stringm_sServerIPAddress; intm_iServerPort; SOCKETconn;//socketconnectedtoserver};Client.cpp代碼如下:#include"client.h"http://GlobalMessageobjectCIPMessageMyMessObj;CIPMessage::CIPMessage()//MyMessObj構(gòu)造函數(shù){ m_bIsConnected=false;}voidCIPMessage::Init(stringsIpAddress,intiPort)//建立與效勞器端得連接{ m_sServerIPAddress=sIpAddress; m_iServerPort=iPort; structhostent*hp; unsignedintaddr; structsockaddr_inserver; WSADATAwsaData; intwsaret=WSAStartup(0x101,&wsaData);//應(yīng)用程序調(diào)用的第一個WindowsSockets函數(shù).//它允許應(yīng)用程序或DLL指明WindowsSocketsAPI的版本號及獲得特定WindowsSockets實現(xiàn)的細(xì)節(jié). if(wsaret!=0) { return; } conn=socket(AF_INET,SOCK_STREAM,0);//建立客戶端套接字 if(conn==INVALID_SOCKET) return; addr=inet_addr(m_sServerIPAddress.c_str());//轉(zhuǎn)化ip地址和端口為指定形式 hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET); if(hp==NULL) { closesocket(conn); return; } server.sin_addr.s_addr=*((unsignedlong*)hp->h_addr); server.sin_family=AF_INET; server.sin_port=htons(m_iServerPort); if(connect(conn,(structsockaddr*)&server,sizeof(server)))//向指定效勞器建立連接 { closesocket(conn); return; } m_bIsConnected=true; return;}CIPMessage::~CIPMessage()//MyMessObj析構(gòu)函數(shù){ if(m_bIsConnected) closesocket(conn);}intCIPMessage::SendMessagePort(stringsMessage)//向指定效勞器發(fā)出數(shù)據(jù){ intiStat=0; iStat=send(conn,sMessage.c_str(),sMessage.size()+1,0); if(iStat==-1) return1; return0;}intCIPMessage::RecMessagePort()//接收指定效勞器數(shù)據(jù){ characRetData[4096]; intiStat=0; iStat=recv(conn,acRetData,4096,0); if(iStat==-1) return1; cout<<"-->:"<<acRetData<<"\n"; return0;}UINTMessageRecThread(LPVOIDpParam)//接收指定效勞器數(shù)據(jù)線程{ while(1) { if(MyMessObj.RecMessagePort()) break; } return0;}intmain(intargc,char*argv[]){ charbuf[4096]; cout<<"ThisisaclientTCP/IPapplication\nConnectingtoport8084\n"; cout<<"\nPressONLYENTERtoquit"; cout<<"\n===============================================\n"; FILE*fp=fopen("server.ini","r");//獲取效勞器端套接字地址 if(fp==NULL) { cout<<"\nUnabletoopenserver.ini.PleasespecifyserverIPsddressinserver.ini"; return1;//mainfailed } stringsServerAddress; while((fgets(buf,4096,fp))!=NULL) { if(buf[0]=='#') continue; sServerAddress=buf; } fclose(fp); if(sServerAddress.size()==0) { cout<<"\nUnabletofindserverIPaddressinserver.ini"; cout<<"\nPleasesetserverIPaddress"; cout<<"\nBYEBYE:"; getch(); return0; } MyMessObj.Init(sServerAddress.c_str(),8084);//啟動與效勞器連接 if(!MyMessObj.IsConnected()) { cout<<"\nUnabletoconnecttotheIPaddressspecifiedinserver.ini"; cout<<"\nPleasecheckserverIPaddress"; cout<<"\nreadytoseegoodbye:"; getch(); return0; } AfxBeginThread(MessageRecThread,0);//開啟接收數(shù)據(jù)線程 while(ge

溫馨提示

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

評論

0/150

提交評論