DWORD dwOwningPid;//关联的进程ID
} MIB_TCPROW_OWNER_PID, *PMIB_TCPROW_OWNER_PID;
int GetTcpConnect()
{
HMODULE hMod = LoadLibrary("Iphlpapi.dll");
if(!hMod)
{
AfxMessageBox("加载Iphlpapi.dll出错");
return 0;
}
PFNGetExtendedTcpTable pfnGetTcpTable =
(PFNGetExtendedTcpTable)::GetProcAddress(hMod,"GetExtendedTcpTable");//获取
函数地址
PMIB_TCPTABLE_OWNER_PID pTcpTable = new MIB_TCPTABLE_OWNER_PID;
DWORD dwSize = sizeof(MIB_TCPTABLE_OWNER_PID);
if (pfnGetTcpTable(pTcpTable, &dwSize,
TRUE,AF_INET,TCP_TABLE_OWNER_PID_ALL,0) == ERROR_INSUFFICIENT_BUFFER)
{//第一次调用时不知道要传入的缓冲区大小,所以要试探一下,参数dwSize会返
回真正需要的大小
delete pTcpTable;
pTcpTable = (MIB_TCPTABLE_OWNER_PID *)new char[dwSize];//重新分配缓
冲区
}
if(pfnGetTcpTable(pTcpTable,&dwSize,TRUE,AF_INET,TCP_TABLE_OWNER_PID_AL
L,0) != NO_ERROR)
{
AfxMessageBox("获取TCP连接出错");
delete pTcpTable;
return 0;
}
int nNum = (int) pTcpTable->dwNumEntries; //TCP连接的数目
for(int i=0;i<nNum;i++)
{
printf(“本地地址:%s:%d 远程地址:%s:%d 状态:%d 进程ID:%d”,
inet_ntoa(*(in_addr*)& pTcpTable->table[i].dwLocalAddr), //本地IP 地址
htons(pTcpTable->table[i].dwLocalPort), //本地端口
inet_ntoa(*(in_addr*)& pTcpTable->table[i].dwRemoteAddr), //远程IP地址
htons(pTcpTable->table[i].dwRemotePort), //远程端口
pTcpTable->table[i].dwState, //状态
pTcpTable->table[i].dwOwningPid); //所属进程PID
}
delete pTcpTable;
}
获取进程 ID 之后就可以获取进程名和路径了。我使用的是
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0)方法,在ROCESSENTRY32中没有进程的
路径信息,可以用 GetModuleFileNameEx 函数获得,或是通过
CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,nPId) 查找进程模块,出现的第一个模块
就是程序模块,路径存储在me32.szExePath中。这部分代码请参看我的源程序。
既然要模仿TcpView,当然要有进程图标了。一开始我选择去读取图标资源,但是这种
方法兼容性不好,比较麻烦,其实只要用ExtractIcon函数就好了。以下是提取代码:
遇到没有图标的程序可以使用系统默认的程序图标,只要调用
HICON GetExeIcon(CString strExe,int nIdx = 0)//获取第 nIdx+1 个图标,一般程序
将 nIdx 设为 0就可以了
{
if(strExe == "") return NULL;
HMODULE hExe = LoadLibrary(strExe);//把EXE 当二进制资源加载
if (hExe == NULL)
{
return NULL;
}
int nNum = (int)::ExtractIcon(hExe,strExe,-1);//获取图标数
if(nNum == 0) return NULL;
HICON hIcon = ::ExtractIcon(hExe,strExe,nIdx);//提取图标
FreeLibrary(hExe);//释放资源
return hIcon;
}
遇到没有图标的程序可以使用系统默认的程序图标,只要调用
GetExeIcon("shell32.dll",2)就好了。要在每一项前面显示图标,需要在视图类的定义中
添加图像列表指针 CImageList *m_pImgList,并在构造函数中初始化 m_pImgList = new
CImageList; m_pImgList->Create(16, 16, ILC_COLORDDB|ILC_COLOR32, 8, 8),然后在
List 添加列的同时将图像列表加入 List : m_list.SetImageList(m_pImgList,
LVSIL_SMALL)。获取图标句柄后调用m_pImgList->Add(hIcon),返回值为图标在 ImageList
中的索引,该索引即是InsertItem时设置的图标索引。
关闭 TCP 连接的方法是用 SetTcpEntry 函数设置连接的状态为:
MIB_TCP_STATE_DELETE_TCB,下面是具体代码:
MIB_TCPROW tcprow;
tcprow.dwLocalAddr = dwLocalIp;//本地 IP地址
tcprow.dwRemoteAddr = dwRemoteIp;//远程IP 地址
tcprow.dwLocalPort = ntohs(nLocalPort);//本地端口
tcprow.dwRemotePort = ntohs(nRemotePort);//远程端口
tcprow.dwState = MIB_TCP_STATE_DELETE_TCB;//删除连接
SetTcpEntry(&tcprow);
使用原始套接字可以监听到接收到的所有IP 数据包,只要分析TCP 包和 UDP 包的相关
信息就可以得到每个连接的流量信息。每个连接在内存中是以 UpDownInfo 结构体的形式存 |