2014-04-01 146 views
0

我使用的是winsocks,我编写的是IDS/Honeypot,这只是它的一小部分,因为此刻我希望服务器侦听多个套接字(7)并接受连接,但我试图动态创建一个数组(和听众等)的套接字,但我仍然遇到麻烦 - 我尝试了多种方式,但到目前为止,我设法做的就是让它成功地运行在一个套接字上,并且监听所有套接字,但不接受它们。创建多个侦听套接字

所以,这是我的最后一次尝试,但不确定,也许我需要使用线程或声明不同的套接字?

到目前为止,在这个小测试代码,我想:

初始化服务器 监听所有7个端口(1111,2222 ...等) 接受其中的任何 显示两个消息传入的连接在客户机/服务器 断开连接 并继续

这是一个有点草率,我知道,但这里是到目前为止的代码,我想你可以看到我用它去:

#include <iostream> 
#include <winsock2.h> 
#include <string> 
#pragma comment(lib, "ws2_32.lib") 

int main() 
{ 
    std::cout<<"Honeypot server [test #1] by Dreamwalker"<<std::endl; 
    WSADATA wsa; 
    SOCKET s[7] , new_socket[7]; 
    struct sockaddr_in server , client; 
    int c, port[7] = {1111,2222,3333,4444,5555,6666,7777}; 
    char *message; 

    std::cout<<"\nInitialising Winsock and other components..."; 
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) 
    { 
     std::cout<<"Failed. Error Code :"<<WSAGetLastError()<<std::endl; 
     return 1; 
    } 


    //!IMPORTANT: create multiple new sockets on different ports 
    int i = 0; 
    for(i = 0; i < 7; i++) 
    { 

    //Create socket 
    if((s[i] = socket(AF_INET , SOCK_STREAM , 0)) == INVALID_SOCKET) 
    { 
     std::cout<<"Could not create socket : "<< WSAGetLastError()<<std::endl; 
    }  

    //Prepare the sockaddr_in structure 
    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(port[i]); 

    //Bind 
    if(bind(s[i] ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) 
    { 
     std::cout<<"Bind failed with error code : "<< WSAGetLastError()<<std::endl; 
    } 


    /*!ALL CREATION CHECKING DONE, now create multiple sockets on the server 
    and listen for connections*/ 

    c = sizeof(struct sockaddr_in); 
    listen(s[i] , SOMAXCONN); 

    } 

    ///ALL INITIALIZED 
    std::cout<<"DONE!"<<std::endl; 

    //Listen/accept incoming connections 
    std::cout<<"Now listening for connections"<<std::endl; 

    new_socket[i] = accept(s[i] , (struct sockaddr *)&client, &c); 

     if (new_socket[i] == INVALID_SOCKET) 
     { 
     std::cout<<"accept failed with error code : "<< WSAGetLastError()<<std::endl; 
     } 

    //Accepted connection 
     else{ 
    std::cout<<"Someone has connected to this machine!"<<std::endl; 
    message = "Hello Client , I have received your connection.\n"; 
    send(new_socket[i] , message , strlen(message) , 0); 
    closesocket(s[i]); 
     } 

     std::cout<<"FINISHED"<<std::endl; 

    WSACleanup(); 
    getchar(); 
    return 0; 
} 

而现在它抛出一个运行时错误,以及:

WSAENOTSOCK 
10038 

Socket operation on nonsocket. 
An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, 

或选择,一个FD_SET的成员无效。

哪个(包括调试)表明在数组上创建时,套接字没有正确声明?

回答

2

你的代码创建/绑定/听都很好。然后:

new_socket[i] = accept(s[i] , (struct sockaddr *)&client, &c); 

首先,在这个时间运行你的循环之外,并i是7这是过去插座的阵列,这是到底为什么你得到的不是-A-套接字错误。

其次,accept()是一个阻塞呼叫,因此您不能像listen那样在同一线程的所有套接字上调用accept()。您需要为每个端口在accept()中设置一个单独的线程块,或者使用例如TCP/IP查找正在进行客户端连接尝试的客户端连接。 select(或epoll - 没有Windows系统有吗?),然后accept()对特定的套接字客户端(但后来你还有要么创建一个线程来处理客户端read/recv S和write/send S或使用select/epoll找出何时有输入准备好到read,或输出缓冲区中有更多空间用于传输)。如果您使用select/epoll,也有一个竞争条件 - 监听套接字可能表示接受客户端连接准备就绪,但在您拨打accept()时,连接尝试失败并被遗忘,然后如果监听套接字没有被设置为非阻塞模式,它会挂在那里等待另一个客户端连接到特定的套接字。恕我直言,这是一个线程实际上更容易的情况。

我认为使用IO Completion Ports(你可能想要谷歌)更“Windowsy”,但AFAIK它们是完全不可移植的。 Winsock与BSD套接字不完全匹配,但移植或双重支持的努力很小。

+0

如果不打算使用多线程,最好使用'ioctlsocket(..,FIONBIO,..)'将套接字置于非阻塞模式(请参阅http://msdn.microsoft.com/library/default.asp?url=1)。 com/en-us/library/windows/desktop/ms738573(v = vs.85).aspx)。然后,只要像'accept'这样的电话会导致等待,它就会返回'WSAEWOULDBLOCK' – MicroVirus

+0

@MicroVirus:非常真实......我只是在编辑中提到了这一点,但是拥有更多的Windows特定细节和链接。干杯。 –