Select listens on multiple clients--Linux functions

Source: Internet
Author: User
Tags socket error

Use the Select function to communicate with multiple sockets in a non-blocking manner. The program simply demonstrates the use of the Select function, which is very simple, even if a connection is closed and the current number of connections is not modified, and the program is terminated after the maximum number of connections is reached.

1. The program uses an array fd_a, and the communication begins after the multiple socket descriptors that need to be communicated are placed in this array.

2. First generate a socket descriptor called SOCK_FD, which is used to listen to the port.

3. Put sock_fd and array fd_a in a descriptor that does not have a 0 in the Select to check the collection FDSR.

4. Handle the connection that can receive data in FDSR. If it is a sock_fd, it indicates that a new connection is added, and the newly joined socket descriptor is placed into the fd_a.

This part of the code to achieve good logic, but a bit of a bug, the socket cache is not processed complete.

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include < string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include < arpa/inet.h> #define MYPORT 1234//The Port users would be a connecting to#define BACKLOG 5/How many pending con    Nections queue would hold#define buf_size 200int Fd_a[backlog];    Accepted connection Fdint Conn_amount;    Current Connection Amountvoid showclient () {int i;    printf ("Client Amount:%d\n", Conn_amount);    for (i = 0; i < BACKLOG; i++) {printf ("[%d]:%d", I, fd_a[i]); } printf ("\ n");}  int main (void) {int sock_fd, NEW_FD;    Listen on SOCK_FD, new connection on new_fd struct sockaddr_in server_addr; Server address information struct sockaddr_in client_addr;    Connector ' s address information socklen_t sin_size;    int yes = 1;    Char Buf[buf_size];    int ret;    int i; if (SOCK_FD = socket (af_iNET, Sock_stream, 0)) = =-1) {perror ("socket");    Exit (1);        } if (setsockopt (SOCK_FD, Sol_socket, so_reuseaddr, &yes, sizeof (int)) = =-1) {perror ("setsockopt");    Exit (1);         } server_addr.sin_family = Af_inet;     Host byte order Server_addr.sin_port = Htons (MyPort); Short, network byte order server_addr.sin_addr.s_addr = Inaddr_any;    Automatically fill with my IP memset (Server_addr.sin_zero, ' + ', sizeof (Server_addr.sin_zero));        if (Bind (SOCK_FD, (struct sockaddr *) &server_addr, sizeof (SERVER_ADDR)) = =-1) {perror ("bind");    Exit (1);        } if (Listen (SOCK_FD, BACKLOG) = =-1) {perror ("listen");    Exit (1);    } printf ("Listen Port%d\n", MyPort);    Fd_set FDSR;    int maxsock;    struct Timeval TV;    Conn_amount = 0;    sin_size = sizeof (CLIENT_ADDR);    Maxsock = SOCK_FD;        while (1) {//Initialize file descriptor set Fd_zero (&AMP;FDSR); Fd_set (SOCK_FD, &FDSR);        Timeout setting tv.tv_sec = 30;        tv.tv_usec = 0;                Add active connection to FD set for (i = 0; i < BACKLOG; i++) {if (fd_a[i]! = 0) {            Fd_set (Fd_a[i], &AMP;FDSR);        }} ret = select (Maxsock + 1, &AMP;FDSR, NULL, NULL, &AMP;TV);            if (Ret < 0) {perror ("select");        Break            } else if (ret = = 0) {printf ("timeout\n");        Continue }//Check every FD in the set for (i = 0; i < Conn_amount; i++) {if (Fd_isset (Fd_a[i], &                FDSR) {ret = recv (Fd_a[i], buf, sizeof (BUF), 0);                    if (ret <= 0) {//Client close printf ("client[%d] close\n", i);                    Close (Fd_a[i]);                    FD_CLR (Fd_a[i], &AMP;FDSR);                Fd_a[i] = 0;              } else {//Receive data if (Ret < buf_size)          memset (&buf[ret], ' n ', 1);                printf ("client[%d] send:%s\n", I, buf);            }}}//Check whether a new connection comes if (Fd_isset (SOCK_FD, &AMP;FDSR)) {            NEW_FD = Accept (sock_fd, (struct sockaddr *) &client_addr, &sin_size);                if (new_fd <= 0) {perror ("accept");            Continue                }//Add to FD queue if (Conn_amount < BACKLOG) {fd_a[conn_amount++] = NEW_FD; printf ("New connection client[%d]%s:%d\n", Conn_amount, Inet_ntoa (client_addr.sin_ad                DR), Ntohs (Client_addr.sin_port));            if (new_fd > Maxsock) maxsock = NEW_FD;                } else {printf ("max connections arrive, exit\n");                Send (NEW_FD, "Bye", 4, 0);                Close (NEW_FD);            Break }} showclient ();    }//Close other connections for (i = 0; i < BACKLOG; i++) {if (fd_a[i]! = 0) {Close (fd_a        [i]); }} exit (0);}


I make changes here (probably logical)

    for (i=0;i<backlog;i++) {Tcpsockindex[i] =-1; } while (1) {Fd_zero (&AMP;READFDS);                Fd_set (Tcpsock, &readfds);                MAXFDP = maxfdp>tcpsock?maxfdp:tcpsock;            for (i=0;i<backlog;i++) {//Ab_log ("fd_set tcpsockindex[%d] =%d.\n", I, tcpsockindex[i]);                if ( -1! = Tcpsockindex[i]) {fd_set (tcpsockindex[i], &readfds);            MAXFDP = maxfdp>tcpsockindex[i]?maxfdp:tcpsockindex[i];        }} timeout.tv_sec = Select_time_out_tm;        timeout.tv_usec = 0;        ret = Select (maxfdp+1, &readfds, NULL, NULL, &timeout), if (Ret < 0) {ab_perror ("select error!\n"); return;}        else if (0 = = ret) {ab_perror ("Select Time out!\n"); }//processing the message sent by the client for (i=0; i<backlog; i++) {if (-1! = Tcpsockindex[i] &&amp                 ;     Fd_isset (Tcpsockindex[i], &readfds)) {       Ab_log ("---TCP client---. \ n");                pthread_t PTHD2;                tcp_sock_t * Ptcpsock = NULL;                Ptcpsock = (tcp_sock_t *) malloc (sizeof (tcp_sock_t));                Ptcpsock->sock = Tcpsockindex[i];                Pthread_create (&AMP;PTHD2, NULL, Bc_sock_handle_client_data, (void *) ptcpsock);            #if 0 bc_sock_handle_client_data (tcpsockindex[i]);                ret = Read (Tcpsockindex[i], NULL, 0);                                              Ab_log ("close tcpsockindex[%d] =%d, ret =%d.\n", I, Tcpsockindex[i], ret);                Closes the socket for the client connection if ( -1 = = Tcpsockindex[i]) Close (tcpsockindex[i]);                #endif//Clear Client Character Set FD_CLR (Tcpsockindex[i], &readfds);                Tcpsockindex[i] =-1;            Tcpclientconnnum--; }}//Gets the socket that the client is connected to if (Fd_isset (Tcpsock, &readfds)) {Ab_log ("---TCP Server---.\ n ");            if (tcpsockclient = Accept (Tcpsock, (struct sockaddr*) &chiaddr, &clilen)) <= 0)                  {Ab_perror ("BCHV Accept Socket Error:%s (errno:%d). \ n", Strerror (errno), errno);              Continue            }//Locate an available add location in the sockets group. for (i=0,tcpsockflag=0; i<backlog; i++) {Ab_log ("tcpsockindex[%d] =%d.\n", I, tcpsockindex[i                ]);                    if ( -1 = = Tcpsockindex[i]) {tcpsockindex[i] = tcpsockclient;                    Tcpclientconnnum + +; Ab_log ("New connection client[%d]%08x:%d.\n", Tcpclientconnnum, ChiAddr.sin_addr.s_addr, Ntohs                    (Chiaddr.sin_port));                    Error printing//ab_log ("New connection client[%d]%s.\n", Tcpclientconnnum,                    Inet_ntoa (CHIADDR.SIN_ADDR));                   #if 0 if (Sock_c > MAXFDP) MAXFDP = Sock_c;                    #endif tcpsockflag = 1;                Break }}//exceeds maximum connection request, can send client disconnect if (0 = = Tcpsockflag) {ab_log ("Max C                Onnections arrive, exit\n ");                Send (Tcpsockclient, "Bye", 4, 0);            Close (tcpsockclient);        }}}//Close all client sockets for (i=0; i<backlog; i++) {if ( -1! = Tcpsockindex[i])        {Close (tcpsockindex[i]); }    }


article excerpt fromHttp://www.cnblogs.com/faraway/archive/2009/03/06/1404449.html

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Select listens on multiple clients--Linux functions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.