基于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); }完成效果如下: 可以双向进行通讯。