建一對話框IDD_Addr,用來輸入IP地址和Port;增加兩個Edit控件:IDC_Addr、IDC_Port按下表在ClassWizard中為CAddrDlg類添加變量。
Control ID Type Member
IDC_Addr CString m_Addr
IDC_Port Int m_Port
在CSockClientDlg.ccp中添加代碼:
#include "AddrDlg.h"
protected:
int TryCount;
MySock m_clientSocket;
UINT m_szPort;
public:
char m_szServerAdr[256];
雙擊IDD_CSOCKCLIENT_DIALOG對話框中的“連接”按鈕,添加以下代碼:
m_clientSocket.ShutDown(2);
m_clientSocket.m_hSocket=INVALID_SOCKET;
m_clientSocket.m_bConnected=FALSE;
CAddrDlg m_Dlg;
m_Dlg.m_Port=1088;//默認端口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;
SetTimer(1,1000,NULL);//建立計時器,每1秒嘗試連接一次
TryCount=0;}
添加Windows消息WM_TIMER響應(yīng)函數(shù)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);}
雙擊IDD_CSOCKCLIENT_DIALOG對話框中的“發(fā)送”按鈕,添加以下代碼:
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("");}}
雙擊IDD_CSOCKCLIENT_DIALOG對話框中的“關(guān)閉”按鈕,添加以下代碼:
void CCSockClientDlg::OnExit()
{ m_clientSocket.ShutDown(2); //關(guān)閉Socket
EndDialog(0);}
運行此項目,連接時輸入主機名或IP均可,CAsyncSocket類會自動處理。
服務(wù)端
Server端的編程與Client端的類似,下面主要介紹他的Listen及Accept函數(shù)。建立一個CNewSocket類,重載CAsyncSocket類的OnReceive、OnSend函數(shù),如何進行信息的顯示和發(fā)送可以參考Client程序。本例中采用將收到信息原封不動發(fā)回的方法來實現(xiàn)Echo功能,代碼如下:
CNewSocket::OnReceive(int nErrorCOde)
{ m_nLength=Receive(m_szBuffer,sizeof(m_szBuffer),0);
AsyncSelect(FD_WRITE);}// 直接轉(zhuǎn)發(fā)消息
CNewSocket::OnSend(int nErrorCode)
{ Send(m_szBuffer,m_nLength,0);}
建立一個CMyServerSocket類,重載CAsyncSocket類的OnAccept函數(shù)代碼如下:
在MyServerSocket.h中聲明變量
public::
CNewSocket* m_pSocket;
void CMyServerSocket::OnAccept(int nErrorCode)
{ CNewSocket* pSocket = new CNewSocket();
if (Accept(*pSocket))
{ pSocket- >AsyncSelect(FD_READ);
m_pSocket=pSocket;}else
delete pSocket;}
為對話框添加一個“偵聽”按鈕,添加如下代碼:
在CsockServerDlg.ccp中聲明變量
public:
CMyServerSocket m_srvrSocket;
void CCSockServerDlg::OnListen()
{ if (m_srvrSocket.m_hSocket==INVALID_SOCKET)
{ BOOL bFlag=m_srvrSocket.Create
(UserPort,SOCK_STREAM,F(xiàn)D_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;}}}
CAsyncSocket類為我們使用Socket提供了極大方便。建立Socket的WSAStartup過程和bind過程被簡化成為Create過程,IP地址類型轉(zhuǎn)換、主機名和IP地址轉(zhuǎn)換的過程中許多復(fù)雜的變量類型都被簡化成字符串和整數(shù)操作,特別是CAsyncSocket類的異步特點,完全可以替代繁瑣的線程操作。MFC提供了大量的類庫,我們?nèi)裟莒`活的使用他們,便會大大提高編程的效率。