• 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 }  
  • 相关阅读:
    Spring框架总结(二)
    java.lang.ClassCastException: com.liuyang.annocation.UserAction cannot be cast to com.liuyang.annocation2.UserAction at com.liuyang.annocation2.App.test
    Spring框架总结(一)
    Error creating bean with name 'us' defined in class path resource [com/liuyang/test/DI/beans2.xml]: Cannot resolve reference to bean 'daoa' while setting bean property 'daoa'; nested exception is org.
    互联网系统架构的演进
    重新理解:ASP.NET 异步编程(转)
    Git初级使用教程(转)
    JavaScript开发规范要求
    大型网站架构演化发展历程(转)
    Bootstrap 学习(1)
  • 原文地址:https://www.cnblogs.com/91program/p/5206296.html
Copyright © 2020-2023  润新知