/*-----------------------------------------
* Copyright (c) 2008 Eric Wong
* 本版紧供读者参考,不得用于任何商业行为
*
* 文件名称: TCPServer_CE.cpp
* 文件标识:
* 摘要:用于封装TCP 服务端通讯
*
* 当前版本: 1.0
* 作者: 汪兵 Eric Wong
* 完成日期: 2008年1月19日
*
* 取代版本:
* 原作者:
* 完成日期:
----------------------------------------*/
#include "StdAfx.h"
#include "TCPServer_CE.h"
#include "TCPCustom_CE.h"
#include <afxtempl.h>
//存储客户端Socket句柄
CPtrList m_ListClientSocket;
//构造函数
CTCPServer_CE::CTCPServer_CE()
{
//创建线程退出事件句柄
m_exitThreadEvent = CreateEvent(NULL,FALSE,FALSE,L"EVENT_SERVER_THREAD_QUIT");
//客户端连接建立事件,回调函数
OnClientConnect = NULL;
//客户端连接断开事件,回调函数
OnClientClose = NULL;
//客户端接收数据事件,回调函数
OnClientRead = NULL;
//客户端发生错误事件,回调函数
OnClientError = NULL;
//服务器端发生错误事件,回调函数
OnServerError = NULL;
}
//析构函数
CTCPServer_CE::~CTCPServer_CE()
{
//关闭线程退出事件句柄
CloseHandle(m_exitThreadEvent);
}
/*-----------------------------------------------------------------
【函数介绍】: 此线程用于检测监听套接字事件。
【入口参数】: lparam:无类型指针,可以通过此参数,向线程中传入需要用到的资源。
在这里我们将CTCPServer_CE类实例指针传进来
【出口参数】: (无)
【返回 值】: 返回值没有特别的意义,在此我们将返回值设为0。
------------------------------------------------------------------*/
DWORD CTCPServer_CE::SocketThreadFunc(PVOID lparam)
{
CTCPServer_CE *pSocket;
//得到CTCPServer_CE实例指针
pSocket = (CTCPServer_CE*)lparam;
//定义读事件集合
fd_set fdRead;
int ret;
TIMEVAL aTime;
aTime.tv_sec = 1;
aTime.tv_usec = 1;
while (TRUE)
{
//收到退出事件,结束线程
if (WaitForSingleObject(pSocket->m_exitThreadEvent,0) == WAIT_OBJECT_0)
{
break;
}
FD_ZERO(&fdRead);
FD_SET(pSocket->m_ServerSocket,&fdRead);
//监听事件
ret = select(0,&fdRead,NULL,NULL,&aTime);
if (ret == SOCKET_ERROR)
{
//触发错误事件
int iErrorCode = WSAGetLastError();
//触发服务器socket的错误事件
if (pSocket->OnServerError)
{
pSocket->OnServerError(pSocket->m_pOwner,pSocket,iErrorCode);
}
//关闭服务器套接字
closesocket(pSocket->m_ServerSocket);
break;
}
if (ret > 0)
{
//判断是否读事件
if (FD_ISSET(pSocket->m_ServerSocket,&fdRead))
{
//如果调用了Listen,则表示触发了OnAccept事件
SOCKADDR_IN clientAddr;
CTCPCustom_CE * pClientSocket = new CTCPCustom_CE();
int namelen = sizeof(clientAddr);
//等待,创建与客户端连接的套接字
pClientSocket->m_socket = accept(pSocket->m_ServerSocket, (struct sockaddr *)&clientAddr, &namelen);
//接收到客户端连接
if (pClientSocket->m_socket)
{
pClientSocket->m_RemoteHost = inet_ntoa(clientAddr.sin_addr);
pClientSocket->m_RemotePort = ntohs(clientAddr.sin_port);
//触发与客户端建立连接事件
if (pSocket->OnClientConnect)
{
pSocket->OnClientConnect(pSocket->m_pOwner,pClientSocket);
}
//打开pClientSocket服务线程
pClientSocket->Open(pSocket);
//添加到客户端连接队列中
m_ListClientSocket.AddTail(pClientSocket);
}
else
{
//失败,释放内存
delete pClientSocket;
pClientSocket = NULL;
}
}
}
}
//
TRACE(L"服务器端线程退出\n");
return 0;
}
//删除客户端
void CTCPServer_CE::RemoteClient(CTCPCustom_CE *pClient /*客户端对象*/)
{
POSITION posPrior;
POSITION pos = m_ListClientSocket.GetHeadPosition();
while (pos != NULL)
{
posPrior = pos;
CTCPCustom_CE *pTcpCustom = (CTCPCustom_CE*)m_ListClientSocket.GetNext(pos);
if (pTcpCustom == pClient)
{
//释放内存
delete pTcpCustom;
pTcpCustom = NULL;
m_ListClientSocket.RemoveAt(posPrior);
TRACE(L"移出了一个客户端对象\n");
break;
}
}
}
/*------------------------------------------------------------------
【函数介绍】: 打开TCP服务
【入口参数】: (无)
【出口参数】: (无)
【返回 值】: <=0:打开TCP服务失败; =1:打开TCP服务成功
------------------------------------------------------------------*/
int CTCPServer_CE::Open()
{
WSADATA wsa;
//1.初始化socket资源
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
return -1;//代表失败
}
//2.创建监听套接字
if ((m_ServerSocket=socket(AF_INET, SOCK_STREAM, 0))<0)
{
return -2;
}
SOCKADDR_IN serverAddr;
ZeroMemory((char *)&serverAddr,sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(m_LocalPort);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//3.绑定监听套接字
if (bind(m_ServerSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr))<0)
{
return -3 ;
}
//4.监听套接字开始监听
if (listen(m_ServerSocket,8)!=0)
{
return -3;
}
//4.设置监听套接字通讯模式为异步模式
DWORD ul= 1;
ioctlsocket(m_ServerSocket,FIONBIO,&ul);
ResetEvent(m_exitThreadEvent);
//5.创建通讯线程,在线程里,等待客户端接入
m_serverThreadHandle = CreateThread(NULL,0,SocketThreadFunc,this,0,NULL);
if (m_serverThreadHandle == NULL)
{
closesocket(m_ServerSocket);
return -1;
}
return 1;
}
/*-----------------------------------------------------------------
【函数介绍】: 关闭TCP服务
【入口参数】: (无)
【出口参数】: (无)
【返回 值】: <=0:关闭TCP服务失败; =1:关闭TCP服务成功
------------------------------------------------------------------*/
int CTCPServer_CE::Close()
{
//结束通讯线程
SetEvent(m_exitThreadEvent);
//等待1秒,如果读线程没有退出,则强制退出
if (WaitForSingleObject(m_serverThreadHandle,1000) == WAIT_TIMEOUT)
{
TerminateThread(m_serverThreadHandle,0);
TRACE(L"强制终止服务器端线程\n");
}
m_serverThreadHandle = NULL;
//关闭Socket,释放资源
int err = closesocket(m_ServerSocket);
if (err == SOCKET_ERROR)
{
return -1;
}
//首先,关闭与所有客户端连接
POSITION pos = m_ListClientSocket.GetHeadPosition();
while (pos != NULL)
{
//得到客户端对象
CTCPCustom_CE *pTcpCustom = (CTCPCustom_CE*)m_ListClientSocket.GetNext(pos);
if (!pTcpCustom->Close())
{
TRACE(L"关闭客户端socket错误");
}
//释放内存
delete pTcpCustom;
pTcpCustom = NULL;
}
m_ListClientSocket.RemoveAll();
WSACleanup();
return 1;
}
/*-----------------------------------------------------------------
【函数介绍】: 发送数据
【入口参数】: pCustomCE :客户端对象指针
buf : 缓冲区
dwBufLen : 缓冲区长度
【出口参数】: (无)
【返回 值】: TRUE : 发送成功 ; FALSE : 发送失败
------------------------------------------------------------------*/
BOOL CTCPServer_CE::SendData(CTCPCustom_CE* pCustomCE, const char * buf , DWORD dwBufLen)
{
BOOL bResult = FALSE;
BOOL bExisted = FALSE;
if (pCustomCE == NULL)
{
return FALSE;
}
//判断此客户端是否存在
POSITION pos = m_ListClientSocket.GetHeadPosition();
while (pos != NULL)
{
CTCPCustom_CE *pTcpCustom = (CTCPCustom_CE*)m_ListClientSocket.GetNext(pos);
if (pCustomCE == pTcpCustom)
{
bExisted = TRUE;
break;
}
}
if (!bExisted)
{
return FALSE;
}
bResult = pCustomCE->SendData(buf,dwBufLen);
if (!bResult)
{
//
RemoteClient(pCustomCE);
}
return bResult;
}
几个很好的wince下UDP、TCP通信程序源码
在Windows CE (Wince)操作系统环境下,网络通信是应用程序开发中的关键部分,特别是对于设备间的交互和数据传输。本文将详细解析标题为“几个很好的wince下UDP、TCP通信程序源码”的资源,以及其中涉及的TCP和UDP通信基础知识。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它确保了数据的顺序传输和错误检查,通过三次握手建立连接,并在传输完成后通过四次挥手断开连接。在提供的源码中,`TCPServer_CE.cpp`和`TCPClient_CE.cpp`可能分别实现了TCP服务器端和客户端的功能。服务器端负责监听连接请求,接收并处理来自客户端的数据,而客户端则用于建立与服务器的连接,发送和接收数据。 UDP(User Datagram Protocol)是无连接的、不可靠的传输层协议,它的主要特点是速度快,但不保证数据包的顺序或到达。在某些实时性要求高的应用场景,如视频流传输,UDP更为适用。源码中的`TCPCustom_CE.cpp`可能是实现了基于UDP的通信功能,它可能包含创建数据报套接字,发送和接收数据报的函数。 从描述中提到的类来看,`TCPCustom_CE`、`TCPClient_CE`和`TCPServer_CE`是基础通信类,可能封装了TCP或UDP通信的常见操作,如连接、断开、数据发送和接收等。这些类的设计可能遵循面向对象编程原则,使得开发者可以通过简单的调用方法来实现网络通信功能,降低了学习和使用的难度。 `TCPClientDlg.cpp`和`TCPServerDlg.cpp`可能包含了与用户交互的对话框控件,例如设置服务器地址、端口,查看发送和接收的数据等。`TCPClientDlg.h`和`TCPServerDlg.h`则是对应的头文件,定义了对话框类的接口和成员变量。`TCPCustom_CE.h`、`TCPClient_CE.h`和`TCPServer_CE.h`是通信类的头文件,它们包含了类的声明和可能的常量、枚举类型、结构体等。 这个源码集合提供了一套基础的Windows CE环境下的TCP和UDP通信实现,对于初学者来说,通过学习和分析这些源码,可以深入理解网络通信的基本原理和实践技巧,包括如何建立连接、发送和接收数据,以及如何处理连接异常等。同时,源码中封装的类和对话框设计也为实际项目开发提供了可复用的组件。通过动手实践,开发者能够快速掌握网络编程的关键技能,为后续的嵌入式系统开发打下坚实的基础。
- 1
- #完美解决问题
- #运行顺畅
- #内容详尽
- #全网独家
- #注释完整
- yx12062015-06-14非常详细的tcp通信基础学习,不错。
- supersegafan2013-04-16谢谢,不过好像和书上的例子有点出入。
- h2451566592014-06-30mfc 的源码
- Jason-252012-12-02mfc 的源码,非常详细的TCP通信基础类使用实例,感谢分享!
- czmagic2012-09-27下载了,但是我还没学会wince开发。装了个vs2010,结果发现不支持wince开发,郁闷。。。
- 粉丝: 0
- 资源: 3
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于PI电流控制器的三相永磁同步电动机矢量控制仿真研究(MATLAB SIMULINK模型)及结果分析报告,基于PI电流控制器的PMSM矢量控制 MATLAB SIMULINK仿真模型(2018b)及
- 基于转子磁链定向的异步电动机矢量控制系统MATLAB仿真模型详解及性能分析,基于转子磁链定向的异步电动机矢量控制系统 MATLAB SIMULINK仿真模型(2018b)及说明报告,仿真结果良好 报
- 2025医疗“三基三严”知识考试题库及参考答案.pptx
- 2025专业技术人员继续教育公需课题库(含答案).ppt
- 2025中小学教师编制考试教育理论基础知识必刷题库(含答案).ppt
- 2025羽毛球知识竞赛题库及答案.pptx
- 2025院前外伤的处理考核试题及答案.pptx
- 2025预防网络诈骗专项培训考试题库(含答案).pptx
- 2025职业教育知识竞赛题库(含答案).pptx
- 2025中华传统文化国学知识竞赛题库及答案.pptx
- 2025职业卫生技术人员评价方向考试题库(含答案).pptx
- 2025中小学教师编制考试教育理论基础知识必刷题库及答案.pptx
- 2025中小学教师编制考试理论基础知识复习题库(含答案).pptx
- 2025专业技术人员继续教育公需课题库(附含答案).pptx
- 2025专业技术人员继续教育公需课试题库(含答案).pptx
- 2025装载机理论考试试题库(含答案).pptx