服务器与客户机互传消息
<P> </P><P>一、 服 务 器 程 序 </P>
<P>创 建 一 个 名 为“server" 的 项 目, 单 文 档 界 面。 </P>
<P>在serverview.h 中 加 入 代 码: </P>
<P> #include “winsock.h" </P>
<P> 添 加 变 量: </P>
<P> CSize sizeTotal;// 控 制 滚 动 条 </P>
<P> int count;// 信 息 条 数 </P>
<P> CString m_data;// 信 息 存 放 </P>
<P> char Hostname; </P>
<P> char Hostaddress;// 主 机IP 地 址 </P>
<P> SOCKET m_sock; </P>
<P> HANDLE m_hListenThread;// 线 程 </P>
<P> BOOL m_bInitialized;// 是 否 初 始 化 </P>
<P> WSADATA WSAData; </P>
<P> BOOL flag; </P>
<P> SOCKADDR_IN saClnt; </P>
<P> int saClntLen; </P>
<P> BOOL Isconnect;// 是 否 连 接 </P>
<P> </P>
<P>在serverview.cpp 中 重 载CServerView() 构 造 器, 创 建 并 绑 定 嵌 套 </P>
<P> 字: </P>
<P> CServerView::CServerView() </P>
<P>{ // TOD add construction code here </P>
<P> Isconnect=FALSE; </P>
<P> flag=FALSE; </P>
<P> sizeTotal.cy=350; </P>
<P> sizeTotal.cx=300; </P>
<P> m_hListenThread; </P>
<P> count=5; </P>
<P> int status; </P>
<P> WSADATA wsaData; </P>
<P> m_data=“initializing Windows Sockets DLL...."; </P>
<P> if((status=WSAStartup(0x0101, &wsaData))==0) </P>
<P> { m_data +=“Succeeded"; </P>
<P> m_bInitialized=TRUE; </P>
<P> } </P>
<P> else </P>
<P> { m_bInitialized=FALSE; </P>
<P> } </P>
<P> m_sock=socket(AF_INET,SOCK_DGRAM,0); </P>
<P> m_data=“Creating socket...."; </P>
<P> if(m_sock==INVALID_SOCKET) </P>
<P> { m_data +=“Failed"; </P>
<P> } </P>
<P> m_data +=“Succeeded"; </P>
<P> m_data=“Binding socket...."; </P>
<P> sockaddr_in sa; </P>
<P> sa.sin_family=AF_INET; </P>
<P> sa.sin_addr.S_un.S_addr=htonl(INADDR_ANY); </P>
<P> sa.sin_port=htons(5050); </P>
<P> if(bind(m_sock,(PSOCKADDR) </P>
<P> &sa,sizeof(sa))==SOCKET_ERROR) </P>
<P> { m_data +=“Failed"; </P>
<P> </P>
<P> closesocket(m_sock); </P>
<P> } </P>
<P> m_data +=“Succeeded"; </P>
<P> m_data=“Creating listener thread...."; </P>
<P> unsigned long idThread; </P>
<P> m_hListenThread=CreateThread(NULL,0, </P>
<P>(LPTHREAD_START_ROUTINE)Listen, </P>
<P>(void if(m_hListenThread) </P>
<P> { m_data +=“Succeeded"; </P>
<P> m_data +=“Listening...."; </P>
<P> } </P>
<P> else </P>
<P> m_data +=“Failed"; </P>
<P>} </P>
<P> </P>
<P>在 析 构 函 数 中 完 成 必 需 的 清 除 操 作: </P>
<P> CServerView:: ~CServerView() </P>
<P>{ if(m_bInitialized) </P>
<P> WSACleanup(); </P>
<P> closesocket(m_sock); </P>
<P> if(m_hListenThread) </P>
<P> ::TerminateThread(m_hListenThread,0); </P>
<P>} </P>
<P> </P>
<P>定 义 接 收 和 处 理 消 息 的 线 程: </P>
<P> long WINAPI Listen(CServerView *pView) </P>
<P>{ char msg=“"; </P>
<P> int nchar; </P>
<P> SOCKADDR_IN saClnt; </P>
<P> int saClntLen; </P>
<P> while(1) </P>
<P> { saClntLen=sizeof(saClnt); </P>
<P> nchar=recvfrom(pView ->m_sock,msg,1024,0, </P>
<P>(PSOCKADDR) &saClnt, &saClntLen); </P>
<P> if(nchar<0) </P>
<P> { pView ->m_data + </P>
<P> =“Error in recvfrom\n"; </P>
<P> pView ->InvalidateRect(NULL); </P>
<P> } </P>
<P> else </P>
<P> {switch(msg) </P>
<P> { </P>
<P> case ‘A': </P>
<P> wsprintf(msg,“A:Client from %s attached\n", </P>
<P> inet_ntoa(saClnt.sin_addr)); </P>
<P> pView ->m_data=msg; </P>
<P> pView ->flag=TRUE; </P>
<P> pView ->InvalidateRect(NULL); </P>
<P> pView ->Isconnect=TRUE; </P>
<P> pView ->saClnt=saClnt; </P>
<P> pView ->saClntLen=saClntLen; </P>
<P> sendto(pView ->m_sock,msg,1024,0,(PSOCKADDR) </P>
<P> &saClnt,saClntLen); </P>
<P> break; </P>
<P> </P>
<P> case ‘D': </P>
<P> wsprintf(msg,“D: Client form %s detached\n", </P>
<P> inet_ntoa(saClnt.sin_addr)); </P>
<P> pView ->m_data=msg; </P>
<P> pView ->flag=TRUE; </P>
<P> pView ->InvalidateRect(NULL); </P>
<P> pView ->Isconnect=FALSE; </P>
<P> sendto(pView ->m_sock,msg,1024,0,(PSOCKADDR) </P>
<P> &saClnt,saClntLen); </P>
<P> break; </P>
<P> </P>
<P> case ‘R': </P>
<P> saClntLen=sizeof(saClnt); </P>
<P> pView ->m_data=msg; </P>
<P> pView ->flag=TRUE; </P>
<P> pView ->InvalidateRect(NULL); </P>
<P> break; </P>
<P> </P>
<P> default: </P>
<P> break; </P>
<P> } </P>
<P> } </P>
<P> </P>
<P> } </P>
<P> return(0); </P>
<P>} </P>
<P> </P>
<P>在 程 序 菜 单 项 中 添 加“ 本 机IP 地 址": </P>
<P> void CServerView::OnIp() </P>
<P>{int WSAReturn; </P>
<P> WSAReturn=WSAStartup( 0x0101, &WSAData ); </P>
<P> if( WSAReturn == 0 ){ </P>
<P> gethostname( Hostname, 260 ); </P>
<P> struct hostent *pHostEnt; </P>
<P> pHostEnt = gethostbyname( Hostname); </P>
<P> if( pHostEnt != NULL ){ </P>
<P> wsprintf( Hostaddress, “ %d. %d. %d. %d", </P>
<P>( pHostEnt ->h_addr_list & 0x00ff ), </P>
<P>( pHostEnt ->h_addr_list & 0x00ff ), </P>
<P>( pHostEnt ->h_addr_list & 0x00ff ), </P>
<P>( pHostEnt ->h_addr_list & 0x00ff ) ); </P>
<P> CString out; </P>
<P> out.Format(Hostaddress); </P>
<P> AfxMessageBox(out); </P>
<P> } </P>
<P> } </P>
<P>} </P>
<P> </P>
<P>在 程 序 菜 单 中 添 加“ 发 送 消 息": </P>
<P> void CServerView::OnSendmessage() </P>
<P>{// TOD Add your command handler code here </P>
<P> char msg; </P>
<P> Csend Sendmessage; </P>
<P> if(Sendmessage.DoModal()==IDOK </P>
<P> & &!Sendmessage.m_Message.IsEmpty()) </P>
<P> { wsprintf(msg,“R: " +Sendmessage.m_Message); </P>
<P> sendto(m_sock,msg,1024,0,(PSOCKADDR) </P>
<P> &saClnt,saClntLen); </P>
<P> m_data=Sendmessage.m_Message; </P>
<P> flag=TRUE; </P>
<P> InvalidateRect(NULL); </P>
<P> } </P>
<P>} </P>
<P> </P>
<P>为 发 送 消 息 项 添 加 一 个 对 话 框 的 类, 名 为send, 有 一 个 文 </P>
<P>本 框, 用 来 发 送 消 息, 并 为 文 本 框 添 加CString m_Message 变 量 </P>
<P>, 在ServerView.cpp 中 添 加 #include “send.h" </P>
<P>为 发 送 消 息 项 添 加 一 个 判 断 函 数: </P>
<P> void CServerView::OnUpdateSendmessage(CCmdUI * </P>
<P>pCmdUI) </P>
<P>{// TOD Add your command update UI handler code here </P>
<P> pCmdUI ->Enable(FALSE); </P>
<P> if(Isconnect) </P>
<P> pCmdUI ->Enable(TRUE); </P>
<P>} </P>
<P> </P>
<P>再 窗 口 显 示 消 息: </P>
<P> void CServerView::OnDraw(CDC * pDC) </P>
<P>{ if(flag) </P>
<P> {sizeTotal.cy +=20; </P>
<P> for(int j=65;j </P>
<P>TextOut(10,y,m_data); </P>
<P> y +=20;} </P>
<P> // TOD add draw code for native data here </P>
<P>} </P>
<P> </P>
<P>在Project 中 点 击Settings 中 选 择Link 项 添 加wsock32.lib。 </P>
<P>----最 后 编 译 程 序, 就 可 以 得 到Server.exe 程 序。 </P>
<P> </P>
<P>二、 客 户 机 程 序 </P>
<P>创 建 一 个 名 为“client" 的 项 目, 单 文 档 界 面。 </P>
<P>在clientview.h 中 加 入 代 码: </P>
<P> #include “winsock.h" </P>
<P> 添 加 变 量: </P>
<P> CString m_data; </P>
<P> HANDLE m_hListenThread; </P>
<P> SOCKET m_sock; </P>
<P> SOCKADDR_IN m_saSrvr; </P>
<P> BOOL Isconnect; </P>
<P> int count; </P>
<P> CSize sizeTotal; </P>
<P> BOOL flag; </P>
<P> </P>
<P>在 构 造 函 数 中 初 始 化 变 量: </P>
<P> CClientView::CClientView() </P>
<P>{ // TOD add construction code here </P>
<P> Isconnect=FALSE; </P>
<P> sizeTotal.cy=350; </P>
<P> sizeTotal.cx=300; </P>
<P> flag=FALSE; </P>
<P>} </P>
<P> </P>
<P>在 析 构 函 数 中 完 成 清 除 操 作, 代 码 如 上。 </P>
<P>在 菜 单 中 添 加“ 拨 号" 项: </P>
<P> void CClientView::OnDial() </P>
<P>{// TOD Add your command handler code here </P>
<P> count=5; </P>
<P> if(m_bInitialized) </P>
<P> { AfxMessageBox(“Already dialing"); </P>
<P> return;} </P>
<P> Cdial dial; </P>
<P> if(dial.DoModal()==IDOK </P>
<P> & &!dial.m_HostAddress.IsEmpty()) </P>
<P> {m_saSrvr.sin_family=AF_INET; </P>
<P> m_saSrvr.sin_addr.S_un.S_addr=htonl </P>
<P>(INADDR_ANY); </P>
<P> m_saSrvr.sin_addr.S_un.S_addr=inet_addr </P>
<P>(dial.m_HostAddress); </P>
<P> m_saSrvr.sin_port=htons(5050); </P>
<P> int status; </P>
<P> WSADATA wsaData; </P>
<P> m_data=“initializing Windows Sockets DLL...."; </P>
<P> if((status=WSAStartup(0x0101, &wsaData))==0) </P>
<P> { m_data +=“Succeeded"; </P>
<P> m_bInitialized=TRUE;} </P>
<P> else </P>
<P> { m_bInitialized=FALSE;} </P>
<P> m_sock=socket(AF_INET,SOCK_DGRAM,0); </P>
<P> m_data=“Creating socket...."; </P>
<P> if(m_sock==INVALID_SOCKET) </P>
<P> { m_data +=“Failed";} </P>
<P> m_data +=“Succeeded"; </P>
<P> m_data=“Binding socket...."; </P>
<P> sockaddr_in sa; </P>
<P> sa.sin_family=AF_INET; </P>
<P> sa.sin_addr.S_un.S_addr=htonl(INADDR_ANY); </P>
<P> sa.sin_port=htons(0); </P>
<P> if(bind(m_sock,(PSOCKADDR) </P>
<P> &sa,sizeof(sa))==SOCKET_ERROR) </P>
<P> { m_data +=“Failed"; </P>
<P> closesocket(m_sock);} </P>
<P> m_data +=“Succeeded"; </P>
<P> m_data=“Creating listener thread...."; </P>
<P> unsigned long idThread; </P>
<P> m_hListenThread=CreateThread(NULL 0, </P>
<P>(LPTHREAD_START_ROUTINE)Listen, </P>
<P>(void *)this,0, &idThread); </P>
<P> if(m_hListenThread) </P>
<P> { m_data +=“Succeeded"; </P>
<P> m_data +=“Waiting....";} </P>
<P> else </P>
<P> m_data +=“Failed"; </P>
<P> InvalidateRect(NULL); </P>
<P> } </P>
<P>} </P>
<P> </P>
<P>添 加 一 个 拨 号 对 话 框, 名 为dial, 有 一 个 文 本 框 用 来 写IP 地 </P>
<P> 址. 并 在clientview.cpp 中 添 加 代 码: </P>
<P> #include dial.h </P>
<P> </P>
<P>在 拨 号 项 添 加 一 个 判 断 函 数: </P>
<P> void CClientView::OnUpdateDial(CCmdUI * </P>
<P>pCmdUI) </P>
<P>{// TOD Add your command update UI handler code here </P>
<P> pCmdUI ->Enable(TRUE); </P>
<P> if(Isconnect) </P>
<P> pCmdUI ->Enable(FALSE); </P>
<P>} </P>
<P> </P>
<P>添 加 接 收 与 发 送 消 息 的 线 程: </P>
<P> long WINAPI Listen(CClientView *pView) </P>
<P>{ char msg; </P>
<P> pView ->m_data=“Sending ATTACH command"; </P>
<P> pView ->InvalidateRect(NULL); </P>
<P> wsprintf(msg,“A: "); </P>
<P> sendto(pView ->m_sock,msg,1024,0,(PSOCKADDR) </P>
<P> &pView ->m_saSrvr,sizeof(pView ->m_saSrvr)); </P>
<P> int saSrvrLen ,nchar; </P>
<P> while(1) </P>
<P> {saSrvrLen=sizeof(pView ->m_saSrvr); </P>
<P> nchar=recvfrom(pView ->m_sock,msg,1024,0, </P>
<P> (PSOCKADDR) &pView ->m_saSrvr, &saSrvrLen); </P>
<P> if(nchar<0) </P>
<P> { pView ->m_data= </P>
<P> “Error in recvform"; </P>
<P> pView ->InvalidateRect(NULL);} </P>
<P> else </P>
<P> { pView ->m_data=msg; </P>
<P> pView ->Isconnect=TRUE; </P>
<P> pView ->flag=TRUE; </P>
<P> pView ->InvalidateRect(NULL); </P>
<P> } </P>
<P> } </P>
<P> return(0); </P>
<P>} </P>
<P> </P>
<P>同 主 程 序 一 样 做 一 个 发 送 消 息 项, 代 码 如 上。 </P>
<P>显 示 程 序 也 与 主 程 序 一 样, 代 码 如 上。 </P>
<P>在Project 中 点 击Settings 中 选 择Link 项 添 加wsock32.lib。 </P>
<P>编 译 程 序 便 可 得 到client.exe 程 序。 </P>
<P>----server.exe 和 client.exe 做 完 后, 就 可 以 在 具 有 TCP/IP 协 议 </P>
<P> 下 的 网 络 中 执 行。</P>
页:
[1]