基於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();
}