8. 在 CSockClientDlg.ccp 中添加代码
- #include "AddrDlg.h"
- protected:
- int TryCount;
- MySock m_clientSocket;
- UINT m_szPort;
- public:
- char m_szServerAdr[256];
9. 双击 IDD_CSOCKCLIENT_DIALOG 对话框中的 "连接" 按钮, 添加以下代码
- void CCSockClientDlg::OnConnect()
- {
- m_clientSocket.ShutDown(2);
- m_clientSocket.m_hSocket=INVALID_SOCKET;
- m_clientSocket.m_bConnected=FALSE;
- CAddrDlg m_Dlg;
- // 默认端口 1088
- m_Dlg.m_Port=1088;
- if (m_Dlg.DoModal()==IDOK && !m_Dlg.m_Addr.IsEmpty())
- {
- memcpy(m_szServerAdr,m_Dlg.m_Addr,sizeof(m_szServerAdr));
- m_szPort=m_Dlg.m_Port;
- // 建立计时器, 每 1 秒尝试连接一次, 直到连上或 TryCount>10
- SetTimer(1,1000,NULL);
- TryCount=0;
- }
- }
10. 添加 Windows 消息 WM_TIMER 响应函数 OnTimer
- void CCSockClientDlg::OnTimer(UINT nIDEvent)
- {
- if (m_clientSocket.m_hSocket==INVALID_SOCKET)
- {
- BOOL bFlag=m_clientSocket.Create(0,SOCK_STREAM,FD_CONNECT);
- if(!bFlag)
- {
- AfxMessageBox("Socket Error!");
- m_clientSocket.Close();
- PostQuitMessage(0);
- return;
- }
- }
- m_clientSocket.Connect(m_szServerAdr,m_szPort);
- TryCount++;
- if (TryCount>=10 || m_clientSocket.m_bConnected)
- {
- KillTimer(1);
- if (TryCount>=10)
- AfxMessageBox("Connect Failed!");
- return;
- }
- CDialog::OnTimer(nIDEvent);
- }
11. 双击 IDD_CSOCKCLIENT_DIALOG 对话框中的 "发送" 按钮, 添加以下代码
- void CCSockClientDlg::OnSend()
- {
- if (m_clientSocket.m_bConnected)
- {
- m_clientSocket.m_nLength=m_MSG.GetWindowText
- (m_clientSocket.m_szBuffer, sizeof(m_clientSocket.m_szBuffer));
- m_clientSocket.AsyncSelect(FD_WRITE);
- m_MSG.SetWindowText("");
- }
- }
12. 双击 IDD_CSOCKCLIENT_DIALOG 对话框中的 "关闭" 按钮, 添加以下代码
- void CCSockClientDlg::OnExit()
- {
- // 关闭 Socket
- m_clientSocket.ShutDown(2);
- // 关闭对话框
- EndDialog(0);
- }
12.运行此项目, 连接时输入主机名或 IP 均可, CAsyncSocket 类会自动处理.
二. 服务端
Server 端的编程与 Client 端的类似, 下面主要介绍他的 Listen 及 Accept 函数
1. 建立一个 CNewSocket 类, 重载 CAsyncSocket 类的 OnReceive, OnSend 函数,
如何进行信息的显示和发送可以参考 Client 程序. 本例中采用将收到信息原封不
动发回的方法来实现 Echo 功能, 代码如下
- CNewSocket:: OnReceive( int nErrorCOde)
- {
- m_nLength=Receive( m_szBuffer, sizeof( m_szBuffer) , 0) ;
- // 直接转发消息
- AsyncSelect( FD_WRITE) ;
- }
- CNewSocket:: OnSend( int nErrorCode)
- {
- Send( m_szBuffer, m_nLength, 0) ;
- }
2. 建立一个 CMyServerSocket 类, 重载 CAsyncSocket 类的 OnAccept 函数代码
如下
在 MyServerSocket.h 中声明变量
- public::
- CNewSocket m_pSocket;
- void CMyServerSocket:: OnAccept( int nErrorCode)
- {
- // 侦听到连接请求, 调用 Accept 函数
- CNewSocket pSocket = new CNewSocket( ) ;
- if ( Accept( pSocket) )
- {
- pSocket->AsyncSelect( FD_READ) ;
- m_pSocket=pSocket;
- }
- else
- delete pSocket;
- }
3. 为对话框添加一个 "侦听" 按钮, 添加如下代码
在 CsockServerDlg.h 中声明变量
- public:
- CMyServerSocket m_srvrSocket;
- void CCSockServerDlg:: OnListen()
- {
- if ( m_srvrSocket.m_hSocket==INVALID_SOCKET)
- {
- BOOL bFlag=m_srvrSocket.Create
- (UserPort, SOCK_STREAM, FD_ACCEPT);
- if (! bFlag)
- {
- AfxMessageBox( "Socket Error!") ;
- M_srvrSocket.Close( ) ;
- PostQuitMessage( 0) ;
- Return;
- }
- }
- //"侦听" 成功, 等待连接请求
- if (! m_srvrSocket. Listen( 1) )
- {
- int nErrorCode = m_srvrSocket.GetLastError( ) ;
- if ( nError! =WSAEWOULDBLOCK)
- {
- AfxMessageBox( "Socket Error!") ;
- M_srvrSocket.Close( ) ;
- PostQuitMessage( 0) ;
- Return;
- }
- }
- }
4. 目前程序只能实现 Echo 功能, 将信息原封不动的转发, 若能将 Accept 中由
CNewSocket pSocket = new CNewSocket( ) ; 得到的 Socket 指针存入一个
CList 或一个数组中, 便像 Client 端那样, 对所有的连接进行读写控制.
三. 总结
CAsyncSocket 类为我们使用 Socket 提供了极大方便. 建立 Socket 的 WSAStartup
过程和 bind 过程被简化成为 Create 过程, IP 地址类型转换, 主机名和 IP 地址转
换的过程中许多复杂的变量类型都被简化成字符串和整数操作, 特别是
CAsyncSocket 类的异步特点, 完全可以替代繁琐的线程操作. MFC 提供了大量的
类库, 我们若能灵活的使用他们, 便会大大提高编程的效率
来源: http://www.bubuko.com/infodetail-2576917.html