MinGW Socket

来源:互联网 发布:台湾人不是中国人 知乎 编辑:程序博客网 时间:2024/05/29 03:40

#ifdef WIN32
    #include <Winsock2.h>
#else
    #include <sys/types.h>
    #include <sys/socket.h>

    #define closesocket close
#endif
#include <stdio.h>

#define D_PORT      4344
#define D_HOST      "localhost"
#define D_QUEUE     32
#define D_SOCKETS   16
#define D_INFO      256

int main(int argc, char **argv) {
    struct timeval tv;
    struct sockaddr_in addr;
    struct hostent *host;
    unsigned int descriptor;
    int result;
    int index;
    int cycle = 0;
    int delay = 0;
    unsigned int sockets[D_SOCKETS];
    int sockets_index = 0;
    unsigned int maximun;
    char buffer[D_INFO];
    fd_set input;

    /*  read the delay if any  */
    if (argc > 1)
        delay = atol(argv[1]);
    else
        delay = 0;

#ifdef WIN32
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif  /*  WIN32  */

    /*  create a socket  */
    descriptor = socket(PF_INET, SOCK_STREAM, 0);
    if (descriptor == -1) {
        perror("socket");
        return (1);
    }

    /*  get information about the host  */
    memset(&addr, 0, sizeof(addr));
    host = gethostbyname(D_HOST);
    if (host == NULL) {
        perror("gethostbyname");
        closesocket(descriptor);
#ifdef WIN32
        WSACleanup();
#endif
        return (1);
    }

    /*  bind the socket to an address and port  */
    memcpy(&addr.sin_addr, host->h_addr_list[0], sizeof(host->h_addr_list[0]));
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(D_PORT);
    result = bind(descriptor, (struct sockaddr *)&addr, sizeof(addr));
    if (result == -1) {
        perror("bind");
        closesocket(descriptor);
#ifdef WIN32
        WSACleanup();
#endif
        return (1);
    }

    /*  listen for connections  */
    result = listen(descriptor, D_QUEUE);
    if (result == -1) {
        perror("listen");
        closesocket(descriptor);
#ifdef WIN32
        WSACleanup();
#endif
        return (1);
    }

    memset(sockets, 0, sizeof(sockets));
    maximun = descriptor;

    result = 0;
    while (result != -1) {
        FD_ZERO(&input);
        FD_SET(descriptor, &input);
        for (result = 0; result < sockets_index; result++)
            FD_SET(sockets[result], &input);

        tv.tv_sec  = delay;
        tv.tv_usec = 0;
        if (delay == -1)
            result = select(maximun + 1, &input, NULL, NULL, NULL);
        else
            result = select(maximun + 1, &input, NULL, NULL, &tv);
        switch (result) {
            /*  error in select  */
            case -1:
                perror("select");
                break;

            /*  nothing to process  */
            case 0:
                break;

            /*  a number of sockets are ready for reading  */
            default:
                /*  check if the descriptor set is our listening one  */
                if (FD_ISSET(descriptor , &input)) {
                    sockets[sockets_index] = accept(descriptor, NULL, NULL);
                    if (sockets[sockets_index] == -1) {
                        perror("accept");
                    }
                    else {
                        if (sockets[sockets_index] > maximun)
                            maximun = sockets[sockets_index];

                        sockets_index++;
                    }
                }
                /*  one of the sockets is sending data. Find it  */
                else {
                    for (index = 0; index < sockets_index; index++) {
                        if (FD_ISSET(sockets[index], &input)) {
                            memset(buffer, 0, sizeof(buffer));

                            /*  read information from socket  */
                            result = recv(sockets[index], buffer, sizeof(buffer), 0);
                            if (result == -1)
                                perror("recv");
                            else
                                printf("Received %d bytes from descriptor %d: %s/n", result, sockets[index], buffer);
                        }
                    }
                }
        }

        printf("%d/r", cycle++);
    }

    for (result = 0; result < sockets_index; result++) {
        closesocket(sockets[sockets_index]);
    }

    closesocket(descriptor);
#ifdef WIN32
    WSACleanup();
#endif

    return (0);
}


Ok, here is a very small program. Put this into a file and add it to a VC project, add Ws2_32.lib library for linking, and compile it. Under MinGW, use g++ main.cpp -o main.exe -lwsock32. Execute it. By default, it is a non blocking program. There is a number counting advancing to show you it is not blocking the execution.

Now, run a telnet (telnet localhost 4344). Telnet will connect, and everytime you type something, it will send the letter to the server. You can connect up to 32 telnets. Every time you type a letter, the server prints the socket and the letter. If you see the Task Manager, the program would be taking like 99% of CPU.

If you want your server to wait for 1 second before continuing processing, pass 1 as argument. You will notice I set the new delay. This time, the server will wait for 1 second before continuing with the program. Finally, if you want to make the program blocking, pass -1 as argument. If you check the code, I call select with NULL as last parameter to block it.

Be careful! I am not doing error handling when a telnet shuts down, so if you do it will get mad  I hope the example is good enough.

(Edited: Non-Windows support is not tested, too sleepy to turn my other computer on, but should work with one or two hacks).

 

original url : http://www.allegro.cc/forums/thread/370013/370226#target

原创粉丝点击