我繼承了一個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