基於TCP(連線導向)的Socket編程
一、用戶端:
1、開啟一個通訊端(Socket);
2、發起串連請求(connect);
3、如果串連成功,則進行資料交換(read、write、send、recv);
4、資料交換完成,關閉串連(shutdown、close);
二、伺服器端:
1、開啟一個通訊端(Socket);
2、將通訊端綁定到伺服器位址上(bind);
3、指定通訊端為伺服器通訊端(listen),做好串連請求準備;
4、等待串連請求(connect);
5、如果串連請求到,則串連建立,進行資料交換(read、write、send、recv);
6、資料交換完成,關閉串連(shutdown、close);
基於UDP(面向無串連)的Socket編程
一、用戶端\伺服器端:
1、開啟一個通訊端(Socket);
2、將通訊端綁定到指定的伺服器位址和連接埠上(bind);
3、進行資料交換(read、write、send、recv);
4、資料交換完成,關閉串連(shutdown、close);
三、MFC對Socket的支援:
1、建立CAsyncSocket對象;
2、發送接收資料報(SendTo、RecvFrom);
3、串連伺服器(Connect);
4、接收串連(Listen);
5、發送和接收流式資料(Send、Receive);
6、關閉通訊端(Close);
7、差錯處理(GetLastError)。
四、執行個體:網路聊天工具
用戶端:
1、。。。。
2、利用類嚮導重載CAsyncSocket類,產生新的MySocket類。。
3、利用類嚮導重載CAsyncSocket的OnReceive(int nErrorCode)和OnSend(int nErrorCode)、OnConnect(int nErrorCode)函數。
void MySocket::OnReceive(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
//擷取對話方塊指標
CTestApp*pApp=(CTestApp*)AfxGetApp();
CTestDlg*pDlg=(CTestDlg*)pApp->m_pMainWnd;
//往編輯框中插入訊息
char *pbuf=new char[4096];
int ibufsize=4096;
int ircvd;
CString strrecvd;
ircvd=Receive(pbuf,ibufsize);
if(ircvd==SOCKET_ERROR)
{
pDlg->MessageBox("SOCKET_ERROR");
}
else
{
pbuf[ircvd]=NULL;
pDlg->m_recmsg+="伺服器:";
pDlg->m_recmsg+=pbuf;
pDlg->m_recmsg+="\r\n";
pDlg->RefreshScreen();
}
delete pbuf;
CAsyncSocket::OnReceive(nErrorCode);
}
void MySocket::OnSend(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CAsyncSocket::OnSend(nErrorCode);
}
void MySocket::OnConnect(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CTestApp*pApp=(CTestApp*)AfxGetApp();
CTestDlg*pDlg=(CTestDlg*)pApp->m_pMainWnd;
int iResult=nErrorCode;
CString buffer;
int namelen;
if(iResult!=0)
{
buffer.Format("串連伺服器失敗。\r\n");
pDlg->m_recmsg+=buffer;
}
else
{
namelen=sizeof(sockaddr_in);
buffer.Format("成功串連到伺服器 %s:%d.\r\n",pDlg->m_ipstr,pDlg->m_port);
pDlg->m_recmsg+=buffer;
pDlg->GetDlgItem(IDC_SEND)->EnableWindow(TRUE);
pDlg->GetDlgItem(IDOK)->EnableWindow(TRUE);
}
pDlg->RefreshScreen();
CAsyncSocket::OnConnect(nErrorCode);
}
4、在C*Dlg類中
標頭檔中:
#include "MySocket.h"
MySocket m_socket;
CString m_ipstr;
.CPP檔案中:
void CTestDlg::OnSend()
{
// TODO: Add your control notification handler code here
int ilen;
int isent;
UpdateData(TRUE);
if(m_msg!="")
{
ilen=m_msg.GetLength ();
isent=m_socket.Send(LPCTSTR(m_msg),ilen);
if(isent==SOCKET_ERROR)
{
MessageBox("串連失敗,請重試!");
// connect=false;
}
else
{
m_recmsg+="客戶機:"+m_msg;
m_recmsg+="\r\n";
UpdateData(FALSE);
}
}
}
void CTestDlg::RefreshScreen()
{
UpdateData(false);
}
void CTestDlg::OnConnect()
{
if (!AfxSocketInit())
{
AfxMessageBox("IDP_SOCKETS_INIT_FAILED");
return ;
}
GetDlgItemText(IDC_IPADDRESS1,m_ipstr);
m_socket.m_hSocket=INVALID_SOCKET;
UpdateData(true);
BOOL flag=m_socket.Create();
if(!flag)
{
AfxMessageBox("SOCKET ERROR");
return;
}
m_socket.Connect(m_ipstr,m_port);
}
void CTestDlg::OnOK()
{
// TODO: Add extra validation here
m_socket.Close();
CDialog::OnOK();
}
伺服器端:
1、。。。。
2、利用類嚮導重載CAsyncSocket類,產生新的MySocket類。。
3、利用類嚮導重載CAsyncSocket的OnReceive(int nErrorCode)和OnSend(int nErrorCode)函數。
void MySocket::OnReceive(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CTestApp*pApp=(CTestApp*)AfxGetApp();
CTestDlg*pDlg=(CTestDlg*)pApp->m_pMainWnd;
//往列表框中插入訊息
char *pbuf=new char[4096];
int ibufsize=4096;
int ircvd;
CString strrecvd;
ircvd=Receive(pbuf,ibufsize);
if(ircvd==SOCKET_ERROR)
{
pDlg->MessageBox("SOCKET_ERROR");
}
else
{
pbuf[ircvd]=NULL;
pDlg->m_msg+="客戶機:";
pDlg->m_msg+=pbuf;
pDlg->m_msg+="\r\n";
pDlg->RefreshScreen();
}
delete pbuf;
CAsyncSocket::OnReceive(nErrorCode);
}
void MySocket::OnSend(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CAsyncSocket::OnSend(nErrorCode);
}
4、建立MyServerSocket類,並添加MySocket * m_socket;即接收請求後的通訊端指標。
MySocket * m_socket;
void CMyServerSocket::OnAccept(int nErrorCode)
{
// TODO: Add your specialized code here and/or call the base class
CTestApp*pApp=(CTestApp*)AfxGetApp();
CTestDlg*pDlg=(CTestDlg*)pApp->m_pMainWnd;
//顯示串連訊息
pDlg->m_msg="客戶機串連到伺服器";
pDlg->m_msg+="\r\n";
pDlg->RefreshScreen();
pDlg->GetDlgItem(IDC_SEND)->EnableWindow(TRUE);
pDlg->GetDlgItem(IDOK)->EnableWindow(TRUE);
MySocket* psocket=new MySocket();
if(Accept(*psocket))
{
psocket->AsyncSelect(FD_READ);
m_socket=psocket;
}
else
{
delete psocket;
}
CAsyncSocket::OnAccept(nErrorCode);
}
5、C*Dlg類中
void CTestDlg::RefreshScreen()
{
UpdateData(false);
}
void CTestDlg::OnListen() //建立伺服器
{
// TODO: Add your control notification handler code here
UpdateData(true);
if (!AfxSocketInit())
{
AfxMessageBox("IDP_SOCKETS_INIT_FAILED");
return ;
}
BOOL flag=m_serversocket.Create(m_port);
if(!flag)
{
AfxMessageBox("SOCKET ERROR");
return;
}
flag=m_serversocket.Listen(1);
if(!flag)
{
AfxMessageBox("SOCKET ERROR");
return;
}
SetDlgItemText(IDC_LISTEN,"正在監聽");
}
void CTestDlg::OnSend()
{
// TODO: Add your control notification handler code here
int ilen;
int isent;
UpdateData(TRUE);
if(m_sendmsg!="")
{
ilen=m_sendmsg.GetLength ();
isent=m_serversocket.m_socket->Send(LPCTSTR(m_sendmsg),ilen);
if(isent==SOCKET_ERROR)
{
MessageBox("串連失敗,請重試!");
}
else
{
m_msg+="伺服器:"+m_sendmsg;
m_msg+="\r\n";
UpdateData(FALSE);
}
}
}
void CTestDlg::OnOK()
{
// TODO: Add extra validation here
m_sendmsg="伺服器退出";
UpdateData(false);
OnSend();
m_serversocket.Close();
CDialog::OnOK();
}