使用CAsyncSocket类进行网络编程

来源:互联网 发布:php开源电商系统源码 编辑:程序博客网 时间:2024/06/06 07:04

1 服务器端

由先得专门为服务器端做一个Socket通信类CNewSocket类,此类继承CAsyncSocket类,专门负责服务器端socket通信事情:

NewSocket.h:

[cpp] view plain copy
  1. #pragma once  
  2. #include "afxsock.h"  
  3. //此类专门用来与客户端进行socket通信  
  4. class CNewSocket :  
  5.     public CAsyncSocket  
  6. {  
  7. public:  
  8.     CNewSocket(void);  
  9.     ~CNewSocket(void);  
  10.     virtual void OnReceive(int nErrorCode);  
  11.     virtual void OnSend(int nErrorCode);  
  12.     // 消息长度  
  13.     UINT m_nLength;  
  14.     //消息缓冲区  
  15.     char m_szBuffer[4096];  
  16. };  

对应实现代码如下:

NewSocket.cpp:

[cpp] view plain copy
  1. #include "StdAfx.h"  
  2. #include "NewSocket.h"  
  3.   
  4.   
  5. CNewSocket::CNewSocket(void)  
  6.     : m_nLength(0)  
  7. {  
  8.     memset(m_szBuffer,0,sizeof(m_szBuffer));  
  9. }  
  10.   
  11.   
  12. CNewSocket::~CNewSocket(void)  
  13. {  
  14.     if(m_hSocket !=INVALID_SOCKET)  
  15.     {  
  16.         Close();  
  17.     }  
  18. }  
  19.   
  20.   
  21. void CNewSocket::OnReceive(int nErrorCode)  
  22. {  
  23.     // TODO: Add your specialized code here and/or call the base class  
  24.     m_nLength =Receive(m_szBuffer,sizeof(m_szBuffer),0); //接收数据  
  25.     m_szBuffer[m_nLength] ='\0';  
  26.     //接收消息后就开始给客户端发相同的消息  
  27.     AsyncSelect(FD_WRITE); //触发OnSend函数  
  28.     CAsyncSocket::OnReceive(nErrorCode);  
  29. }  
  30.   
  31.   
  32. void CNewSocket::OnSend(int nErrorCode)  
  33. {  
  34.     // TODO: Add your specialized code here and/or call the base class  
  35.     char m_sendBuf[4096];   //消息缓冲区  
  36.   
  37.     strcpy(m_sendBuf,"server send:");  
  38.     strcat(m_sendBuf,m_szBuffer);  
  39.     Send(m_sendBuf,strlen(m_sendBuf));  
  40.   
  41.     //触发OnReceive函数  
  42.     AsyncSelect(FD_READ);  
  43.     CAsyncSocket::OnSend(nErrorCode);  
  44. }  

如上,NewSocket类重载了CAsyncSocket类的接收与发送事件处理例程,一旦被触发了发送或接收事件,将调用此对应函数.

接下来服务器端在做一个专门类CListenSocket类,用来监听来自客户端的连接请求,如下:

ListenSocket.h:

[cpp] view plain copy
  1. #pragma once  
  2. #include "afxsock.h"  
  3. #include "NewSocket.h"  
  4. class CListenSocket :  
  5.     public CAsyncSocket  
  6. {  
  7. public:  
  8.     CListenSocket(void);  
  9.     ~CListenSocket(void);  
  10.   
  11.     CNewSocket *m_pSocket; //指向一个连接的socket对象  
  12.     virtual void OnAccept(int nErrorCode);  
  13. };  
由上可知,CListenSocket类还是继承了CAsyncSocket类,并重载了其接受事件,且包含了一个由之前定义好的CNewSocket类指针做为成员,用来指向与客户端连接好的连接.
其实现代码如下:

ListenSocket.cpp:

[cpp] view plain copy
  1. #include "StdAfx.h"  
  2. #include "ListenSocket.h"  
  3.   
  4.   
  5. CListenSocket::CListenSocket(void)  
  6. {  
  7. }  
  8.   
  9.   
  10. CListenSocket::~CListenSocket(void)  
  11. {  
  12. }  
  13.   
  14.   
  15. void CListenSocket::OnAccept(int nErrorCode)  
  16. {  
  17.     // TODO: Add your specialized code here and/or call the base class  
  18.     CNewSocket *pSocket =new CNewSocket();  
  19.     if(Accept(*pSocket))  
  20.     {  
  21.         pSocket->AsyncSelect(FD_READ); //触发通信socket的Read函数读数据  
  22.         m_pSocket =pSocket;  
  23.     }  
  24.     else  
  25.     {  
  26.         delete pSocket;  
  27.     }  
  28.     CAsyncSocket::OnAccept(nErrorCode);  
  29. }  

这个OnAccept事件触发是在Listen之后,如果有客户端尝试连接时触发,且先看后续内容.

接下来就是对话框的代码了:

SocketServerDlg.h:

[cpp] view plain copy
  1. // SocketServerDlg.h : header file  
  2. //  
  3.   
  4. #pragma once  
  5. #include "ListenSocket.h"  
  6.   
  7. // CSocketServerDlg dialog  
  8. class CSocketServerDlg : public CDialogEx  
  9. {  
  10. // Construction  
  11. public:  
  12.     CSocketServerDlg(CWnd* pParent = NULL); // standard constructor  
  13.   
  14. // Dialog Data  
  15.     enum { IDD = IDD_SOCKETSERVER_DIALOG };  
  16.   
  17.     protected:  
  18.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support  
  19.   
  20.     CListenSocket m_srvrSocket; //监听套接字  
  21. // Implementation  
  22. protected:  
  23.     HICON m_hIcon;  
  24.   
  25.     // Generated message map functions  
  26.     virtual BOOL OnInitDialog();  
  27.     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);  
  28.     afx_msg void OnPaint();  
  29.     afx_msg HCURSOR OnQueryDragIcon();  
  30.     DECLARE_MESSAGE_MAP()  
  31. public:  
  32.     afx_msg void OnBnClickedBtStart();  
  33. };  
在这个CSocketServerDlg类的声明内包含了一个CListenSocket成员m_srvrSocket,并有一个start按键.

[cpp] view plain copy
  1. // SocketServerDlg.cpp : implementation file  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "SocketServer.h"  
  6. #include "SocketServerDlg.h"  
  7. #include "afxdialogex.h"  
  8.   
  9. #ifdef _DEBUG  
  10. #define new DEBUG_NEW  
  11. #endif  
  12.   
  13.   
  14. // CAboutDlg dialog used for App About  
  15.   
  16. class CAboutDlg : public CDialogEx  
  17. {  
  18. public:  
  19.     CAboutDlg();  
  20.   
  21. // Dialog Data  
  22.     enum { IDD = IDD_ABOUTBOX };  
  23.   
  24.     protected:  
  25.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support  
  26.   
  27. // Implementation  
  28. protected:  
  29.     DECLARE_MESSAGE_MAP()  
  30. };  
  31.   
  32. CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)  
  33. {  
  34. }  
  35.   
  36. void CAboutDlg::DoDataExchange(CDataExchange* pDX)  
  37. {  
  38.     CDialogEx::DoDataExchange(pDX);  
  39. }  
  40.   
  41. BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)  
  42. END_MESSAGE_MAP()  
  43.   
  44.   
  45. // CSocketServerDlg dialog  
  46.   
  47.   
  48.   
  49.   
  50. CSocketServerDlg::CSocketServerDlg(CWnd* pParent /*=NULL*/)  
  51.     : CDialogEx(CSocketServerDlg::IDD, pParent)  
  52. {  
  53.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  
  54. }  
  55.   
  56. void CSocketServerDlg::DoDataExchange(CDataExchange* pDX)  
  57. {  
  58.     CDialogEx::DoDataExchange(pDX);  
  59. }  
  60.   
  61. BEGIN_MESSAGE_MAP(CSocketServerDlg, CDialogEx)  
  62.     ON_WM_SYSCOMMAND()  
  63.     ON_WM_PAINT()  
  64.     ON_WM_QUERYDRAGICON()  
  65.     ON_BN_CLICKED(IDC_BT_START, &CSocketServerDlg::OnBnClickedBtStart)  
  66. END_MESSAGE_MAP()  
  67.   
  68.   
  69. // CSocketServerDlg message handlers  
  70.   
  71. BOOL CSocketServerDlg::OnInitDialog()  
  72. {  
  73.     CDialogEx::OnInitDialog();  
  74.   
  75.     // Add "About..." menu item to system menu.  
  76.   
  77.     // IDM_ABOUTBOX must be in the system command range.  
  78.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  79.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  80.   
  81.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  82.     if (pSysMenu != NULL)  
  83.     {  
  84.         BOOL bNameValid;  
  85.         CString strAboutMenu;  
  86.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  87.         ASSERT(bNameValid);  
  88.         if (!strAboutMenu.IsEmpty())  
  89.         {  
  90.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  91.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  92.         }  
  93.     }  
  94.   
  95.     // Set the icon for this dialog.  The framework does this automatically  
  96.     //  when the application's main window is not a dialog  
  97.     SetIcon(m_hIcon, TRUE);         // Set big icon  
  98.     SetIcon(m_hIcon, FALSE);        // Set small icon  
  99.   
  100.     // TODO: Add extra initialization here  
  101.   
  102.     return TRUE;  // return TRUE  unless you set the focus to a control  
  103. }  
  104.   
  105. void CSocketServerDlg::OnSysCommand(UINT nID, LPARAM lParam)  
  106. {  
  107.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)  
  108.     {  
  109.         CAboutDlg dlgAbout;  
  110.         dlgAbout.DoModal();  
  111.     }  
  112.     else  
  113.     {  
  114.         CDialogEx::OnSysCommand(nID, lParam);  
  115.     }  
  116. }  
  117.   
  118. // If you add a minimize button to your dialog, you will need the code below  
  119. //  to draw the icon.  For MFC applications using the document/view model,  
  120. //  this is automatically done for you by the framework.  
  121.   
  122. void CSocketServerDlg::OnPaint()  
  123. {  
  124.     if (IsIconic())  
  125.     {  
  126.         CPaintDC dc(this); // device context for painting  
  127.   
  128.         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);  
  129.   
  130.         // Center icon in client rectangle  
  131.         int cxIcon = GetSystemMetrics(SM_CXICON);  
  132.         int cyIcon = GetSystemMetrics(SM_CYICON);  
  133.         CRect rect;  
  134.         GetClientRect(&rect);  
  135.         int x = (rect.Width() - cxIcon + 1) / 2;  
  136.         int y = (rect.Height() - cyIcon + 1) / 2;  
  137.   
  138.         // Draw the icon  
  139.         dc.DrawIcon(x, y, m_hIcon);  
  140.     }  
  141.     else  
  142.     {  
  143.         CDialogEx::OnPaint();  
  144.     }  
  145. }  
  146.   
  147. // The system calls this function to obtain the cursor to display while the user drags  
  148. //  the minimized window.  
  149. HCURSOR CSocketServerDlg::OnQueryDragIcon()  
  150. {  
  151.     return static_cast<HCURSOR>(m_hIcon);  
  152. }  
  153.   
  154.   
  155.   
  156. void CSocketServerDlg::OnBnClickedBtStart()  
  157. {  
  158.     // TODO: Add your control notification handler code here  
  159.   
  160.     if(m_srvrSocket.m_hSocket ==INVALID_SOCKET)  
  161.     {  
  162.         //创建监听套接字,激发FD_ACCEPT事件,默认端口7190  
  163.         BOOL bFlag =m_srvrSocket.Create(7190,SOCK_STREAM,FD_ACCEPT);    //第三个参数表示m_srvrSocket只对FD_ACCEPT事件感兴趣  
  164.         if(!bFlag)  
  165.         {  
  166.             AfxMessageBox(_T("Socket创建失败!"));  
  167.             m_srvrSocket.Close();  
  168.   
  169.             PostQuitMessage(0);  
  170.   
  171.             return;  
  172.         }  
  173.         GetDlgItem(IDC_BT_START)->EnableWindow(FALSE);  
  174.   
  175.         //监听成功,等待连接请求  
  176.         if(!m_srvrSocket.Listen())//如果监听失败  
  177.         {  
  178.             int nErrorCode =m_srvrSocket.GetLastError();    //检测错误信息  
  179.             if(nErrorCode !=WSAEWOULDBLOCK)             //如果不是线程阻塞  
  180.             {  
  181.                 AfxMessageBox(_T("Socket错误!"));  
  182.                 m_srvrSocket.Close();  
  183.                 PostQuitMessage(0);  
  184.   
  185.                 return;  
  186.             }  
  187.         }  
  188.     }  
  189. }  

当用户按下start按键时,程序首先调用m_srvrSocket的Create函数创建一个socket,然后调用它的Listen函数监听客户端的连接请求,一旦客户端尝试连接服务器,那将触发m_srvrSocket的FD_ACCEPT事件.接着在m_srvrSocket的OnAccept函数内,将创建一个CNewSocket对象,并利用此对象来操作socket收发,到此,服务器端的代码完.


2 客户端

这里的客户端的功能就是与服务器建立连接,交用户的数据发送给服务器,并显示来自服务器的接收数据.

与服务器类似,首先做一个专门用于socket通信的类ClientSocket类:

ClientSocket.h:

[cpp] view plain copy
  1. #pragma once  
  2. #include "afxsock.h"  
  3. class ClientSocket :  
  4.     public CAsyncSocket  
  5. {  
  6. public:  
  7.     ClientSocket(void);  
  8.     ~ClientSocket(void);  
  9.     // 是否连接  
  10.     bool m_bConnected;  
  11.     // 消息长度  
  12.     UINT m_nLength;  
  13.     //消息缓冲区  
  14.     char m_szBuffer[5096];  
  15.     virtual void OnConnect(int nErrorCode);  
  16.     virtual void OnReceive(int nErrorCode);  
  17.     virtual void OnSend(int nErrorCode);  
  18. };  
由上类声明可知,此类重载了CAsyncSocket的连接,接收,发送事件例程.其实现代码如下:

[cpp] view plain copy
  1. #include "StdAfx.h"  
  2. #include "ClientSocket.h"  
  3. #include "SocketTest.h"  
  4. #include "SocketTestDlg.h"  
  5.   
  6.   
  7. ClientSocket::ClientSocket(void)  
  8.     : m_bConnected(false)  
  9.     , m_nLength(0)  
  10. {  
  11.     memset(m_szBuffer,0,sizeof(m_szBuffer));  
  12. }  
  13.   
  14.   
  15. ClientSocket::~ClientSocket(void)  
  16. {  
  17.     if(m_hSocket !=INVALID_SOCKET)  
  18.     {  
  19.         Close();  
  20.     }  
  21. }  
  22.   
  23.   
  24. void ClientSocket::OnConnect(int nErrorCode)  
  25. {  
  26.     // TODO: Add your specialized code here and/or call the base class  
  27.     //连接成功  
  28.     if(nErrorCode ==0)  
  29.     {  
  30.         m_bConnected =TRUE;  
  31.           
  32.   
  33.         //获取主程序句柄  
  34.         CSocketTestApp *pApp =(CSocketTestApp *)AfxGetApp();  
  35.         //获取主窗口  
  36.         CSocketTestDlg *pDlg =(CSocketTestDlg *)pApp->m_pMainWnd;  
  37.   
  38.         //在主窗口输出区显示结果  
  39.         CString strTextOut;  
  40.         strTextOut.Format(_T("already connect to "));  
  41.         strTextOut +=pDlg->m_Address;  
  42.         strTextOut += _T("    端口号:");  
  43.         CString str;  
  44.         str.Format(_T("%d"),pDlg->m_Port);  
  45.         strTextOut +=str;  
  46.   
  47.         pDlg->m_MsgR.InsertString(0,strTextOut);  
  48.   
  49.         //激活一个网络读取事件,准备接收  
  50.         AsyncSelect(FD_READ);  
  51.           
  52.     }  
  53.     CAsyncSocket::OnConnect(nErrorCode);  
  54. }  
  55.   
  56.   
  57. void ClientSocket::OnReceive(int nErrorCode)  
  58. {  
  59.     // TODO: Add your specialized code here and/or call the base class  
  60.     //获取socket数据  
  61.     m_nLength =Receive(m_szBuffer,sizeof(m_szBuffer));  
  62.     //获取主程序句柄  
  63.     CSocketTestApp *pApp =(CSocketTestApp *)AfxGetApp();  
  64.     //获取主窗口  
  65.     CSocketTestDlg *pDlg =(CSocketTestDlg *)pApp->m_pMainWnd;  
  66.   
  67.     CString strTextOut(m_szBuffer);  
  68.     //在主窗口的显示区显示接收到的socket数据  
  69.     pDlg->m_MsgR.InsertString(0,strTextOut);  
  70.   
  71.     memset(m_szBuffer,0,sizeof(m_szBuffer));  
  72.     CAsyncSocket::OnReceive(nErrorCode);  
  73. }  
  74.   
  75.   
  76. void ClientSocket::OnSend(int nErrorCode)  
  77. {  
  78.     // TODO: Add your specialized code here and/or call the base class  
  79.     //发送数据  
  80.     Send(m_szBuffer,m_nLength,0);  
  81.     m_nLength =0;  
  82.   
  83.     memset(m_szBuffer,0,sizeof(m_szBuffer));  
  84.   
  85.     //继续提请一个读的网络事件,接收socket消息  
  86.     AsyncSelect(FD_READ);  
  87.     CAsyncSocket::OnSend(nErrorCode);  
  88. }  

接下来就是对话框代码了:

SocketTestDlg.h:

[cpp] view plain copy
  1. // SocketTestDlg.h : header file  
  2. //  
  3.   
  4. #pragma once  
  5. #include "afxwin.h"  
  6. #include "ClientSocket.h"  
  7.   
  8.   
  9. // CSocketTestDlg dialog  
  10. class CSocketTestDlg : public CDialogEx  
  11. {  
  12. // Construction  
  13. public:  
  14.     CSocketTestDlg(CWnd* pParent = NULL);   // standard constructor  
  15.   
  16. // Dialog Data  
  17.     enum { IDD = IDD_SOCKETTEST_DIALOG };  
  18.   
  19.     protected:  
  20.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support  
  21.   
  22.   
  23. // Implementation  
  24. protected:  
  25.     HICON m_hIcon;  
  26.   
  27.     // Generated message map functions  
  28.     virtual BOOL OnInitDialog();  
  29.     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);  
  30.     afx_msg void OnPaint();  
  31.     afx_msg HCURSOR OnQueryDragIcon();  
  32.     DECLARE_MESSAGE_MAP()  
  33. public:  
  34.     // 服务器IP地址  
  35.     CString m_Address;  
  36.     // 服务器端口号  
  37.     int m_Port;  
  38.     // 消息接收显示控件  
  39.     CListBox m_MsgR;  
  40.     afx_msg void OnBnClickedBtClear();  
  41.     afx_msg void OnBnClickedOk();  
  42.     // 用户输入的即将发送的内容  
  43.     CString m_MsgS;  
  44.     afx_msg void OnBnClickedBtConnect();  
  45.     afx_msg void OnTimer(UINT_PTR nIDEvent);  
  46.     // 连接服务器次数  
  47.     int m_nTryTimes;  
  48.     ClientSocket m_ClientSocket;  
  49.     afx_msg void OnBnClickedBtSend();  
  50.     afx_msg void OnBnClickedBtClose();  
  51. };  

其实现代码如下:

[cpp] view plain copy
  1. // SocketTestDlg.cpp : implementation file  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "SocketTest.h"  
  6. #include "SocketTestDlg.h"  
  7. #include "afxdialogex.h"  
  8.   
  9. #ifdef _DEBUG  
  10. #define new DEBUG_NEW  
  11. #endif  
  12.   
  13.   
  14. // CAboutDlg dialog used for App About  
  15.   
  16. class CAboutDlg : public CDialogEx  
  17. {  
  18. public:  
  19.     CAboutDlg();  
  20.   
  21. // Dialog Data  
  22.     enum { IDD = IDD_ABOUTBOX };  
  23.   
  24.     protected:  
  25.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support  
  26.   
  27. // Implementation  
  28. protected:  
  29.     DECLARE_MESSAGE_MAP()  
  30. };  
  31.   
  32. CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)  
  33. {  
  34. }  
  35.   
  36. void CAboutDlg::DoDataExchange(CDataExchange* pDX)  
  37. {  
  38.     CDialogEx::DoDataExchange(pDX);  
  39. }  
  40.   
  41. BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)  
  42. END_MESSAGE_MAP()  
  43.   
  44.   
  45. // CSocketTestDlg dialog  
  46.   
  47.   
  48.   
  49.   
  50. CSocketTestDlg::CSocketTestDlg(CWnd* pParent /*=NULL*/)  
  51.     : CDialogEx(CSocketTestDlg::IDD, pParent)  
  52.     , m_Address(_T("127.0.0.1"))  
  53.     , m_Port(0)  
  54.     , m_MsgS(_T(""))  
  55.     , m_nTryTimes(0)  
  56. {  
  57.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  
  58. }  
  59.   
  60. void CSocketTestDlg::DoDataExchange(CDataExchange* pDX)  
  61. {  
  62.     CDialogEx::DoDataExchange(pDX);  
  63.     DDX_Text(pDX, IDC_ET_IPADDRESS, m_Address);  
  64.     DDX_Text(pDX, IDC_ET_PORT, m_Port);  
  65.     DDX_Control(pDX, IDC_LIST_R, m_MsgR);  
  66.     DDX_Text(pDX, IDC_ET_SEND, m_MsgS);  
  67. }  
  68.   
  69. BEGIN_MESSAGE_MAP(CSocketTestDlg, CDialogEx)  
  70.     ON_WM_SYSCOMMAND()  
  71.     ON_WM_PAINT()  
  72.     ON_WM_QUERYDRAGICON()  
  73.     ON_BN_CLICKED(IDC_BT_CLEAR, &CSocketTestDlg::OnBnClickedBtClear)  
  74.     ON_BN_CLICKED(IDOK, &CSocketTestDlg::OnBnClickedOk)  
  75.     ON_BN_CLICKED(IDC_BT_CONNECT, &CSocketTestDlg::OnBnClickedBtConnect)  
  76.     ON_WM_TIMER()  
  77.     ON_BN_CLICKED(IDC_BT_SEND, &CSocketTestDlg::OnBnClickedBtSend)  
  78.     ON_BN_CLICKED(IDC_BT_CLOSE, &CSocketTestDlg::OnBnClickedBtClose)  
  79. END_MESSAGE_MAP()  
  80.   
  81.   
  82. // CSocketTestDlg message handlers  
  83.   
  84. BOOL CSocketTestDlg::OnInitDialog()  
  85. {  
  86.     CDialogEx::OnInitDialog();  
  87.   
  88.     // Add "About..." menu item to system menu.  
  89.   
  90.     // IDM_ABOUTBOX must be in the system command range.  
  91.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  92.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  93.   
  94.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  95.     if (pSysMenu != NULL)  
  96.     {  
  97.         BOOL bNameValid;  
  98.         CString strAboutMenu;  
  99.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  100.         ASSERT(bNameValid);  
  101.         if (!strAboutMenu.IsEmpty())  
  102.         {  
  103.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  104.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  105.         }  
  106.     }  
  107.   
  108.     // Set the icon for this dialog.  The framework does this automatically  
  109.     //  when the application's main window is not a dialog  
  110.     SetIcon(m_hIcon, TRUE);         // Set big icon  
  111.     SetIcon(m_hIcon, FALSE);        // Set small icon  
  112.   
  113.     // TODO: Add extra initialization here  
  114.   
  115.     return TRUE;  // return TRUE  unless you set the focus to a control  
  116. }  
  117.   
  118. void CSocketTestDlg::OnSysCommand(UINT nID, LPARAM lParam)  
  119. {  
  120.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)  
  121.     {  
  122.         CAboutDlg dlgAbout;  
  123.         dlgAbout.DoModal();  
  124.     }  
  125.     else  
  126.     {  
  127.         CDialogEx::OnSysCommand(nID, lParam);  
  128.     }  
  129. }  
  130.   
  131. // If you add a minimize button to your dialog, you will need the code below  
  132. //  to draw the icon.  For MFC applications using the document/view model,  
  133. //  this is automatically done for you by the framework.  
  134.   
  135. void CSocketTestDlg::OnPaint()  
  136. {  
  137.     if (IsIconic())  
  138.     {  
  139.         CPaintDC dc(this); // device context for painting  
  140.   
  141.         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);  
  142.   
  143.         // Center icon in client rectangle  
  144.         int cxIcon = GetSystemMetrics(SM_CXICON);  
  145.         int cyIcon = GetSystemMetrics(SM_CYICON);  
  146.         CRect rect;  
  147.         GetClientRect(&rect);  
  148.         int x = (rect.Width() - cxIcon + 1) / 2;  
  149.         int y = (rect.Height() - cyIcon + 1) / 2;  
  150.   
  151.         // Draw the icon  
  152.         dc.DrawIcon(x, y, m_hIcon);  
  153.     }  
  154.     else  
  155.     {  
  156.         CDialogEx::OnPaint();  
  157.     }  
  158. }  
  159.   
  160. // The system calls this function to obtain the cursor to display while the user drags  
  161. //  the minimized window.  
  162. HCURSOR CSocketTestDlg::OnQueryDragIcon()  
  163. {  
  164.     return static_cast<HCURSOR>(m_hIcon);  
  165. }  
  166.   
  167.   
  168.   
  169. void CSocketTestDlg::OnBnClickedBtClear()  
  170. {  
  171.     // TODO: Add your control notification handler code here  
  172.     m_MsgR.ResetContent();  
  173. }  
  174.   
  175.   
  176. void CSocketTestDlg::OnBnClickedOk()  
  177. {  
  178.     // TODO: Add your control notification handler code here  
  179.     /*CDialogEx::OnOK();*/  
  180.     UpdateData(TRUE);  
  181.     if(m_MsgS.IsEmpty())  
  182.     {  
  183.         AfxMessageBox(_T("please type the message you want to send!"));  
  184.         return;  
  185.     }  
  186. }  
  187.   
  188.   
  189. void CSocketTestDlg::OnBnClickedBtConnect()  
  190. {  
  191.     // TODO: Add your control notification handler code here  
  192.     //如果当前已经与服务器建立了连接,则直接返回  
  193.     if(m_ClientSocket.m_bConnected)  
  194.     {  
  195.         AfxMessageBox(_T("当前已经与服务器建立连接"));  
  196.         return;  
  197.     }  
  198.     UpdateData(TRUE);  
  199.   
  200.     if(m_Address.IsEmpty())  
  201.     {  
  202.         AfxMessageBox(_T("服务器的IP地址不能为空!"));  
  203.         return;  
  204.     }  
  205.     if(m_Port <=1024)  
  206.     {  
  207.         AfxMessageBox(_T("服务器的端口设置非法!"));  
  208.         return;  
  209.     }  
  210.     //使Connect按键失能  
  211.     GetDlgItem(IDC_BT_CONNECT)->EnableWindow(FALSE);  
  212.     //启动连接定时器,每1秒中尝试一次连接  
  213.     SetTimer(1,1000,NULL);  
  214. }  
  215.   
  216.   
  217. void CSocketTestDlg::OnTimer(UINT_PTR nIDEvent)  
  218. {  
  219.     // TODO: Add your message handler code here and/or call default  
  220.     if(m_ClientSocket.m_hSocket ==INVALID_SOCKET)  
  221.     {  
  222.         BOOL bFlag =m_ClientSocket.Create(0,SOCK_STREAM,FD_CONNECT); //创建套接字  
  223.         if(!bFlag)  
  224.         {  
  225.             AfxMessageBox(_T("Socket创建失败!"));  
  226.             m_ClientSocket.Close();  
  227.             PostQuitMessage(0);//退出  
  228.             return;  
  229.         }  
  230.     }  
  231.   
  232.     m_ClientSocket.Connect(m_Address,m_Port);   //连接服务器  
  233.       
  234.   
  235.     if(m_nTryTimes >=10)  
  236.     {  
  237.         KillTimer(1);  
  238.         AfxMessageBox(_T("连接失败!"));  
  239.         GetDlgItem(IDC_BT_CONNECT)->EnableWindow(TRUE);  
  240.         return;  
  241.     }  
  242.     else if(m_ClientSocket.m_bConnected)  
  243.     {  
  244.         KillTimer(1);  
  245.         GetDlgItem(IDC_BT_CONNECT)->EnableWindow(TRUE);  
  246.         return;  
  247.     }  
  248.     CString strTextOut =_T("尝试连接服务器第");  
  249.   
  250.     m_nTryTimes ++;  
  251.     CString str;  
  252.     str.Format(_T("%d"),m_nTryTimes);  
  253.     strTextOut +=str;  
  254.     strTextOut +=_T("次...");  
  255.     m_MsgR.InsertString(0,strTextOut);  
  256.     CDialogEx::OnTimer(nIDEvent);  
  257. }  
  258.   
  259.   
  260. void CSocketTestDlg::OnBnClickedBtSend()  
  261. {  
  262.     // TODO: Add your control notification handler code here  
  263.     UpdateData(TRUE);  
  264.   
  265.     if(m_ClientSocket.m_bConnected)  
  266.     {  
  267.         //将用户输入的数据从CString转化为char *字符串,即Unicode-->ANSI,并保存到m_ClientSocket.m_szBuffer中  
  268.         int len =WideCharToMultiByte(CP_ACP,0,m_MsgS,-1,NULL,0,NULL,NULL);  
  269.         WideCharToMultiByte(CP_ACP,0,m_MsgS,-1,m_ClientSocket.m_szBuffer,len,NULL,NULL );  
  270.         m_ClientSocket.m_nLength =strlen(m_ClientSocket.m_szBuffer);  
  271.   
  272.   
  273.         m_ClientSocket.AsyncSelect(FD_WRITE);//触发写事件  
  274.         m_MsgS =_T("");  
  275.         UpdateData(FALSE);  
  276.     }  
  277. }  
  278.   
  279.   
  280.   
  281.   
  282. void CSocketTestDlg::OnBnClickedBtClose()  
  283. {  
  284.     // TODO: Add your control notification handler code here  
  285.     m_ClientSocket.ShutDown();  
  286.     EndDialog(0);  
  287. }  

OK,完!