网络编程实验(5)实验报告--王笑晗
- 格式:doc
- 大小:173.50 KB
- 文档页数:27
实验3 Winsock I/O模型的使用姓名:刘方华学号:110420214 班级:1104202一、实验环境:vc++ 6.0二、实验内容:1.设计思路1. 编写一个基于流式套接字的C/S通信程序,客户端与服务器建立连接之后,客户端向服务器发送一个简单的四则算式(只含一个算符),服务器收到这个算式后,对其进行计算,并将计算结果回送给客户端,客户端将计算结果显示出来。
要求:(1)服务器可以同时为多个客户提供服务。
(2)采用select模型实现。
2. 对于实验1的回射服务器采用select模型改写。
3.实现一聊天程序,要求采用WSAAyncSelect(异步选择)模型实现。
2.程序清单(要求有详细的注释)1.1客户端1:#include<iostream>#include<winsock2.h>using namespace std ;#define DEFAULT_PORT 4000 //默认端口号DWORD WINAPI ThreadFunc(LPVOID pParam); //客户端socket接收线程函数char info[255]; //控制台输入字符串void main(){WORD wVersionRequested=MAKEWORD(2,2); //初始化WinsockWSADATA wsaData;WSAStartup(wVersionRequested,&wsaData); //加载winsock库SOCKET sClntSock;sockaddr_in addr;sockaddr_in ServAddr;int nSockErr;// sClntSock=socket(AF_INET,SOCK_DGRAM,0);sClntSock=socket(AF_INET,SOCK_STREAM,0);addr.sin_family=AF_INET;addr.sin_port=0;addr.sin_addr.s_addr=htonl(INADDR_ANY);//绑定套接字到一个已知地址if(bind(sClntSock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR)nSockErr=WSAGetLastError();ServAddr.sin_family=AF_INET;ServAddr.sin_port=htons(DEFAULT_PORT);cout<<"Please input the ip of server:";char add_ip[50];cin>>add_ip;char dummy;cin.get(dummy);ServAddr.sin_addr.s_addr=inet_addr(add_ip);//连接服务器if(connect(sClntSock,(const sockaddr*)(&ServAddr),sizeof(ServAddr))==SOCKET_ERROR) {nSockErr=WSAGetLastError();}else cout<<"*****************Connect successful.****************"<<endl;//创建socket接收线程CreateThread(NULL,0,ThreadFunc,&sClntSock,0,NULL);//接收控制台输入并作相应操作cout << ">";cin.getline(info,255);while(strcmp(info,"bye")){send(sClntSock,info,255,0);cout << ">";cin.getline(info,255);}}//线程函数,接收网络消息DWORD WINAPI ThreadFunc(LPVOID pParam){SOCKET *s=(SOCKET *)pParam;char in[255];while(strcmp(info,"bye")) //退出{if(recv(*s,in,255,0)!=SOCKET_ERROR) //接收消息{cout << "\b" << in << endl << ">";cout.flush();}else//出错,可能服务器死机{cout<<"*****************Server Down*****************"<<endl;exit(0);}}return 0;}1.2 客户端2:#include<iostream>#include<winsock2.h>using namespace std;#pragma comment (lib,"ws2_32.lib")#define DEFAULT_PORT 4000 //默认端口号DWORD WINAPI ThreadFunc(LPVOID pParam); //客户端socket接收线程函数char info[255]; //控制台输入字符串void main(){WORD wVersionRequested=MAKEWORD(2,2); //初始化WinsockWSADATA wsaData;WSAStartup(wVersionRequested,&wsaData); //加载winsock库SOCKET sClntSock;sockaddr_in addr;sockaddr_in ServAddr;int nSockErr;// sClntSock=socket(AF_INET,SOCK_DGRAM,0);sClntSock=socket(AF_INET,SOCK_STREAM,0);addr.sin_family=AF_INET;addr.sin_port=0;addr.sin_addr.s_addr=htonl(INADDR_ANY);//绑定套接字到一个已知地址if(bind(sClntSock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR) nSockErr=WSAGetLastError();ServAddr.sin_family=AF_INET;ServAddr.sin_port=htons(DEFAULT_PORT);cout<<"Please input the ip of server:";char add_ip[50];cin>>add_ip;char dummy;cin.get(dummy);ServAddr.sin_addr.s_addr=inet_addr(add_ip);//连接服务器if(connect(sClntSock,(const sockaddr*)(&ServAddr),sizeof(ServAddr))==SOCKET_ERROR) {nSockErr=WSAGetLastError();}else cout<<"*****************Connect successful.****************"<<endl;//创建socket接收线程CreateThread(NULL,0,ThreadFunc,&sClntSock,0,NULL);//接收控制台输入并作相应操作cout << ">";cin.getline(info,255);while(strcmp(info,"bye")){send(sClntSock,info,255,0);cout << ">";cin.getline(info,255);}}//线程函数,接收网络消息DWORD WINAPI ThreadFunc(LPVOID pParam){SOCKET *s=(SOCKET *)pParam;char in[255];while(strcmp(info,"bye")) //退出{if(recv(*s,in,255,0)!=SOCKET_ERROR) //接收消息{cout << "\b" << in << endl << ">";cout.flush();}else//出错,可能服务器死机{cout<<"*****************Server Down*****************"<<endl;exit(0);}}return 0;}1.3 服务器端:#include<iostream>#include<winsock2.h>using namespace std;#pragma comment (lib,"ws2_32.lib")#define DEFAULT_PORT 4000 //默认端口号void WINAPI SendOut();char info[255]; //服务器端控制台输入字符串//是否有客户端连接fd_set fds;SOCKET sServSock;int main(){WORD wVersionRequested=MAKEWORD(2,2); //初始化WinsockWSADATA wsaData;WSAStartup(wVersionRequested,&wsaData); //加载winsock库sServSock=socket(AF_INET,SOCK_STREAM,0);sockaddr_in addr;int nSockErr;SOCKET sClient;sockaddr ConnAddr;int nAddrLen=sizeof(sockaddr);addr.sin_family=AF_INET;addr.sin_port=htons(DEFAULT_PORT);addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//绑定套接字到一个已知地址if(bind(sServSock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR)nSockErr=WSAGetLastError();FD_ZERO(&fds);/*&*/FD_SET(sServSock,&fds);/*&*///将套接字置入监听模式if (listen(sServSock,5)==SOCKET_ERROR)nSockErr=WSAGetLastError();cout << "*****************Wait Client to Connect**********************" << endl;/*&*/bool bRunning=true;do {fd_set readfds;CopyMemory(&readfds,&fds,sizeof(fd_set));if(select(0,&readfds,NULL,NULL,NULL)>0){for(int i=readfds.fd_count-1;i>=0;i--)/* 顺序处理每一个有事件发生的套接字*/if(readfds.fd_array[i]==sServSock){sClient=accept(sServSock,&ConnAddr,&nAddrLen);if(sClient==INVALID_SOCKET){bRunning=false;break;}cout<<"One of the Clients Accept Successful"<<endl;FD_SET(sClient,&fds); /* 将与新客户端对应的套接字加入select函数监视的集合*/CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendOut,NULL,0,NULL);//发送数据}else// 与客户端对应的套接字有事件发生说明有数据需要接收{char in[255];SOCKET sClient=readfds.fd_array[i];if(recv(sClient,in,255,0)!=SOCKET_ERROR)cout<<"\b<"<<in<<endl<<">";else{cout<<"\b<"<<"client exit"<<endl<<">";FD_CLR(sClient,&fds);// 将该套接字移出select函数监视的集合 closesocket(sClient);}}}} while(bRunning);WSACleanup();/*&*/return 0;}//服务器发送函数void WINAPI SendOut(){do {cin.getline(info,255);if(!strcmp(info,"bye")) break;cout<<">";for(int i=fds.fd_count-1;i>=0;i--)if( fds. fd_array [i]!=sServSock){fd_set writefds;FD_ZERO (&writefds);FD_SET(fds.fd_array[i],&writefds);if(select(0,NULL,&writefds,NULL,NULL)>0)send(fds.fd_array[i],info,255,0);}} while(true);closesocket(sServSock);}2.1 聊天程序服务器端:#include"stdafx.h"#include"ChatServer.h"#include"ChatServerDlg.h"#include"PortDlg.h"#include"Msg.h"#ifdef_DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{public:CAboutDlg();// Dialog Data//{{AFX_DATA(CAboutDlg)enum { IDD = IDD_ABOUTBOX };//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected://{{AFX_MSG(CAboutDlg)//}}AFX_MSGDECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){//{{AFX_DATA_INIT(CAboutDlg)//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAboutDlg)//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)//{{AFX_MSG_MAP(CAboutDlg)// No message handlers//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CChatServerDlg dialogCChatServerDlg::CChatServerDlg(CWnd* pParent/*=NULL*/): CDialog(CChatServerDlg::IDD, pParent){//{{AFX_DATA_INIT(CChatServerDlg)// NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);m_pSocket=NULL;}void CChatServerDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CChatServerDlg)DDX_Control(pDX, IDC_STATIC_PORT, m_StaPort);DDX_Control(pDX, IDC_STATIC_NUMBER, m_StaNumber);DDX_Control(pDX, IDC_STATIC_MESSAGE, m_StaMessage);DDX_Control(pDX, IDC_LIST_MSG, m_ListMsg);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CChatServerDlg, CDialog)//{{AFX_MSG_MAP(CChatServerDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_WM_DESTROY()ON_BN_CLICKED(IDOK, OnStopServer)ON_BN_CLICKED(IDC_BTN_START, OnBtnStart)//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CChatServerDlg message handlersBOOL CChatServerDlg::OnInitDialog(){CDialog::OnInitDialog();ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}SetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small iconreturn TRUE; // return TRUE unless you set the focus to a control}void CChatServerDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.void CChatServerDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}// The system calls this to obtain the cursor to display while the user drags// the minimized window.HCURSOR CChatServerDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}void CChatServerDlg::OnDestroy(){CDialog::OnDestroy();delete m_pSocket;m_pSocket = NULL;CString strTemp;strTemp = "the serveice is stoped";m_msgList.AddTail(strTemp);//deal with the connection listwhile(!m_connectionList.IsEmpty()){//send message to all the client and shut up the servise one by anotherCClientSocket* pSocket = (CClientSocket*) m_connectionList.RemoveHead();CMsg* pMsg = AssembleMsg(pSocket);pMsg->m_bClose = TRUE;SendMsg(pSocket,pMsg);if(!pSocket->IsAborted()){pSocket->ShutDown();BYTE Buffer[50];while(pSocket->Receive(Buffer,50)>0);delete pSocket;}}m_msgList.RemoveAll();// TODO: Add your message handler code here}void CChatServerDlg::UpdateClients(){for(POSITION pos = m_connectionList.GetHeadPosition();pos!= NULL;){CClientSocket* pSocket = (CClientSocket*) m_connectionList.GetNext(pos);CMsg* pMsg = AssembleMsg(pSocket);if(pMsg != NULL){SendMsg(pSocket,pMsg);}}}void CChatServerDlg::OnAccept(){CClientSocket* pSocket = new CClientSocket(this);// AfxMessageBox(" Ther server is created a socket for the client\nSuccess!");if(m_pSocket->Accept(*pSocket)){pSocket->Initialize();m_connectionList.AddTail(pSocket);}elsedelete pSocket;}void CChatServerDlg::OnReceive(CClientSocket* pSocket){do{CMsg* pMsg = ReadMsg(pSocket);if(pMsg->m_bClose){DeleteSocket(pSocket);break;}}while(!pSocket->m_pArchiveIn->IsBufferEmpty());UpdateClients();}// analsy the sequence of message listCMsg* CChatServerDlg::AssembleMsg(CClientSocket* pSocket){static CMsg msg;msg.Init();//客户机的消息列表无需更新if (pSocket->m_nMsgCount>=m_msgList.GetCount())return NULL;//客户机的消息列表需要更新for (POSITION pos=m_msgList.FindIndex(pSocket->m_nMsgCount);pos!=NULL;) {//将缺少的消息增加到消息列表最后CString strTemp=m_msgList.GetNext(pos);msg.m_msgList.AddTail(strTemp);}pSocket->m_nMsgCount=m_msgList.GetCount();UpdateInfo();return& msg;}CMsg* CChatServerDlg::ReadMsg(CClientSocket* pSocket){static CMsg msg;TRY{pSocket->ReceiveMessage(&msg);DisplayMsg(msg.m_strText);m_msgList.AddTail(msg.m_strText);//DisplayMessage}CATCH(CFileException,e){CString strTemp;strTemp = "reading error";msg.m_bClose= TRUE;pSocket->Abort();}END_CATCHreturn &msg;}void CChatServerDlg::SendMsg(CClientSocket* pSocket,CMsg* pMsg){TRY{pSocket->SendMessage(pMsg);}CATCH(CFileException,e){pSocket->Abort();CString strTemp;strTemp = "sending information error";DisplayMsg(strTemp);}END_CATCH}void CChatServerDlg::DeleteSocket(CClientSocket* pSocket){pSocket->Close();POSITION pos,temp;for (pos=m_connectionList.GetHeadPosition();pos!=NULL;){//对于已经关闭的客户机//在消息列表中将已经建立的连接删除temp=pos;CClientSocket* pSock=(CClientSocket*)m_connectionList.GetNext(pos);//匹配成功if (pSock==pSocket){m_connectionList.RemoveAt(temp);UpdateInfo();break;}}delete pSocket;}void CChatServerDlg::DisplayMsg(LPCTSTR lpszMessage){m_ListMsg.AddString(lpszMessage);UpdateInfo();}void CChatServerDlg::UpdateInfo(){CString strTemp;strTemp.Format("ON LINE: %d",m_connectionList.GetCount());m_StaNumber.SetWindowText(strTemp);strTemp.Format("information: %d",m_msgList.GetCount());m_StaMessage.SetWindowText(strTemp);}void CChatServerDlg::OnStopServer(){CDialog::OnOK();}void CChatServerDlg::OnBtnStart(){CPortDlg dlg;// AfxMessageBox("show a CPortdlg dialog!");//调用对话框接受用户的设置if(dlg.DoModal() == IDOK){m_pSocket = new CListeningSocket(this);// ASSERT(m_pSocket);// AfxMessageBox("the server is creating a listeningSocket\n success");//get the communication portif(m_pSocket->Create(dlg.m_nPort)){CString strTemp;strTemp.Format("Port No. %4d",dlg.m_nPort);m_StaPort.SetWindowText(strTemp);if(! m_pSocket->Listen()){AfxMessageBox("failed in listening");CDialog::OnOK();return;}}}}2.2 聊天程序客户端:// ClientDlg.cpp : implementation file//#include"stdafx.h"#include"ChatClient.h"#include"ClientDlg.h"#include"ConfigDlg.h"#include"ChatSocket.h"#include"Msg.h"#ifdef_DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{public:CAboutDlg();// Dialog Data//{{AFX_DATA(CAboutDlg)enum { IDD = IDD_ABOUTBOX };//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected://{{AFX_MSG(CAboutDlg)//}}AFX_MSGDECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){//{{AFX_DATA_INIT(CAboutDlg)//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAboutDlg)//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)//{{AFX_MSG_MAP(CAboutDlg)// No message handlers//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CClientDlg dialogCClientDlg::CClientDlg(CWnd* pParent/*=NULL*/): CDialog(CClientDlg::IDD, pParent){//{{AFX_DATA_INIT(CClientDlg)m_strMsg = _T("");//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CClientDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CClientDlg)DDX_Control(pDX, IDC_LIST_MSG, m_ListMsg);DDX_Text(pDX, IDC_EDIT_MSG, m_strMsg);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CClientDlg, CDialog)//{{AFX_MSG_MAP(CClientDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDOK, OnSend)ON_WM_DESTROY()ON_BN_CLICKED(ID_LOGIN, OnLogin)//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CClientDlg message handlersBOOL CClientDlg::OnInitDialog(){CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization herereturn TRUE; // return TRUE unless you set the focus to a control}void CClientDlg::OnSysCommand(UINT nID, LPARAM lParam)if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model,// this is automatically done for you by the framework.void CClientDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}// The system calls this to obtain the cursor to display while the user drags // the minimized window.HCURSOR CClientDlg::OnQueryDragIcon()return (HCURSOR) m_hIcon;}void CClientDlg::OnDestroy(){CDialog::OnDestroy();m_bAutoChat = FALSE;if((m_pSocket != NULL)&& (m_pFile != NULL) && (m_pArchiveOut != NULL) ) {// send the message of client leaving the chatting roomCMsg msg;CString strTemp;strTemp = ": leaving the chatting room!";msg.m_bClose = TRUE;msg.m_strText = m_strHandle + strTemp;msg.Serialize(*m_pArchiveOut);m_pArchiveOut->Flush();}delete m_pArchiveOut;m_pArchiveOut = NULL;delete m_pArchiveIn;m_pArchiveIn = NULL;delete m_pFile;m_pFile = NULL;if(m_pSocket != NULL){BYTE Buffer[50];m_pSocket->ShutDown();while(m_pSocket->Receive(Buffer,50)>0);}delete m_pSocket;m_pSocket = NULL;}void CClientDlg::OnSend(){UpdateData(TRUE);if(!m_strMsg.IsEmpty()){this->SendMsg(m_strMsg);m_strMsg = _T("");UpdateData(FALSE);}}BOOL CClientDlg::ConnectSocket(LPCTSTR lpszHandle,LPCTSTR lpszAddress,UINT nPort) {m_strHandle = lpszHandle;m_pSocket = new CChatSocket(this);if(!m_pSocket ->Create()){//deal with errordelete m_pSocket;m_pSocket = NULL;AfxMessageBox("Error in creating the socket");return FALSE;}while(!m_pSocket->Connect(lpszAddress,nPort)){//could not get connectionif(AfxMessageBox("CANNOT CONNECT TO THE SERVER \n RETRY?",MB_YESNO) == IDNO){// DEAL WITH ERRORdelete m_pSocket;m_pSocket = NULL;return FALSE;}}//create the CSocketFile class object;m_pFile = new CSocketFile(m_pSocket);m_pArchiveIn = new CArchive(m_pFile,CArchive::load);m_pArchiveOut = new CArchive(m_pFile,CArchive::store);//send message indicates the client has entered the chatting roomCString strTemp;strTemp = "enter the chatting room";SendMsg(strTemp);return TRUE;}void CClientDlg::OnReceive(){do{// receive messageReceiveMsg();if(m_pSocket == NULL)return;}while(!m_pArchiveIn->IsBufferEmpty());}void CClientDlg::SendMsg(CString & strText){if(m_pArchiveOut != NULL){CMsg msg;msg.m_strText = m_strHandle + _T(":") + strText;TRY{msg.Serialize(*m_pArchiveOut);m_pArchiveOut->Flush();}CATCH(CFileException,e){m_bAutoChat = FALSE;m_pArchiveOut ->Abort();delete m_pArchiveOut;m_pArchiveOut = NULL;CString strTemp;strTemp= "服务器重置连接";DisplayMsg(strTemp);}END_CATCH}}void CClientDlg::ReceiveMsg()CMsg msg;TRY{msg.Serialize(*m_pArchiveIn);while(!msg.m_msgList.IsEmpty()){CString strTemp;strTemp = msg.m_msgList.RemoveHead();DisplayMsg(strTemp);}}CATCH(CFileException , e){m_bAutoChat = FALSE;msg.m_bClose = TRUE;m_pArchiveOut ->Abort();CString strTemp;strTemp= "服务器重置连接";DisplayMsg(strTemp);strTemp= "连接 shut up";DisplayMsg(strTemp);}END_CATCHif(msg.m_bClose){delete m_pArchiveOut;m_pArchiveOut = NULL;delete m_pArchiveIn;m_pArchiveIn = NULL;delete m_pFile;m_pFile = NULL;delete m_pSocket;m_pSocket = NULL;}}void CClientDlg::DisplayMsg(LPCTSTR lpszText){m_ListMsg.AddString(lpszText);}void CClientDlg::OnLogin(){CConfigDlg dlg;while(TRUE){//调用对话框接受用户的设置if(dlg.DoModal() != IDOK){CDialog::OnOK();return ;}// 获得设置,向服务器发送请求if(ConnectSocket(dlg.m_strHandle,dlg.m_strServer,dlg.m_nPort)){GetDlgItem(ID_LOGIN)->EnableWindow(FALSE);return ;}if(AfxMessageBox("Try other address,please !",MB_YESNO) == IDNO){CDialog::OnOK();return;}}}3.用户使用说明(输入/ 输出规定)1.当客户输入“q”后退出2. 输入次数应当多一点,确保不同类型的输入3. 要输入符合规范的IP地址4.运行结果(要求截图)1.1. 客户端1连接成功:1.2.客户端2连接成功:1.3 服务器连接成功:1.4 进行计算客户端:1.5 进行计算服务器端:2.1 服务器端:2.2 客户端一号和二号:第一个客户端:第二个客户端:。