#include "stdafx.h"
#include "Net.h"
using namespace netcomm;
/*********************************************************************************************************************
2009-3-12 增加了OnReceiveBegin, OnReceiveEnd接口
修改了接收数据的逻辑: 按块接收数据, 当发送方发来一块数据时, 首先OnReceiveBegin会被调用以通知该块数据的大小,
接着OnReceive会被调用以接收实际的数据, 由于本程序接收缓冲区是固定有限的,为4096字节,因此OnReceive可能会被调
用多次. 这个次数为大于等于值(发送方数据块大小除以4096)的最小整数.当全部块数据接收完成时,会调用OnReceiveEnd
来通知程序
2009-3-18 因考虑到异步接受连接,可能还有未决的套接字, 当接受出错错误时,应该关闭套接字.因此增加了InsertSocketObjToPendingAcceptList,
RemoveSocketObjFromPendingAcceptList,FreeAllPendingAcceptSocketObj三个函数来处理这一问题
*********************************************************************************************************************/
CNet::CNet():
m_bStart(FALSE),
m_bStop(FALSE)
{
}
CNet::~CNet()
{
}
//////////////////////////////////////////////////////////////////////////
/**
* @brief 启动服务
* 绑定端口, 开始监听接受连接
@param wPort 监听端口
@return TRUE表示启动服务成功,FALSE表示启动失败
*/
//////////////////////////////////////////////////////////////////////////
BOOL CNet::Start(WORD wPort)
{
if (m_bStart)
{
return FALSE;
}
m_bStop = FALSE;
// 创建监听套节字,绑定到本地端口,进入监听模式
SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN si;
si.sin_family = AF_INET;
si.sin_port = ::ntohs(wPort);
si.sin_addr.S_un.S_addr = INADDR_ANY;
if(::bind(sListen, (sockaddr*)&si, sizeof(si)) == SOCKET_ERROR)
{
TRACE("bind Failed %d \n", WSAGetLastError());
closesocket(sListen);
m_bStart = FALSE;
return FALSE;
}
::listen(sListen, 100);
PSOCKET_OBJ pSocketObj = AllocSocketObj(sListen);
if (NULL == pSocketObj)
{
closesocket(sListen);
return FALSE;
}
memcpy(&pSocketObj->addr, &si, sizeof(si));
// 加载扩展函数AcceptEx
GUID GuidAcceptEx = WSAID_ACCEPTEX;
DWORD dwchars;
int rc = WSAIoctl(pSocketObj->s,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&GuidAcceptEx,
sizeof(GuidAcceptEx),
&pSocketObj->lpfnAcceptEx,
sizeof(pSocketObj->lpfnAcceptEx),
&dwchars,
NULL,
NULL);
if (SOCKET_ERROR == rc)
{
TRACE("WSAIoctl GET_EXTENSION_FUNCTION_POINTER Failed %d \n", WSAGetLastError());
FreeSocketObj(pSocketObj);
return FALSE;
}
PBUFFER_OBJ pBufferObj = AllocBufferObj(pSocketObj);
if (NULL == pBufferObj)
{
FreeSocketObj(pSocketObj);
return FALSE;
}
if (!AssignToIoThread(pBufferObj))
{
FreeSocketObj(pSocketObj);
return FALSE;
}
if (!PostAccept(pBufferObj))
{
FreeSocketObj(pSocketObj);
RemoveBufferObjFromThread(pBufferObj);
return FALSE;
}
InsertSocketObjToPendingAcceptList(pBufferObj->s);
InsertSocketObjToListenList(pSocketObj);
m_bStart = TRUE;
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
/**
@brief 停止服务
* 关闭所有连接,退出工作线程,释放所有内存
*/
//////////////////////////////////////////////////////////////////////////
void CNet::Stop()
{
m_bStart = FALSE;
m_bStop = TRUE;
CloseAllListenSocketObj();
CloseAllConnection();
SignalAllThreadObj();
ExitAllThreadObj();
FreeAllListenSocketObj();
FreeAllPendingAcceptSocketObj();
FreeAllClientSocketObj();
FreeAllServerSocketObj();
FreeAllThreadObj();
}
//////////////////////////////////////////////////////////////////////////
/**
@brief 关闭所有连接
* 这些连接包括作为服务器与客户端的连接,作为客户端与服务器的连接
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::CloseAllConnection()
{
CloseAllClientSocketObj();
CloseAllServerSocketObj();
}
//////////////////////////////////////////////////////////////////////////
/**
使所有线程受信
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::SignalAllThreadObj()
{
InnerLock lock(m_cs_ThreadObjList);
for (ThreadObjIter iter = m_ThreadObjList.begin(); iter != m_ThreadObjList.end(); ++iter)
{
PTHREAD_OBJ pThreadObj = *iter;
SetEvent(pThreadObj->hExitEvent);
}
TRACE("SignalAllThreadObj, Thread = %d \n", m_ThreadObjList.size());
}
//////////////////////////////////////////////////////////////////////////
/**
退出所有线程
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::ExitAllThreadObj()
{
for (ThreadObjIter iter = m_ThreadObjList.begin(); iter != m_ThreadObjList.end(); ++iter)
{
ExitThreadObj(*iter);
}
}
//////////////////////////////////////////////////////////////////////////
/**
释放所有线程对象
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::FreeAllThreadObj()
{
TRACE("FreeAllThreadObj, Thread = %d \n", m_ThreadObjList.size());
for (ThreadObjIter iter = m_ThreadObjList.begin(); iter != m_ThreadObjList.end(); )
{
PTHREAD_OBJ pThreadObj = *iter;
iter = m_ThreadObjList.erase(iter);
FreeThreadObj(pThreadObj);
}
}
//////////////////////////////////////////////////////////////////////////
/**
关闭所有监听套接字
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::CloseAllListenSocketObj()
{
InnerLock lock(m_cs_ListenList);
for (SocketObjIter iter = m_ListenList.begin(); iter != m_ListenList.end(); ++iter)
{
PSOCKET_OBJ pSocketObj = *iter;
if (pSocketObj->s != INVALID_SOCKET)
{
closesocket(pSocketObj->s);
pSocketObj->s = INVALID_SOCKET;
}
}
}
//////////////////////////////////////////////////////////////////////////
/**
释放所有监听套接字对象
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::FreeAllListenSocketObj()
{
InnerLock lock(m_cs_ListenList);
for (SocketObjIter iter = m_ListenList.begin(); iter != m_ListenList.end(); )
{
PSOCKET_OBJ pSocketObj = *iter;
iter = m_ListenList.erase(iter);
FreeSocketObj(pSocketObj);
}
}
//////////////////////////////////////////////////////////////////////////
/**
向未决接受列表插入套接字
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::InsertSocketObjToPendingAcceptList(const SOCKET s)
{
ASSERT(s != INVALID_SOCKET);
InnerLock lock(m_cs_PendingAcceptList);
m_PendingAcceptList.push_back(s);
}
//////////////////////////////////////////////////////////////////////////
/**
从未决接受列表移除套接字
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::RemoveSocketObjFromPendingAcceptList(const SOCKET s)
{
ASSERT(s != INVALID_SOCKET);
InnerLock lock(m_cs_PendingAcceptList);
m_PendingAcceptList.remove(s);
}
//////////////////////////////////////////////////////////////////////////
/**
关闭所有未决接受套接字
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::FreeAllPendingAcceptSocketObj()
{
for (list<SOCKET>::iterator iter = m_PendingAcceptList.begin(); iter != m_PendingAcceptList.end(); )
{
closesocket((*iter));
iter = m_PendingAcceptList.erase(iter);
}
}
//////////////////////////////////////////////////////////////////////////
/**
向监听列表插入套接字对象
*/
//////////////////////////////////////////////////////////////////////////
inline void CNet::InsertSocketObjToListenList(const PSOCKET_OBJ pSocketObj)
{
ASSERT(pSocketObj);
InnerLock lock(m_cs_ListenList);
m_ListenList.push_back(pSocketObj);
}
//////////////////////////////////////////////////////////////////////////
/*
CTrace类 路由跟踪VC源码
4星 · 超过85%的资源 需积分: 0 176 浏览量
更新于2009-03-24
收藏 22KB RAR 举报
CTrace类是一个在VC2005环境下开发的专门用于路由跟踪的封装类。路由跟踪是网络诊断中常用的一种技术,它允许用户查看数据包在网络中的传输路径,从而帮助识别网络延迟或通信问题的原因。CTrace类实现了类似操作系统自带的`tracert.exe`(Windows系统下的traceroute命令)的功能,提供了格式化的跟踪信息输出。
让我们深入理解CTrace类的核心功能。CTrace类通常会包含一系列方法,如初始化、设置参数、发送ICMP(Internet Control Message Protocol)或UDP(User Datagram Protocol)数据包、解析返回的响应、以及输出跟踪结果等。这些方法的实现基于网络层的协议,如IP和ICMP,以及传输层的UDP协议。
1. **初始化**:在使用CTrace类之前,可能需要设置一些参数,如目标主机的IP地址、最大跳数、超时时间等。这些参数会影响到路由跟踪的效果和精度。
2. **发送数据包**:CTrace类会通过发送具有不同TTL(Time To Live)值的数据包来执行路由跟踪。每个数据包的TTL值会从1开始递增,直到到达目标主机。当数据包达到某个路由器时,其TTL值将被减一;如果TTL值降为零,路由器将回送一个ICMP“超时”消息,从而暴露其存在。
3. **解析响应**:接收到的ICMP响应包含发送者的IP地址,CTrace类会收集这些地址并按照它们出现的顺序排列,形成一个完整的路由路径。
4. **输出结果**:CTrace类的一个关键特性是其能够输出对齐和格式化的跟踪信息,使得用户可以清晰地看到每个跳点的IP地址、延迟时间以及可能的主机名。这与`tracert.exe`的输出非常相似,有助于分析网络性能和问题定位。
在提供的压缩包文件中,有两个文件:`netcomm`和`TestTraceroute`。`netcomm`可能是一个包含了网络通信相关功能的库或者模块,它可能包含了CTrace类所需要的一些底层网络操作函数,如发送和接收数据包。`TestTraceroute`则可能是一个示例程序,用于演示如何使用CTrace类进行路由跟踪,并展示其输出效果。
为了进一步学习和使用CTrace类,你需要了解以下几点:
- **网络基础知识**:理解IP协议、ICMP协议和UDP协议的工作原理,这对于理解CTrace类如何实现路由跟踪至关重要。
- **C++编程**:熟悉C++编程语言,特别是面向对象编程的概念,因为CTrace是一个类,需要通过对象实例来调用其方法。
- **Winsock编程**:了解Winsock API,这是在Windows系统下进行网络编程的标准接口,CTrace类可能依赖于它来实现网络通信。
通过对`TestTraceroute`源代码的分析,你可以看到CTrace类如何被使用,以及如何与`netcomm`库配合工作。同时,也可以学习到如何在实际项目中集成和应用路由跟踪功能。这不仅有助于提升网络诊断能力,也是深入理解网络编程和C++类设计的好机会。
qinshubo1984
- 粉丝: 5
- 资源: 25
最新资源
- 飞机、森林、河、网球场检测16-YOLO(v8至v11)数据集合集.rar
- PANGU盘古M900硬件资料包
- 飞机和飞机跑道检测14-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar
- 注册表监视器,时刻检查程序修改的地方,一切动作尽在掌控
- linux samba.
- redhad-lsb,安装磐维数据库,安装oracle数据库等常用的依赖包
- 飞机检测12-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord数据集合集.rar
- libpng,安装磐维数据库,安装oracle数据库等常用的依赖包
- 非常好的在线聊天系统源代码100%好用.zip
- redhat-lsb-core,安装磐维数据库,安装oracle数据库等常用的依赖包
- redhat-lsb-core,安装磐维数据库,安装oracle数据库等常用的依赖包
- 可以在mac下开发的微雪esp32触摸屏开发板的支持包
- redhat-lsb-submit-security,安装磐维数据库,安装oracle数据库等常用的依赖包
- glibc-devel,安装磐维数据库,安装oracle数据库等常用的依赖包
- iperf3.18 for win7 x64 +andriod +win X64
- 国产视频会议软件全套(适配麒麟、UOS等 适配ARM、X65、龙芯等CPU)