C++ WIndows 2012上服务中的套接字连接问题
我继承了一个C++/Windows项目,其中有一个SNMP扩展代理(由SNMP服务加载)。在代理内部,我们正在创建一个简单的TCP服务器,我们的客户端应用程序将连接到该服务器,并为其提供用于SNMP查询/陷阱等的数据。这一切在Windows 2008上似乎都可以正常工作。但是,在Windows 2012上,客户端无法再连接到代理内部运行的服务器(在SNMP服务中)。connect()失败,错误为10013 我的服务器代码如下所示:C++ WIndows 2012上服务中的套接字连接问题,c++,sockets,tcp,snmp,windows2012,C++,Sockets,Tcp,Snmp,Windows2012,我继承了一个C++/Windows项目,其中有一个SNMP扩展代理(由SNMP服务加载)。在代理内部,我们正在创建一个简单的TCP服务器,我们的客户端应用程序将连接到该服务器,并为其提供用于SNMP查询/陷阱等的数据。这一切在Windows 2008上似乎都可以正常工作。但是,在Windows 2012上,客户端无法再连接到代理内部运行的服务器(在SNMP服务中)。connect()失败,错误为10013 我的服务器代码如下所示: fd_set master_set; fd_set read
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;
}
fd_集主_集;
fd_设置读取FDS;
套接字侦听器;
WSADATA WSADATA;
int-iResult=WSAStartup(MAKEWORD(2,2)和wsaData);
如果(iResult!=无错误)
{
OutputDebugStringA(“WSAStartup失败\n”);
返回-1;
}
FD_零点和主_集);
FD_零(&readfds);
//----------------------
//创建用于侦听的套接字
//传入的连接请求。
侦听器=套接字(AF_INET、SOCK_STREAM、IPPROTO_TCP);
if(侦听器==无效的\u套接字){
OutputDebugStringA(“套接字失败,错误:\n”);
返回-1;
}
int reuse_addr=1;
setsockopt(监听器,SOL_套接字,SO_REUSEADDR,(char*)和reuse_addr,sizeof(reuse_addr));
//----------------------
//结构中的sockaddr_指定地址族,
//要绑定的套接字的IP地址和端口。
服务中的sockaddr_={0};
service.sinu family=AF\u INET;
service.sin_addr.s_addr=inet_addr(“127.0.0.1”);
service.sinu port=htons(27015);
if(绑定(侦听器,(SOCKADDR*)和服务,sizeof(服务))==SOCKET\u错误)
{
printf(“绑定失败,错误:%d\n”,WSAGetLastError());
closesocket(监听器);
返回-1;
}
如果(侦听器,5)=套接字错误)
{
OutputDebugStringA(“侦听失败,出现错误\n”);
closesocket(监听器);
返回-1;
}
u_long NonBlock=1;
if(ioctlsocket(侦听器、FIONBIO和非块)=套接字错误)
{
OutputDebugStringA(“ioctlsocket()失败,出现错误\n”);
返回-1;
}
FD_集(侦听器和主_集);
timeval超时;
timeout.tv_sec=3;
timeout.tv_usec=0;
printf(“已在端口%d上启动服务器”,27015);
对于(;;)
{
readfds=主数据集;
int ret=select(0,&readfds,NULL,NULL,&timeout);
如果(ret==0)
{
//超时//检查是否需要关机
继续;
}
如果(ret<0)
{
printf(“套接字选择错误”);
返回-1;
}
对于(int i=0;i 如果((recv_bytes=recv(fd,buffer,16,0))我解决了该问题。该问题是由于Windows服务强化导致的,它不允许来自snmp服务(和扩展)的任何TCP通信。即使防火墙关闭,也会强制执行此操作
我可以按照以下步骤解决它(在中找到)
以管理员身份登录系统,并通过在命令提示符下发出regedit打开注册表
导航到[HKEY\U LOCAL\U MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\Static\SYSTEM]
找到满足以下几点的值:
a、 “Name”字符串以“SNMP-”开头。
b、 “数据”字符串包含“syswow64\snmp.exe”。
c、 “数据”字符串包含“动作=块”
将这些条目的“Action=Block”更改为“Action=Allow”
通过发出net stop MPSSVC和net start MPSSVC重新启动“Windows防火墙”服务
使用网络停止SNMP和网络启动SNMP重新启动“SNMP服务”服务
不要直接使用readfds
结构,使用FD_ISSET
宏检查套接字是否在集合中。此外,不要以这种方式循环集合,而是保存连接套接字的列表并仅检查它们。特别是因为在尝试处理它们之前,实际上不检查套接字是否有事件。您考虑过吗查找Winsock错误10013?感谢您的评论。是的,我查找了10013,它是WSAEACCESS:权限被拒绝。试图以其访问权限所禁止的方式访问套接字。例如,在未使用setsockopt(SO_broadcast)设置广播权限的情况下使用发送到的广播地址。WSAEACCES错误的另一个可能原因是调用bind函数时(在使用SP4和更高版本的Windows NT 4.0上),另一个应用程序、服务或内核模式驱动程序通过独占访问绑定到同一地址。这种独占访问是Windows NT 4.0 SP4及更高版本的一项新功能,并通过使用SO_exclusiveAdruse选项来实现。@JoachimPileborg我也用FD_ISSET()尝试过(在我的原始代码中仍然存在)然而,对于我来说,真正的问题是select()总是返回0,这意味着超时(FD_ISSET()返回false)。你能详细说明一下你是如何解决的吗?有没有办法禁用强化规则?