C++ WIndows 2012上服务中的套接字连接问题

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

我继承了一个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;
}
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)。你能详细说明一下你是如何解决的吗?有没有办法禁用强化规则?