Windows CE 下的 TCP 客户端类
来源:互联网 发布:ubuntu terminal 字体 编辑:程序博客网 时间:2024/05/17 02:53
以前一直在使用 UDP 与服务器进行通讯,这次一个新的项目需要采用 TCP 来实现与服务器的通讯。
先写了一个 TCP 客户端的类,同时也做了一个服务器用于测试。先把客户端的 TCP 类代码分分享出来吧。
头文件:
// CeTcpClient.h: interface for the CCeTcpClient class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_CETCPCLIENT_H__B7856B99_69E7_4868_9BA3_96152245C65E__INCLUDED_)#define AFX_CETCPCLIENT_H__B7856B99_69E7_4868_9BA3_96152245C65E__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include <winsock.h>// 连接断开typedef void (CALLBACK *ONDISCONNECT)(CWnd *);// 数据接收typedef void (CALLBACK *ONREAD)(CWnd *,const char *,int);// Socket 错误typedef void (CALLBACK *ONERROR)(CWnd *,int);class CCeTcpClient{public:CCeTcpClient();virtual ~CCeTcpClient();public:// 服务器 IP 地址CString m_csRemoteHost;// 服务器端口 int m_iPort; // 连接断开ONDISCONNECT OnDisConnect;// 接收数据ONREAD OnRead;// 发生错误ONERROR OnError;public:// 打开 Socketbool Open(CWnd *pWnd);// 关闭 Socketbool Close();// 与服务器端建立连接bool Connect();// 向服务器端发送数据bool SendData(const char *pcBuffer,int iLen);private:// Socket 句柄SOCKET m_socket;// 通讯线程退出事件HANDLE m_hExitThreadEvent;// 通讯线程HANDLE m_hTcpThreadHandle;// 父窗口句柄CWnd *m_pOwnerWnd;private: // 通讯线程static DWORD SocketControlThread(LPVOID lparam);};#endif // !defined(AFX_TCPCLIENT_CE_H__B7856B99_69E7_4868_9BA3_96152245C65E__INCLUDED_)
源文件:
// CeTcpClient.cpp: implementation of the CCeTcpClient class.// Leo.Zheng 2012.04.09//////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "TCPClient.h"#include "CeTcpClient.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////CCeTcpClient::CCeTcpClient(){int iInitWSA = 0;// 初始化 Socket, 版本: 1.1WSADATA wsd;iInitWSA = WSAStartup(MAKEWORD(1,1),&wsd);if(0 != iInitWSA){RETAILMSG(1,(L"[CCeTcpClient::CCeTcpClient]WSA start up failed: %d\r\n",iInitWSA));}// 创建线程退出事件m_hExitThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL);}CCeTcpClient::~CCeTcpClient(){// 释放 SocketWSACleanup();// 关闭线程退出事件CloseHandle(m_hExitThreadEvent);}/* * 功能: 打开 Socket * 参数: pWnd 用于指定父窗口句柄 * 返回值: TRUE 成功; FALSE 失败*/bool CCeTcpClient::Open(CWnd *pWnd){ResetEvent(m_hExitThreadEvent);m_pOwnerWnd = pWnd;// 创建 TCP 套接字 m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(SOCKET_ERROR == m_socket){return FALSE;}// 创建通讯线程m_hTcpThreadHandle = CreateThread(NULL,0,SocketControlThread,this,0,NULL);if(NULL == m_hTcpThreadHandle){closesocket(m_socket);return FALSE;}return TRUE;}/* * 功能: 关闭 Socket * 参数: 无 * 返回值: TRUE 成功; FALSE 失败*/bool CCeTcpClient::Close(){// 设置通讯线程结束事件SetEvent(m_hExitThreadEvent);Sleep(1000);// 关闭 Socketint iError = closesocket(m_socket);if(SOCKET_ERROR == iError){return FALSE;}return TRUE;}/* * 功能: 与 TCP 服务器建立连接 * 参数: 无 * 返回值: TRUE 成功; FALSE 失败*/bool CCeTcpClient::Connect(){struct sockaddr_in addr;int iError = 0;char cAnsiRemoteHost[255 + 1];addr.sin_family = AF_INET;addr.sin_port = htons(m_iPort);ZeroMemory(cAnsiRemoteHost,sizeof(char) * (255 + 1));WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,m_csRemoteHost,wcslen(m_csRemoteHost),cAnsiRemoteHost,wcslen(m_csRemoteHost),NULL,NULL); addr.sin_addr.s_addr = inet_addr(cAnsiRemoteHost); // 采用同步连接方式, connect 直接返回成功或是失败 iError = connect(m_socket,(struct sockaddr *)&addr,sizeof(addr)); if(SOCKET_ERROR == iError) { return FALSE; } // 设置通讯模式为异步模式 DWORD dwMode = 1; ioctlsocket(m_socket,FIONBIO,&dwMode); return TRUE;}/* * 功能: 向服务器端发送数据 * 参数: buf 待发送的数据len 待发送的数据长度 * 返回值: TRUE 成功; FALSE 失败*/bool CCeTcpClient::SendData(const char *pcBuffer,int iLen){int iBytes = 0;int iSendBytes = 0;while(iSendBytes < iLen){ iBytes = send(m_socket,pcBuffer + iSendBytes,iLen - iSendBytes,0);if(SOCKET_ERROR == iBytes){int iErrorCode = WSAGetLastError();OnError(m_pOwnerWnd,iErrorCode);OnDisConnect(m_pOwnerWnd);//关闭 SocketClose();return FALSE;}iSendBytes = iSendBytes + iBytes;if(iSendBytes < iLen){ Sleep(1000);}} return TRUE; }/* * 功能: 此线程用于监听 TCP 客户端通讯的事件例如: 当接收到数据、连接断开或通讯过程发生错误等事件 * 参数: lparam: 可以通过此参数,向线程中传入需要用到的资源在这里我们将 CCeTcpClient 类实例指针传进来 * 返回值: 无意义,将返回值设为 0。*/DWORD CCeTcpClient::SocketControlThread(LPVOID lparam){CCeTcpClient *pSocket = NULL;fd_set fdRead;TIMEVALaTime;int iRet = 0;// 得到 CCeTcpClient 实例指针pSocket = (CCeTcpClient *)lparam;// 事件等待时间设置aTime.tv_sec = 1;aTime.tv_usec = 0;while(TRUE){ // 退出事件,结束线程if(WAIT_OBJECT_0 == WaitForSingleObject(pSocket->m_hExitThreadEvent,0)){break;}// 置 fdRead 为空FD_ZERO(&fdRead);// Socket 设置读事件FD_SET(pSocket->m_socket,&fdRead);// 判断是否有读事件iRet = select(0,&fdRead,NULL,NULL,&aTime);if(SOCKET_ERROR == iRet){pSocket->OnError(pSocket->m_pOwnerWnd,1);pSocket->OnDisConnect(pSocket->m_pOwnerWnd);//关闭客户端 Socketclosesocket(pSocket->m_socket);break;}if(iRet > 0){if(FD_ISSET(pSocket->m_socket,&fdRead)){char cRecvBuffer[1024 + 1];int iRecvLength = 0;ZeroMemory(cRecvBuffer,sizeof(char) * (1024 + 1));// 接收数据iRecvLength = recv(pSocket->m_socket,cRecvBuffer,1024,0); if(SOCKET_ERROR == iRecvLength){int iError = WSAGetLastError();pSocket->OnError(pSocket->m_pOwnerWnd,iError);pSocket->OnDisConnect(pSocket->m_pOwnerWnd);// 关闭客户端 Socketclosesocket(pSocket->m_socket);break;}else if(0 == iRecvLength){pSocket->OnDisConnect(pSocket->m_pOwnerWnd);// 关闭客户端 Socketclosesocket(pSocket->m_socket);break;}else{ // 触发数据接收事件 pSocket->OnRead(pSocket->m_pOwnerWnd,cRecvBuffer,iRecvLength);}}}}return 0;}
测试代码如下:
BOOL CTCPClientDlg::OnInitDialog(){//m_bFullScreen = FALSE;CDialog::OnInitDialog();// Set the icon for this dialog. The framework does this automatically// when the application's main window is not a dialogSetIcon(m_hIcon, TRUE);// Set big iconSetIcon(m_hIcon, FALSE);// Set small iconCenterWindow(GetDesktopWindow());// center to the hpc screen// 初始化输入值m_csRemoteHost = GetLocalIP();// 在模拟器上测试时用: 客户端与服务器都运行在模拟器上m_iRemotePort = 5000;UpdateData(FALSE);return TRUE; // return TRUE unless you set the focus to a control}// 连接断开void CALLBACK CTCPClientDlg::OnDisConnect(CWnd *pWnd){CTCPClientDlg *pDlg = (CTCPClientDlg *)pWnd;CStatic *pStatus = (CStatic *)pDlg->GetDlgItem(IDC_LBLCONNSTATUS);ASSERT(NULL != pStatus);pStatus->SetWindowText(L"连接断开");CButton *pBtnConn = (CButton *)pDlg->GetDlgItem(IDC_BTNCONN);CButton *pBtnDisConn = (CButton *)pDlg->GetDlgItem(IDC_BTNDISCONN);CButton *pBtnSendData = (CButton *)pDlg->GetDlgItem(IDC_BTNSENDDATA);ASSERT(NULL != pBtnConn);ASSERT(NULL != pBtnDisConn);ASSERT(NULL != pBtnSendData);pBtnConn->EnableWindow(TRUE);pBtnDisConn->EnableWindow(FALSE);pBtnSendData->EnableWindow(FALSE);}// 接收的数据显示void CALLBACK CTCPClientDlg::OnRead(CWnd *pWnd,const char *pcBuffer,int iLen){CTCPClientDlg *pDlg = (CTCPClientDlg *)pWnd;CString csRecvStr = pcBuffer;CEdit *pEdtRecv = (CEdit *)pDlg->GetDlgItem(IDC_EDTRECV);ASSERT(NULL != pEdtRecv);//将接收的数据显示到接收文本框上pEdtRecv->SetWindowText(csRecvStr);}// Socket 错误显示void CALLBACK CTCPClientDlg::OnError(CWnd *pWnd,int iErrorCode){CString csErrorInfo;csErrorInfo.Format(L"%s:%d",L"客户端socket发生错误",iErrorCode);AfxMessageBox(csErrorInfo);}// 建立连接void CTCPClientDlg::OnBtnconn() {CStatic *pStatus = (CStatic *)GetDlgItem(IDC_LBLCONNSTATUS);CButton *pBtnConn = (CButton *)GetDlgItem(IDC_BTNCONN);CButton *pBtnDisConn = (CButton *)GetDlgItem(IDC_BTNDISCONN);CButton *pBtnSendData = (CButton *)GetDlgItem(IDC_BTNSENDDATA);ASSERT(NULL != pStatus);ASSERT(NULL != pBtnConn);ASSERT(NULL != pBtnDisConn);ASSERT(NULL != pBtnSendData);UpdateData(TRUE);// 设置 m_tcpClient 属性m_tcpClient.m_csRemoteHost = m_csRemoteHost;m_tcpClient.m_iPort = m_iRemotePort;m_tcpClient.OnDisConnect = OnDisConnect;m_tcpClient.OnRead = OnRead;m_tcpClient.OnError = OnError;// 打开客户端 socketm_tcpClient.Open(this);// 与服务器端连接if(m_tcpClient.Connect()){pStatus->SetWindowText(L"建立连接");UpdateData(FALSE);}else{AfxMessageBox(L"建立连接失败");pStatus->SetWindowText(L"连接断开");return;}pBtnConn->EnableWindow(FALSE);pBtnDisConn->EnableWindow(TRUE);pBtnSendData->EnableWindow(TRUE);}// 断开连接void CTCPClientDlg::OnBtndisconn() {if(m_tcpClient.Close()){CStatic *pStatus = (CStatic *)GetDlgItem(IDC_LBLCONNSTATUS);CButton *pBtnConn =(CButton*)GetDlgItem(IDC_BTNCONN);CButton *pBtnDisConn = (CButton*)GetDlgItem(IDC_BTNDISCONN);CButton *pBtnSendData = (CButton*)GetDlgItem(IDC_BTNSENDDATA);ASSERT(NULL != pStatus);ASSERT(NULL != pBtnConn);ASSERT(NULL != pBtnDisConn);ASSERT(NULL != pBtnSendData);pStatus->SetWindowText(L"连接断开");pBtnConn->EnableWindow(TRUE);pBtnDisConn->EnableWindow(FALSE);pBtnSendData->EnableWindow(FALSE);}else{AfxMessageBox(L"连接断开失败");}}// 发送数据void CTCPClientDlg::OnBtnsenddata() {char *pcSendBuf;int iSendLength = 0;UpdateData(TRUE);iSendLength = m_csSendData.GetLength();pcSendBuf = new char[iSendLength * 2];ASSERT(NULL != pcSendBuf);wcstombs(pcSendBuf,m_csSendData,iSendLength);if(!m_tcpClient.SendData(pcSendBuf,iSendLength)){AfxMessageBox(L"发送失败");}delete[] pcSendBuf;pcSendBuf = NULL;}
- Windows CE 下的 TCP 客户端类
- Windows CE 下的 TCP 服务器端类
- Windows CE下的串口通讯类
- Windows CE下的串口通讯类
- Windows CE下的iostream
- Windows CE下的字符串
- Windows下TCP聊天服务器与客户端雏形的实现
- Windows CE下的串口通讯实例
- Windows CE下串行通信的实现
- Windows CE下的注册表 (转)
- Windows CE下PlaySound的解决方法
- Windows CE下的蓝牙开发
- windows CE下一些目录的变量
- Windows CE下的多线程编程实验
- Windows CE下ActiveX 控件的使用
- Windows CE下MUI image的实现
- Windows CE下的串口通讯实例
- Windows CE下的串口通讯实例
- Iphone开发基础篇(三)-ObjectC之继承
- Yahoo Web前端优化守则
- WPF触发器的使用
- gcc 详解
- 建立自己的手写笔画图案
- Windows CE 下的 TCP 客户端类
- 插件开发,包冲突之类加载器问题
- 数据库范式
- asp.net 读取 (导入) CSV文件内容 到页面 (数据库)
- 判断IE WEBBROWSER IHTMLDocument2 是否用户正在编辑
- 苹果开发者帐号(Company)申请流程
- SQL SERVER 内存分配及常见内存问题(1)——简介
- 家用3D视频格式-数据存储格式
- alsa-utils工具包的使用