我继承了一个 C++/Windows 项目,其中我们有一个 SNMP 扩展代理(由 snmp 服务加载)。在代理内部,我们正在创建一个简单的 TCP 服务器,我们的客户端应用程序连接到该服务器并为其提供 SNMP 查询/陷阱等数据。这一切似乎在 Windows 2008 上运行良好。但是,在 Windows 2012 上,客户端不能再连接到在代理内部运行的服务器(在 SNMP 服务中)。connect() 失败并出现错误 10013。
我的服务器代码如下所示:
fd_set master_set;
fd_set readfds;
SOCKET listener;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
OutputDebugStringA("WSAStartup failed\n");
return -1;
}
FD_ZERO(&master_set);
FD_ZERO(&readfds);
//----------------------
// Create a SOCKET for listening for
// incoming connection requests.
listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listener == INVALID_SOCKET) {
OutputDebugStringA("socket failed with error:\n");
return -1;
}
int reuse_addr = 1;
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse_addr, sizeof(reuse_addr));
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service = { 0 };
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27015);
if (bind(listener, (SOCKADDR *)& service, sizeof(service)) == SOCKET_ERROR)
{
printf("bind failed with error: %d \n", WSAGetLastError());
closesocket(listener);
return -1;
}
if (listen(listener, 5) == SOCKET_ERROR)
{
OutputDebugStringA("listen failed with error\n");
closesocket(listener);
return -1;
}
u_long NonBlock = 1;
if (ioctlsocket(listener, FIONBIO, &NonBlock) == SOCKET_ERROR)
{
OutputDebugStringA("ioctlsocket() failed with error\n");
return -1;
}
FD_SET(listener, &master_set);
timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
printf("Started Server on port %d\n", 27015);
for (;;)
{
readfds = master_set;
int ret = select(0, &readfds, NULL, NULL, &timeout);
if (ret == 0)
{
// Time out // Check if we need to shutdown
continue;
}
if (ret < 0)
{
printf("Error in Socket select\n");
return -1;
}
for (int i = 0; i < readfds.fd_count; i++)
{
SOCKET xfd = readfds.fd_array[i];
if (xfd == listener)
{
// New Connection.
SOCKET new_fd = HandleNewConnection(listener);
if (new_fd == -1)
{
printf("Error Accepting new connection");
continue;
}
FD_SET(new_fd, &master_set);
printf("Accepted new Connection\n");
continue;
}
else
{
if (!HandleIncomingData(xfd))
{
closesocket(xfd);
FD_CLR(xfd, &master_set);
continue;
}
}
}
}
SOCKET HandleNewConnection(SOCKET listener)
{
SOCKET newfd = accept(listener, (sockaddr*)NULL, (int*)NULL);
u_long NonBlock = 1;
ioctlsocket(newfd, FIONBIO, &NonBlock);
return newfd;
}
bool HandleIncomingData(SOCKET fd)
{
char buffer[16] = { 0 };
int recv_bytes = -1;
if ((recv_bytes = recv(fd, buffer, 16, 0)) <= 0)
{
printf("Connection Closed/ Error in Recieving");
return false;
}
printf("recieved %d bytes\n", recv_bytes);
return true;
}
选择继续每 3 秒超时一次,没有任何连接被接受。
这是我尝试过的所有方法(没有奏效):
- 试图在特定用户帐户中运行服务。
- 服务器在一个单独的线程中运行,我提供了一个带有 NULL DACL 的 SECURITY_ATTRIBUTE 来查看它是否是一个安全问题。
- 尝试了不同的端口。
- 在单独的普通应用程序中尝试了相同的服务器代码。客户端可以连接到此应用程序。
- 从代理启动示例服务器应用程序时,客户端无法连接到它。
- Windows 防火墙已关闭,我没有安装任何会阻止此类连接的防病毒软件。
- 从外部检查连接并在 Wireshark 中观察到 TCP SYN 数据包确实到达但没有响应。
- 在 Process Explorer TCP/IP 属性中观察到 SNMP 服务确实具有侦听 127.0.0.1:27015 的 TCP 套接字。
对于快速测试,我只是对端口 27015 进行 telnet。
我的问题是:
- 我缺少的服务器代码是否有明显问题?
- Windows 2012 中是否存在一些不允许服务接受此类 TCP 连接的安全限制?
- 任何其他提示、评论、输入?
谢谢,