且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

创建多个侦听套接字

更新时间:2023-11-22 17:01:22

代码创建/ bind / listen都是好的。然后:

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

首先,当这个运行时你处于循环之外,



其次,这是为什么你会得到一个非socket错误。 , accept()是一个阻塞调用,因此您不能在所有套接字上调用 accept() listen 相同的线程。您需要在 accept()中为每个端口都有一个单独的线程块,或者使用例如查看哪个端口正在进行客户端连接尝试。 选择(或 epoll - Windows是否有?),然后 code>在这个特定的套接字上的客户端(但是你还是要创建一个线程来处理客户端 read / recv s和写$ c> / code> / 以查看输入是否准备好读取,或输出缓冲区中的更多空间传输)。还有一个竞争条件,如果你使用 select / epoll - 一个侦听socket可能会表示准备接受一个客户端连接,但是当你调用 accept()的时候,连接尝试失败并被遗忘,那么如果监听套接字没有设置为非阻塞模式, ll挂在那里等待另一个客户端连接到该特定的套接字。



我认为更多的是使用IO完成端口(你可能想谷歌)Windowsy,但AFAIK他们完全不实用。 Winsock不是BSD套接字的精确匹配,但移植或双重支持的努力很小。


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.

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

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.

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.

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. 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 e.g. 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/recvs and write/sends or use select/epoll to find out when there's input ready to read, or more space in output buffers for transmission). 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. 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. Winsock's not an exact match for BSD sockets, but the porting or dual-support effort's small.