C++ programming: Linux server socket example

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>

#define TRUE   1
#define PORT 51500

int main(int argc, char *argv[]) {
    int master_sock,
            addrlen,
            new_sock,
            maximum_clients = 30,
            client_sock[maximum_clients],
            act,
            i,
            value_read,
            sock_descriptor,
            maximum_socket_descriptor;
    struct sockaddr_in adr{};

    char buff[1024];  //data buffer of 1K
    fd_set read_fds; //set of socket file descriptors
    char *message = "ECHO Daemon v1.0 \r\n"; //connect notice message

    //initialise all client_sock to 0
    for (i = 0; i < maximum_clients; i++) {
        client_sock[i] = 0;
    }

    //creating a master socket
    if ((master_sock = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Failed_Socket");
        exit(EXIT_FAILURE);
    }

    //These are the types of sockets that we have created
    adr.sin_family = AF_INET;//PROTOCOL = IP
    adr.sin_addr.s_addr = INADDR_ANY;//SOURCE ADDRESS = 0.0.0.0/0
    adr.sin_port = htons(PORT);//LISTENING PORT = PORT

    //bind the socket to localhost port
    if (bind(master_sock, (struct sockaddr *) &adr, sizeof(adr)) < 0) {
        perror("Failed_Bind");
        exit(EXIT_FAILURE);
    }

    printf("Port having listener:  %d \n", PORT);

    //Specify 3 as maximum pending connections for master socket
    if (listen(master_sock, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    //Accepting the Incoming Connection
    addrlen = sizeof(adr);
    puts("Looking For Connections");

    //*******************************//
    // Here we start using select functions and the macros for multiple client handling

    while (TRUE) {
        //Clearing the socket set
        FD_ZERO(&read_fds);

        //Adding the master socket to the set
        FD_SET(master_sock, &read_fds);
        maximum_socket_descriptor = master_sock;

        //Adding child sockets to set
        for (i = 0; i < maximum_clients; i++) {
            //Descriptor for Socket
            sock_descriptor = client_sock[i];

            //if the socket descriptor is valid then adding it to the read list
            if (sock_descriptor > 0) {
                FD_SET(sock_descriptor, &read_fds);
            }

            //Highest File Descriptor Number which is needed for the select function
            if (sock_descriptor > maximum_socket_descriptor) {
                maximum_socket_descriptor = sock_descriptor;
            }
        }

        //Waiting for something to happen on the master socket. As the wait time is NULL the wait is indefinite
        act = select(maximum_socket_descriptor + 1, &read_fds, nullptr, nullptr, nullptr);
        if ((act < 0) && (errno != EINTR)) {
            printf("Failed_Select");
        }

        //Any activity on the master socket is treated as an incoming connection
        if (FD_ISSET(master_sock, &read_fds)) {
            if ((new_sock = accept(master_sock, (struct sockaddr *) &adr, (socklen_t *) &addrlen)) < 0) {
                perror("Accept!");
                exit(EXIT_FAILURE);
            }

            //Informing the user of the socket number which will be sued to send and receive messages
            printf("This is a New Connection,The socket file descriptor is %d and the IP is : %s on Port : %d\n",
                   new_sock,
                   inet_ntoa(adr.sin_addr),
                   ntohs(adr.sin_port));

            // Sending Greeting Message on New Connection
            if (send(new_sock, message, strlen(message), 0) != strlen(message)) {
                perror("Send!!");
            }
            puts("Welcome Text Sent Affirmative.");

            // Adding new socket to the array of sockets
            for (i = 0; i < maximum_clients; i++) {
                // Checking if the position is empty
                if (client_sock[i] == 0) {
                    client_sock[i] = new_sock;
                    printf("Adding new socket to the list of sockets as %d\n", i);
                    break;
                }
            }
        }

        //If not the master socket then it is some i/o activity on some other socket
        for (i = 0; i < maximum_clients; i++) {

            sock_descriptor = client_sock[i];
            if (FD_ISSET(sock_descriptor, &read_fds)) {

                //Checking if the activity was for closing and reading the incoming message
                if ((value_read = read(sock_descriptor, buff, 1024)) == 0) {

                    //If someone disconnected, getting their details and printing a message
                    getpeername(sock_descriptor, (struct sockaddr *) &adr, (socklen_t *) &addrlen);

                    printf("Disconnected Host. Their , IP %s and PORT %d \n",
                           inet_ntoa(adr.sin_addr), ntohs(adr.sin_port));

                    //Closing the socket and marking it as 0 in the list to be reused
                    close(sock_descriptor);
                    client_sock[i] = 0;
                } else {
                    //Setting the string terminating NULL byte on the end of the data that is read
                    buff[value_read] = '\0';
                    //Echoing back the message that came in the socket
                    send(sock_descriptor, buff, strlen(buff), 0);
                }
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值