Konkurentní server v C++

Konkurentní server v C++

Konkurentní server dokáže obsloužit více klientů zároveň. V mém kódu je tohoto požadavku dosaženo použitím systémového volání fork(), které slouží k vytvoření nového procesu. Stejné funkčnosti se dá docílit i pomocí jiných metod, mimo jiné použitím vláken, či funkcí select() a poll() z knihovny pro práci se sockety.

Na server se můžete připojit například pomocí telnetu příkazem:
telnet 127.0.0.1 1234

Proč tento snippet vznikl?

V rámci druhého projekt do kurzu Počítačové komunikace a sítě (účelem bylo navrhnout protokol pro přenos souborů a implementovat klienta a konkurentní server, využívající tento protokol).

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <sstream>

using namespace std;

const int OK = 0;
const int ERR = 1;

const int PORT = 1234;
const int MAXHOSTNAME = 200;
const int MAXCONNECTIONS = 5;
const int MAXRECV = 500;
const int SEC = 12;
const string MESS = "HELLO, YOU ARE CONNECTED TO HELLO SEVERn";
const string BYE  = "Byen";

void wait ( int seconds )
{
    clock_t endwait = clock () + seconds * CLOCKS_PER_SEC ;
    while ( clock() < endwait ) {}
}

int main()
{
    cout << "Hello I'am Hello server!" << endl <<
            "My IP: 127.0.0.1 and port: " << PORT << endl;

    // 0.0 Variables
    int m_sock;
    sockaddr_in m_addr;

    // 1.0 Create socket

    // 1.1 Create
    m_sock = socket(AF_INET, SOCK_STREAM, 0);
    if ( m_sock == -1 )
        return ERR;

    // 1.1.1 Allows other socket bind to this port
    //  (get around "Bind: Address already in use" error)
    int on = 1;
    if ( setsockopt (m_sock, SOL_SOCKET, SO_REUSEADDR,
        (const char*) &on, sizeof(on)) )
        return ERR;

    // 1.2 Bind
    m_addr.sin_family = AF_INET;
    m_addr.sin_addr.s_addr = INADDR_ANY;
    m_addr.sin_port = htons(PORT);

    if ( ::bind(m_sock, (struct sockaddr*) &m_addr, sizeof(m_addr)) )
        return ERR;

    // 1.3 Listen
    if ( ::listen ( m_sock, MAXCONNECTIONS ) )
        return ERR;

    // 2.0 Server body

    while ( true ) {
        // 2.1 Local variables
        int client_m_sock;
        int client_m_addr;

        // 2.2 Accept connection
        int addr_length = sizeof (client_m_addr);
        client_m_sock = ::accept (m_sock, (sockaddr*) &client_m_addr, 
                                  (socklen_t*) &addr_length);

        if (client_m_sock <= 0)
            return ERR;

        // 2.3 Fork
        if (!fork()) {  // Child (Service for a client)
            close(m_sock);
            write (client_m_sock, MESS.data(), MESS.length());

            for (int x = 0; x < SEC; x++) {  // Countdown
                wait(1);
                stringstream out;     // ----
                out << x;             // Converting integer
                string count;         // to string.
                count = out.str();    // ----
                count.append("n");
                write(client_m_sock, count.data(), count.length());
            }

            write(client_m_sock, BYE.data(), BYE.length());
            close (client_m_sock);
            exit(OK);
        }

        close(client_m_sock);
    }

    return OK;
}

Leave a Reply

Your email address will not be published. Required fields are marked *