Windows CE 下的 TCP 服务器端类

与上一个帖子对应,可以互相通讯。

头文件:

 1 // TCPCustom_CE.h: interface for the CTCPCustom_CE class.  
 2 //  
 3 //////////////////////////////////////////////////////////////////////  
 4   
 5 #if !defined(AFX_TCPCUSTOM_CE_H__0E8B4A18_8A99_438E_B5F6_B5985FFC117D__INCLUDED_)  
 6 #define AFX_TCPCUSTOM_CE_H__0E8B4A18_8A99_438E_B5F6_B5985FFC117D__INCLUDED_  
 7   
 8 #if _MSC_VER > 1000  
 9 #pragma once  
10 #endif // _MSC_VER > 1000  
11   
12 #include <winsock.h>  
13 #include "TCPServer_CE.h"  
14   
15 class CTCPCustom_CE    
16 {  
17 public:  
18     CTCPCustom_CE();  
19     virtual ~CTCPCustom_CE();  
20 public:  
21     CTCPServer_CE * m_pTCPServer_CE; //引用TCP服务端监听Socket  
22   
23     CString m_RemoteHost; //远程主机IP地址  
24     DWORD m_RemotePort; //远程主机端口号  
25     SOCKET m_socket;      //通讯Socket句柄  
26 private:  
27     HANDLE m_exitThreadEvent;  //通讯线程退出事件句柄  
28     HANDLE m_tcpThreadHandle;  //通讯线程句柄  
29 private:  
30     //通讯线程函数  
31     static DWORD SocketThreadFunc(PVOID lparam);  
32 public:  
33     //打开socket,创建通讯线程  
34     bool Open(CTCPServer_CE *pTCPServer);  
35       
36     //关闭socket,关闭线程,释放Socket资源  
37     bool Close();  
38   
39     //向客户端发送数据  
40     bool  SendData(const char * buf , int len);  
41   
42 };  
43   
44 #endif // !defined(AFX_TCPCUSTOM_CE_H__0E8B4A18_8A99_438E_B5F6_B5985FFC117D__INCLUDED_)  

源文件:

  1 // TCPCustom_CE.cpp: implementation of the CTCPCustom_CE class.  
  2 //  
  3 //////////////////////////////////////////////////////////////////////  
  4   
  5 #include "stdafx.h"  
  6 #include "TCPServer.h"  
  7 #include "TCPCustom_CE.h"  
  8   
  9 #ifdef _DEBUG  
 10 #undef THIS_FILE  
 11 static char THIS_FILE[]=__FILE__;  
 12 #define new DEBUG_NEW  
 13 #endif  
 14   
 15 //////////////////////////////////////////////////////////////////////  
 16 // Construction/Destruction  
 17 //////////////////////////////////////////////////////////////////////  
 18   
 19 //构造函数  
 20 CTCPCustom_CE::CTCPCustom_CE()  
 21 {  
 22    //创建线程退出事件  
 23    m_exitThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL);  
 24 }  
 25   
 26 //析构函数  
 27 CTCPCustom_CE::~CTCPCustom_CE()  
 28 {  
 29    //关闭线程退出事件  
 30    CloseHandle(m_exitThreadEvent);  
 31 }  
 32   
 33 /*-------------------------------------------------------------------- 
 34 【函数介绍】:  此线程用于监听与客户端连接的socket通讯的事件,例如当接收到数据、 
 35                连接断开和通讯过程发生错误等事件 
 36 【入口参数】:  lparam:无类型指针,可以通过此参数,向线程中传入需要用到的资源。 
 37                在这里我们将CTCPCustom_CE类实例指针传进来 
 38 【出口参数】:  (无) 
 39 【返回  值】:  返回值没有特别的意义,在此我们将返回值设为0。 
 40 ---------------------------------------------------------------------*/  
 41 DWORD CTCPCustom_CE::SocketThreadFunc(PVOID lparam)  
 42 {  
 43     CTCPCustom_CE *pSocket;  
 44     //得到CTCPCustom类实例指针  
 45     pSocket = (CTCPCustom_CE*)lparam;  
 46     //定义读事件集合  
 47     fd_set fdRead;    
 48     int ret;  
 49     TIMEVAL aTime;  
 50     aTime.tv_sec = 1;  
 51     aTime.tv_usec = 0;  
 52     while (TRUE)  
 53     {  
 54         //收到退出事件,结束线程  
 55         if (WaitForSingleObject(pSocket->m_exitThreadEvent,0) == WAIT_OBJECT_0)  
 56         {  
 57             break;  
 58         }  
 59         //置空读事件集合  
 60         FD_ZERO(&fdRead);  
 61         //给pSocket设置读事件  
 62         FD_SET(pSocket->m_socket,&fdRead);  
 63         //调用select函数,判断是否有读事件发生  
 64         ret = select(0,&fdRead,NULL,NULL,&aTime);  
 65           
 66         if (ret == SOCKET_ERROR)  
 67         {  
 68             //触发错误事件  
 69             pSocket->m_pTCPServer_CE->OnClientError(pSocket->m_pTCPServer_CE->m_pOwnerWnd,pSocket,1);  
 70             //关闭socket  
 71             closesocket(pSocket->m_socket);  
 72             break;  
 73         }  
 74           
 75         if (ret > 0)  
 76         {  
 77             //判断是否读事件  
 78             if (FD_ISSET(pSocket->m_socket,&fdRead))  
 79             {  
 80                 char recvBuf[1024];  
 81                 int recvLen;  
 82                 ZeroMemory(recvBuf,1024);  
 83                 recvLen = recv(pSocket->m_socket,recvBuf, 1024,0);   
 84                 if (recvLen == SOCKET_ERROR)  
 85                 {  
 86                     int nErrorCode = WSAGetLastError();  
 87                     //触发与客户端端连接的Socket错误  
 88                     pSocket->m_pTCPServer_CE->OnClientError(pSocket->m_pTCPServer_CE->m_pOwnerWnd,pSocket,nErrorCode);  
 89                     //触发与客户端端连接的Socket关闭事件  
 90                     pSocket->m_pTCPServer_CE->OnClientClose(pSocket->m_pTCPServer_CE->m_pOwnerWnd,pSocket);  
 91                     //关闭socket  
 92                     closesocket(pSocket->m_socket);  
 93                     break;  
 94   
 95                 }  
 96                 //表示连接已经从容关闭  
 97                 else if (recvLen == 0)  
 98                 {  
 99                     pSocket->m_pTCPServer_CE->OnClientClose(pSocket->m_pTCPServer_CE->m_pOwnerWnd,pSocket);  
100                     //关闭socket  
101                     closesocket(pSocket->m_socket);  
102                     break;  
103                 }  
104                 else  
105                 {  
106                    //触发与客户端端连接的Socket读事件  
107                    pSocket->m_pTCPServer_CE->OnClientRead(pSocket->m_pTCPServer_CE->m_pOwnerWnd,pSocket,recvBuf,recvLen);  
108                 }  
109             }  
110         }  
111     }  
112     return 0;  
113 }  
114   
115 /*-------------------------------------------------------------------- 
116 【函数介绍】: 打开socket,创建通讯线程 
117 【入口参数】:  pTCPServer指向服务器端监听socket 
118 【出口参数】:  (无) 
119 【返回  值】:  TRUE:打开成功;FALSE:打开失败 
120 ---------------------------------------------------------------------*/  
121 bool CTCPCustom_CE::Open(CTCPServer_CE *pTCPServer)  
122 {  
123    //创建通讯线程  
124    m_tcpThreadHandle = CreateThread(NULL,0,SocketThreadFunc,this,0,NULL);  
125    if (m_tcpThreadHandle == NULL)  
126    {  
127        closesocket(m_socket);  
128        return FALSE;  
129    }  
130    //设置通讯模式为异步模式  
131    DWORD ul= 1;  
132    ioctlsocket(m_socket,FIONBIO,&ul);  
133    m_pTCPServer_CE = pTCPServer;  
134    return TRUE;  
135 }  
136   
137 /*-------------------------------------------------------------------- 
138 【函数介绍】: 关闭socket,关闭线程,释放Socket资源 
139 【入口参数】:  (无) 
140 【出口参数】:  (无) 
141 【返回  值】:  TRUE:成功关闭;FALSE:关闭失败 
142 ---------------------------------------------------------------------*/  
143 bool CTCPCustom_CE::Close()  
144 {  
145    //发送通讯线程结束事件  
146    SetEvent(m_exitThreadEvent);  
147    Sleep(1000);  
148    //关闭Socket,释放资源  
149    int err = closesocket(m_socket);  
150    if (err == SOCKET_ERROR)  
151    {  
152        return FALSE;  
153    }  
154    return TRUE;  
155 }  
156   
157   
158 /*----------------------------------------------------------------- 
159 【函数介绍】: 向客户端发送数据 
160 【入口参数】: buf:待发送的数据 
161               len:待发送的数据长度 
162 【出口参数】: (无) 
163 【返回  值】: TRUE:发送数据成功;FALSE:发送数据失败 
164 ------------------------------------------------------------------*/  
165 bool CTCPCustom_CE::SendData(const char * buf , int len)  
166 {  
167     int nBytes = 0;  
168     int nSendBytes=0;  
169               
170     while (nSendBytes < len)  
171     {  
172         nBytes = send(m_socket,buf+nSendBytes,len-nSendBytes,0);  
173         if (nBytes==SOCKET_ERROR )  
174         {  
175             int iErrorCode = WSAGetLastError();  
176             //触发socket的Error事件  
177             m_pTCPServer_CE->OnClientError(m_pTCPServer_CE->m_pOwnerWnd,this,iErrorCode);  
178             //触发与服务器端断开连接事件  
179             m_pTCPServer_CE->OnClientClose(m_pTCPServer_CE->m_pOwnerWnd,this);  
180             //关闭socket  
181             Close();  
182             return FALSE;  
183         }  
184   
185         nSendBytes = nSendBytes + nBytes;  
186           
187         if (nSendBytes < len)  
188         {  
189             Sleep(1000);  
190         }  
191     }   
192     return TRUE;   
193 }  

调用示例:

  1 BOOL CTCPServerDlg::OnInitDialog()  
  2 {  
  3     //m_bFullScreen = FALSE;  
  4     CDialog::OnInitDialog();  
  5   
  6     // Set the icon for this dialog.  The framework does this automatically  
  7     //  when the application's main window is not a dialog  
  8     SetIcon(m_hIcon, TRUE);         // Set big icon  
  9     SetIcon(m_hIcon, FALSE);        // Set small icon  
 10       
 11     CenterWindow(GetDesktopWindow());   // center to the hpc screen  
 12   
 13     // TODO: Add extra initialization here  
 14     // 设置默认值  
 15     m_localPort = 5000;  
 16     UpdateData(FALSE);  
 17     return TRUE;  // return TRUE  unless you set the focus to a control  
 18 }  
 19   
 20   
 21 // 客户端连接建立事件处理函数  
 22 void CALLBACK  CTCPServerDlg::OnClientConnect(CWnd* pWnd,CTCPCustom_CE* pTcpCustom)  
 23 {  
 24     CTCPServerDlg * pDlg = (CTCPServerDlg*)pWnd;  
 25     CListBox * pLstConn = (CListBox*)pDlg->GetDlgItem(IDC_LSTCONN);  
 26     ASSERT(pLstConn != NULL);  
 27     pLstConn->AddString(pTcpCustom->m_RemoteHost + _T("建立连接"));  
 28       
 29     RETAILMSG(1,(TEXT("==OnClientConnect=%s 
"),pTcpCustom->m_RemoteHost));  
 30   
 31     gTcpSendObj = *pTcpCustom;  
 32 }  
 33   
 34 // 客户端SOCKET关闭事件处理函数  
 35 void  CALLBACK CTCPServerDlg::OnClientClose(CWnd* pWnd,CTCPCustom_CE* pTcpCustom)  
 36 {  
 37     CTCPServerDlg * pDlg = (CTCPServerDlg*)pWnd;  
 38     int iIndex = 0;  
 39       
 40     CListBox * pLstConn = (CListBox*)pDlg->GetDlgItem(IDC_LSTCONN);  
 41     ASSERT(pLstConn != NULL);  
 42     iIndex = pLstConn->FindString(iIndex,pTcpCustom->m_RemoteHost + _T("建立连接"));  
 43     if (iIndex == LB_ERR)  
 44     {  
 45         return;  
 46     }  
 47     pLstConn->DeleteString(iIndex);   
 48       
 49     RETAILMSG(1,(TEXT("==OnClientClose=%s 
"),pTcpCustom->m_RemoteHost));  
 50 }  
 51   
 52 // 服务器端收到来自客户端的数据  
 53 void CALLBACK CTCPServerDlg::OnClientRead(CWnd* pWnd,CTCPCustom_CE* pTcpCustom,const char *buf,int len)  
 54 {  
 55     CString strRecv;  
 56     CString strLen;  
 57     strLen.Format(L"%d",len);  
 58     strRecv = buf;  
 59     CTCPServerDlg * pDlg = (CTCPServerDlg*)pWnd;  
 60     CListBox * pLstRecv = (CListBox*)pDlg->GetDlgItem(IDC_LSTRECV);  
 61     ASSERT(pLstRecv != NULL);  
 62       
 63     pLstRecv->AddString(_T("************************************"));  
 64     pLstRecv->AddString(_T("来自: ") + pTcpCustom->m_RemoteHost);  
 65     pLstRecv->AddString(_T("数据长度:")+strLen);  
 66     pLstRecv->AddString(strRecv);  
 67       
 68     RETAILMSG(1,(TEXT("===%s 
"),pTcpCustom->m_RemoteHost));  
 69     if (!pTcpCustom->SendData("OK",strlen("OK")))  
 70     {  
 71         AfxMessageBox(_T("发送失败"));  
 72     }  
 73 }  
 74   
 75 //客户端Socket错误事件处理函数  
 76 void CALLBACK CTCPServerDlg::OnClientError(CWnd* pWnd,CTCPCustom_CE* pTcpCustom,int nErrorCode)  
 77 {  
 78       
 79     RETAILMSG(1,(TEXT("==OnClientError=%s 
"),pTcpCustom->m_RemoteHost));  
 80 }  
 81   
 82 //服务器端Socket错误事件处理函数  
 83 void CALLBACK CTCPServerDlg::OnServerError(CWnd* pWnd,CTCPServer_CE* pTcpServer_CE,int nErrorCode)  
 84 {  
 85 }  
 86   
 87 // 监听按钮单击事件方法  
 88 void CTCPServerDlg::OnBtnlisten()   
 89 {  
 90     UpdateData(TRUE);  
 91     // 设置 m_tcpServer 属性  
 92     m_tcpServer.m_LocalPort = m_localPort;  
 93     m_tcpServer.m_pOwnerWnd = this;  
 94     m_tcpServer.OnClientConnect = OnClientConnect;  
 95     m_tcpServer.OnClientClose = OnClientClose;  
 96     m_tcpServer.OnClientRead = OnClientRead;  
 97     m_tcpServer.OnClientError = OnClientError;  
 98     m_tcpServer.OnServerError = OnServerError;  
 99     if (m_tcpServer.Open() <= 0)  
100     {  
101         AfxMessageBox(_T("监听失败"));  
102         return;  
103     }  
104     CButton * pBtnListen = (CButton*)GetDlgItem(IDC_BTNLISTEN);  
105     ASSERT(pBtnListen != NULL);  
106     pBtnListen->EnableWindow(FALSE);  
107       
108     CButton * pBtnClose = (CButton*)GetDlgItem(IDC_BTNCLOSE);  
109     ASSERT(pBtnClose != NULL);  
110     pBtnClose->EnableWindow(TRUE);     
111       
112     CButton *pBtnSend = (CButton*)GetDlgItem(IDC_SendBtn);  
113     ASSERT(pBtnSend != NULL);  
114     pBtnSend->EnableWindow(TRUE);  
115 }  
116   
117 //关闭按钮单击事件代码   
118 void CTCPServerDlg::OnBtnclose()   
119 {  
120     if (m_tcpServer.Close() <=0)  
121     {  
122         AfxMessageBox(_T("关闭TCP服务器失败"));  
123         return;  
124     }  
125     CButton * pBtnListen = (CButton*)GetDlgItem(IDC_BTNLISTEN);  
126     ASSERT(pBtnListen != NULL);  
127     pBtnListen->EnableWindow(TRUE);  
128   
129     CButton * pBtnClose = (CButton*)GetDlgItem(IDC_BTNCLOSE);  
130     ASSERT(pBtnClose != NULL);  
131     pBtnClose->EnableWindow(FALSE);        
132       
133     CButton *pBtnSend = (CButton*)GetDlgItem(IDC_SendBtn);  
134     ASSERT(pBtnSend != NULL);  
135     pBtnSend->EnableWindow(FALSE);  
136   
137     CListBox * pLstConn = (CListBox*)GetDlgItem(IDC_LSTCONN);  
138     ASSERT(pLstConn != NULL);  
139       
140     CListBox * pLstRecv = (CListBox*)GetDlgItem(IDC_LSTRECV);  
141     ASSERT(pLstRecv != NULL);  
142       
143     pLstConn->ResetContent();  
144     pLstRecv->ResetContent();  
145       
146 }  
147   
148 void CTCPServerDlg::OnSendBtn()   
149 {  
150     // TODO: Add your control notification handler code here  
151       
152     if (!gTcpSendObj.SendData("Send data ok(Server)",strlen("Send data ok(Server)")))  
153     {  
154         AfxMessageBox(_T("发送失败"));  
155     }  
156 }  
原文地址:https://www.cnblogs.com/91program/p/5206296.html