简体   繁体   English

创建多个监听套接字

[英]Create multiple listening sockets

I'm using winsocks and I am coding an IDS/Honeypot, this is just a small section of it, because at the moment I want the server to listen on multiple sockets (7) and accept the connections, but I've tried to dynamically create the sockets with an array (and the listener etc) but I am still having trouble - I've tried it multiple ways but so far, all I've managed to do is get it working successfully on ONE socket, and LISTEN to all sockets, but not accept them. 我正在使用Winsocks,正在编写IDS / Honeypot,这只是其中的一小部分,因为目前我希望服务器在多个套接字(7)上侦听并接受连接,但是我试图动态地使用数组(和侦听器等)创建套接字,但是我仍然遇到麻烦-我已经尝试了多种方法,但是到目前为止,我所要做的就是让它在一个套接字上成功工作,并进行监听所有套接字,但不接受它们。

So, this was my last attempt but not sure, maybe I need to use threads or declare the sockets differently? 因此,这是我的最后一次尝试,但不确定,也许我需要使用线程或以不同的方式声明套接字?

So far, in this small test code, I want: 到目前为止,在这个小的测试代码中,我想要:

Initialize server listen on all 7 ports (1111,2222 ...etc) Accept an incoming connection on ANY of them display both messages on client/server drop the connection and continue 在所有7个端口上初始化服务器侦听(1111,2222 ... etc)在其中任何一个上接受传入连接,在客户端/服务器上显示两条消息,断开连接并继续

It's a little sloppy I know, but here is the code so far and I think you can see where I am going with it: 我知道这有点草率,但这是到目前为止的代码,我想您可以看到我的使用方向:

#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;
}

And now it's throwing a runtime error as well: 现在,它还会引发运行时错误:

 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, 

or for select, a member of an fd_set was not valid. 或对于select而言,fd_set的成员无效。

Which (including debugging) indicates that the socket isn't declared properly when creating on an array, advice? 哪个(包括调试)指示在数组上创建时未正确声明套接字,建议?

You code to create/bind/listen is all good. 您创建/绑定/监听的代码都很好。 Then: 然后:

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

Firstly, by the time this runs you're outside the loop, and i is 7 which is past the end of the array of sockets, which is why you get the not-a-socket error. 首先,到运行此代码时,您已经超出了循环范围,并且i是7(已超出套接字数组的末尾),这就是为什么您收到非套接字错误的原因。

Secondly, accept() is a blocking call, so you can't just call accept() on all the sockets from the same thread the way you did for listen . 其次, accept()是一个阻塞调用,因此您不能像listen方法那样仅从同一线程在所有套接字上调用accept() You need to either have a separate thread block in accept() for each of the ports, or find out which one has a client connection attempt in progress using eg select (or epoll - does Windows have that?), then accept() a client on that specific socket (but then you've still got to either create a thread to handle the client read / recv s and write / send s or use select / epoll to find out when there's input ready to read , or more space in output buffers for transmission). 您需要为每个端口在accept()有一个单独的线程块,或者使用例如select (或epoll -Windows是否具有该功能)找出正在尝试进行客户端连接的端口,然后accept() a特定套接字上的client(但是您仍然必须创建一个线程来处理client的read / recvwrite / send或者使用select / epoll来查找何时有准备read的输入,或者在其中有更多空间输出缓冲区用于传输)。 There's also a race condition to be wary of if you use select / epoll - a listening socket might signal readiness for accepting a client connection, but by the time you call accept() that connection attempt's failed and forgotten, then if the listening socket hasn't been set to non-blocking mode it'll hang there waiting for another client to connect to that specific socket. 如果您使用select / epoll还有一个竞争条件要提防-侦听套接字可能表示已准备好接受客户端连接,但是当您调用accept() ,连接尝试已失败并被遗忘,那么如果侦听套接字已经失败没有设置为非阻塞模式,它将挂在那里等待另一个客户端连接到该特定套接字。 IMHO, this is a case where threading is actually easier. 恕我直言,这是线程实际上更容易的情况。

I think it's more "Windowsy" to use IO Completion Ports (you might want to Google), but AFAIK they're totally unportable. 我认为使用IO完成端口(您可能要使用Google)更“ Windowsy”,但AFAIK完全不可移植。 Winsock's not an exact match for BSD sockets, but the porting or dual-support effort's small. Winsock不能与BSD插槽完全匹配,但是移植或双重支持的工作量很小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM