【C++】请教下服务端获取客户端IP的问题,附上代码

yann2 2018-05-04 11:49:11
//定义
//--------------------------------
typedef DWORD(WINAPI *_GetExtendedTcpTable)
(
PVOID pTcpTable,
PDWORD pdwSize,
BOOL bOrder,
ULONG ulAf,
TCP_TABLE_CLASS TableClass,
ULONG Reserved
);
static _GetExtendedTcpTable pGetExtendedTcpTable = NULL;

//初始化
//---------------------------------------
HMODULE hIpDLL = LoadLibrary(_T("iphlpapi.dll"));
pGetExtendedTcpTable = (_GetExtendedTcpTable)GetProcAddress(hIpDLL, "GetExtendedTcpTable");

//代码(获取所有链接到本机指定端口的IP信息)
//----------------------------------------
MIB_TCPTABLE_OWNER_PID* pBufTCP = NULL;
DWORD dwBufTCP = 0;
pGetExtendedTcpTable(pBufTCP, &dwBufTCP, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0);
pBufTCP = (MIB_TCPTABLE_OWNER_PID*)new BYTE[dwBufTCP];

if (NO_ERROR == pGetExtendedTcpTable(pBufTCP, &dwBufTCP, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0))
{
char strState[50];
struct in_addr inadLocal, inadRemote;
DWORD dwRemotePort = 0;
char szLocalIp[50];
char szRemIp[50];
char szItemText[MAX_PATH] = {0};

UINT uStatus = 0xFF;
for (UINT i = 0; i < pBufTCP->dwNumEntries; i++)
{
switch (pBufTCP->table[i].dwState)
{
case MIB_TCP_STATE_CLOSED:
uStatus = MIB_TCP_STATE_CLOSED;
break;
case MIB_TCP_STATE_TIME_WAIT:
uStatus = MIB_TCP_STATE_TIME_WAIT;
break;
case MIB_TCP_STATE_LAST_ACK:
uStatus = MIB_TCP_STATE_LAST_ACK;
break;
case MIB_TCP_STATE_CLOSING:
uStatus = MIB_TCP_STATE_CLOSING;
break;
case MIB_TCP_STATE_CLOSE_WAIT:
uStatus = MIB_TCP_STATE_CLOSE_WAIT;
break;
case MIB_TCP_STATE_FIN_WAIT1:
uStatus = MIB_TCP_STATE_FIN_WAIT1;
break;
case MIB_TCP_STATE_ESTAB:
uStatus = MIB_TCP_STATE_ESTAB;
break;
case MIB_TCP_STATE_SYN_RCVD:
uStatus = MIB_TCP_STATE_SYN_RCVD;
break;
case MIB_TCP_STATE_SYN_SENT:
uStatus = MIB_TCP_STATE_SYN_SENT;
break;
case MIB_TCP_STATE_LISTEN:
uStatus = MIB_TCP_STATE_LISTEN;
break;
case MIB_TCP_STATE_DELETE_TCB:
uStatus = MIB_TCP_STATE_DELETE_TCB;
break;
default:
uStatus = 0xFF;
break;
}

//已关闭的链接略过
if(uStatus == MIB_TCP_STATE_CLOSED || uStatus == MIB_TCP_STATE_CLOSING) continue;

inadLocal.s_addr = pBufTCP->table[i].dwLocalAddr;

if (strcmp(strState, "LISTEN") != 0)
{
dwRemotePort = pBufTCP->table[i].dwRemotePort;
}
else
dwRemotePort = 0;

//校验端口
u_short uPortCondion = u_short( wPort );
u_short uPortRead = ntohs((unsigned short)(0x0000FFFF & pBufTCP->table[i].dwLocalPort));
if(uPortCondion != uPortRead) continue;

//得到对方IP
inadRemote.s_addr = pBufTCP->table[i].dwRemoteAddr;
memset(szRemIp, sizeof(szRemIp), 0);
strcpy(szRemIp, inet_ntoa(inadRemote));
TCHAR *pszRemIP = CharToTChar(szRemIp);
if(!pszRemIP) continue;

//放入内存
保存这些IP[pszRemIP]到内存

delete[] pszRemIP; pszRemIP = NULL;
}
}

delete[] pBufTCP; pBufTCP = NULL;


=======================================================
=======================================================
=======================================================

以上是我获取本机指定端,例如1234这个端口,所有链接到这个端口的IP地址,这里是没问题的。
问题是下面

//IOCP服务端【用户连接线程】
//-----------------------------------------
while( WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0) )
{
LPSOCKET_INFORMATION sClientObj = new SOCKET_INFORMATION;
if( (sClientObj->Socket = WSAAccept(m_ListenSocket, (SOCKADDR*)&ClientAddr, &addr_length, NULL, 0)) != SOCKET_ERROR )
{
.....
//保存链接进来的客户端IP地址
//问题就在这里,所有链接进来的客户端IP我都保存了
char *pszIP = inet_ntoa(ClientAddr.sin_addr);
}
}

//BUG现象
//------------------------------------------

服务端保存下来链接进来的IP地址为列表A
上面获取本机指定端口链接的IP为列表B

遍历列表B,然后拿IP去列表A中去查找,结果发现,有小部分IP查询不到!!
比如列表B在1234这个端口得到100个连进来的IP,其中有20多个IP在列表A中查询不到!!

客户端连接到1234端口并不是我的客户端软件去链接,是其他软件,但是客户端都有再多开一个客户端软件,去链接我的服务端,也就是说客户端其他软件连接到1234端口后,多开出来的那个软件都有链接到我的服务端,所以理论说列表A和列表B的IP数量是同步的。

这个BUG困扰我几天了,一直找不到解决办法。。

下面是我最后一次通过对比得出来查询不到的IP:
111.42.30.7
111.44.141.15
111.56.42.206
112.12.31.156
122.190.94.122
122.190.94.125
122.190.94.128
122.190.94.130
122.190.94.140
122.190.94.186
122.190.94.190
122.191.204.109
124.160.153.55
183.198.47.59
183.232.25.133
218.201.223.186
220.203.63.63
223.67.168.108
61.148.103.146

并没有发现有什么不妥的地方,不明白为什么就是总有一部分人IP查询不到。

他们都没有开代理,都是直接连接。

还望各位大神指点迷津,十分感谢!!!!!!!
...全文
1376 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
smwhotjay 2018-05-05
  • 打赏
  • 举报
回复
我的理解GetExtendedTcpTable 不准确。 WSAAccept 准确
yann2 2018-05-05
  • 打赏
  • 举报
回复
引用 4 楼 zgl7903 的回复:
似乎只处理了 accept, 是否是客户端已经关闭了连接? 是否还应该处理关闭,然后从列表中也剔除?
不会,因为accept后已经保存了他的IP,即使他断开了 我IP也记录过了。 并且是每10秒自动判断 如果断开了会自动重连
zgl7903 2018-05-05
  • 打赏
  • 举报
回复
似乎只处理了 accept, 是否是客户端已经关闭了连接? 是否还应该处理关闭,然后从列表中也剔除?
yann2 2018-05-05
  • 打赏
  • 举报
回复
引用 2 楼 smwhotjay 的回复:
我的理解GetExtendedTcpTable 不准确。 WSAAccept 准确
因为列表A的获取办法只能通过这个办法获取,因为不是我自己的程序,客户端连接到列表A以后 会再开一个软件 这个软件才会链接到我的服务端 以便我获取到列表B 而且测试中,GetExtendedTcpTable获取的IP列表应该是对的,在查询时,比如发现某IP,列表A中有,列表B中没有 然后我通过策略的办法禁止这个IP访问,那边客户端就连不上了,说明IP是对的。
yann2 2018-05-04
  • 打赏
  • 举报
回复
分不够了,解决一定追加分,给大伙散分,哪怕充值C币,等待大神解答,感谢!!

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧