我继承了一个C++/Windows项目,其中有一个SNMP扩展代理(由snmp服务加载)。在代理内部,我们正在创建一个简单的TCP服务器,我们的客户端应用程序连接到该服务器并为其提供SNMP查询/陷阱等数据。这似乎在Windows 2008上运行良好。但是,在Windows 2012上,客户端无法再运行连接到代理中运行的服务器(在SNMP服务中)。在connect()失败,错误10013.WIndows 2012上的服务中的SOCKET连接问题
我的服务器代码看起来是这样的:
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中观察到SNMP服务确实拥有在127.0.0.1:27015上侦听的TCP套接字的TCP/IP属性。
对于快速测试我只是做的telnet端口27015.
我的问题是:
- 有什么明显错误与我缺少服务器端的代码?
- 在Windows 2012中是否存在一些不允许服务接受此类TCP连接的安全限制?
- 其他提示,评论,输入?
感谢,
不要直接使用'readfds'结构,使用'FD_ISSET'宏来检查套接字是否在集合中。另外,不要以这种方式遍历集合,而应保存连接套接字的列表并仅检查它们。特别是因为你实际上没有*检查*如果一个套接字有事件,然后试图处理它们。 –
你考虑过查找Winsock错误10013吗? – EJP
感谢您的意见。是的,我查了10013这是WSAEACCESS:权限被拒绝。 试图以禁止其访问权限的方式访问套接字。一个示例是使用sendto的广播地址,而不使用setsockopt(SO_BROADCAST)设置广播权限。 – user1688877