基于TCP(面向连接)的socket编程,分为客户端和服务器端。
客户端的流程如下:
(1)创建套接字(socket)
(2)向服务器发出连接请求(connect)
(3)和服务器端进行通信(send/recv)
(4)关闭套接字
服务器端的流程如下:
(1)创建套接字(socket)
(2)将套接字绑定到一个本地地址和端口上(bind)
(3)将套接字设为监听模式,准备接收客户端请求(listen)
(4)等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)
(5)用返回的套接字和客户端进行通信(send/recv)
(6)返回,等待另一个客户请求。
(7)关闭套接字。
TCP的三次握手如下所示:
本篇使用编程验证,使用到MFC。
(a)分别双击Server和Client选项,添加函数名为OnRadio1和OnRadio1,添加代码如下
void CTCPDlg::OnRadio2()
{
// TODO: Add your control notification handler code here
m_WorkType=1;
SetDlgItemText(IDC_Start_Server,"ConnectServer");
SetDlgItemText(IDC_Close_Server,"ShutDown");
GetDlgItem(IDC_IP)->EnableWindow(TRUE);
}
void CTCPDlg::OnRadio1()
{
// TODO: Add your control notification handler code here
m_WorkType=0;
SetDlgItemText(IDC_Start_Server,"StartServer");
SetDlgItemText(IDC_Close_Server,"CloseServer");
GetDlgItem(IDC_IP)->EnableWindow(FALSE);
m_IP=GetIP();
UpdateData(FALSE);
}
(b)分别双击StartServer和CloseServer按钮,添加函数如下:
void CTCPDlg::OnStartServer()
{
// TODO: Add your control notification handler code here
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0){
MessageBox("Failed to load Winsock!");
return;
}
if(m_WorkType==0)
{
if(!m_bStarting)
{
UpdateData(TRUE);
if(m_Port==0)
{
MessageBox("Please input the Port!");
return;
}
if(sockListen.Create(m_Port,SOCK_STREAM,m_IP))
{
m_State="Service Start...";
sockListen.Bind(m_Port,m_IP);
sockListen.Listen(5);
WSAAsyncSelect(sockListen,GetSafeHwnd(),ACCEPT_EVENT,FD_ACCEPT|FD_READ|FD_CLOSE);
m_bStarting=TRUE;
}
else
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
MessageBox((LPCTSTR)lpMsgBuf,_T("Error"),MB_OK|MB_ICONINFORMATION);
}
}
}
else if(m_WorkType==1)
{
if(!m_bConnected)
{
CString str;
UpdateData(TRUE);
if(m_Port==0||m_IP=="")
{
MessageBox("Please input IP and Port!");
return;
}
m_TCPsock.Create();
if(BOOL fC=m_TCPsock.Connect(m_IP,m_Port))
{
WSAAsyncSelect(m_TCPsock,GetSafeHwnd(),ACCEPT_EVENT,FD_READ|FD_CLOSE);
m_bConnected=TRUE;
m_State="Connect with Server";
}
else
{
m_TCPsock.Close();
m_State="Connect failed";
}
}
}
else
MessageBox("Please choose the type of the machine!");
UpdateData(FALSE);
}
void CTCPDlg::OnCloseServer()
{
// TODO: Add your control notification handler code here
if(m_bConnected)
{
m_TCPsock.ShutDown(2);
m_TCPsock.Close();
m_bConnected=FALSE;
WSAAsyncSelect(m_TCPsock,GetSafeHwnd(),0,0);
}
if(m_WorkType==1)
{
m_State="Service Stop!";
sockListen.Close();
}
if(m_WorkType==1)
m_State="Shut down!";
UpdateData(FALSE);
}
(c)双击Send按钮,添加函数如下
void CTCPDlg::OnSend()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
int iSend=m_TCPsock.Send(m_SendMsg,40,0);
TRACE("sent %d byte\n",iSend);
}
完成效果如下:
可以双向进行通讯。