Concurrent Server Design এবং উদাহরণ

Computer Programming - ইউনিক্স সকেট (Unix Socket) - Concurrency এবং Socket Programming (Concurrency in Socket Programming)
371

Concurrent Server Design হলো এমন একটি সার্ভার আর্কিটেকচার, যেখানে সার্ভার একসাথে একাধিক ক্লায়েন্ট সংযোগ পরিচালনা করতে পারে। এটি নেটওয়ার্ক প্রোগ্রামিংয়ের একটি গুরুত্বপূর্ণ ধারণা এবং সাধারণত উচ্চ-পারফরম্যান্স ও স্কেলেবল সার্ভার ডিজাইন করার জন্য ব্যবহৃত হয়। Concurrent Server Design-এর মাধ্যমে সার্ভার একাধিক ক্লায়েন্টের জন্য দ্রুত সাড়া দিতে সক্ষম হয় এবং এর মাধ্যমে সার্ভারের কার্যকারিতা বৃদ্ধি করা যায়।

Concurrent Server Design-এর মূল পদ্ধতি

Concurrent Server Design-এ সাধারণত তিনটি পদ্ধতি ব্যবহার করা হয়:

Multiprocessing:

  • এই পদ্ধতিতে প্রতিটি নতুন ক্লায়েন্ট সংযোগের জন্য একটি নতুন প্রক্রিয়া (process) তৈরি করা হয়।
  • Unix বা Linux সিস্টেমে fork() ফাংশন ব্যবহার করে নতুন প্রক্রিয়া তৈরি করা হয়।
  • প্রতিটি প্রক্রিয়া আলাদা মেমোরি স্পেস ব্যবহার করে, তাই এদের মধ্যে ডেটা কনফ্লিক্ট বা সমস্যা কম হয়।
  • Multiprocessing-এর একটি সাধারণ উদাহরণ হলো Pre-forking Model

Multithreading:

  • Multithreading-এ প্রতিটি নতুন ক্লায়েন্ট সংযোগের জন্য একটি নতুন থ্রেড তৈরি করা হয়।
  • থ্রেডগুলো একটি প্রক্রিয়ার মধ্যে কাজ করে এবং তারা একই মেমোরি স্পেস শেয়ার করে।
  • Multithreading সাধারণত লাইটওয়েট এবং Multiprocessing-এর তুলনায় কম রিসোর্স ব্যবহার করে, তবে থ্রেড সিঙ্ক্রোনাইজেশন গুরুত্বপূর্ণ।

Event-Driven/Asynchronous I/O:

  • এই পদ্ধতিতে একটি ইভেন্ট-ড্রিভেন আর্কিটেকচার ব্যবহার করা হয়, যেখানে সার্ভার একাধিক ক্লায়েন্ট সংযোগ পরিচালনা করতে select(), poll(), বা epoll()-এর মতো I/O Multiplexing টেকনিক ব্যবহার করে।
  • এই মডেলটি স্কেলেবল এবং উচ্চ-পারফরম্যান্স সার্ভার তৈরি করতে ব্যবহৃত হয়।

Concurrent Server Design-এর উদাহরণ (Multithreading)

নিচে একটি TCP Concurrent Server প্রোগ্রাম দেখানো হলো, যা Multithreading পদ্ধতি ব্যবহার করে একাধিক ক্লায়েন্ট সংযোগ পরিচালনা করে:

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

#define PORT 8080
#define BUFFER_SIZE 1024

// ক্লায়েন্ট সংযোগ পরিচালনা করার ফাংশন
void *handle_client(void *client_socket) {
    int sock = *(int*)client_socket;
    char buffer[BUFFER_SIZE];
    int n;

    // ক্লায়েন্ট থেকে ডেটা গ্রহণ করা
    while ((n = read(sock, buffer, sizeof(buffer) - 1)) > 0) {
        buffer[n] = '\0';
        printf("Client: %s\n", buffer);

        // ক্লায়েন্টে ডেটা পাঠানো
        write(sock, buffer, strlen(buffer));
    }

    // ক্লায়েন্টের সাথে সংযোগ বন্ধ করা
    close(sock);
    free(client_socket);
    return NULL;
}

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);

    // Server socket তৈরি করা
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    // Socket binding করা
    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // Listening শুরু করা
    if (listen(server_fd, 5) < 0) {
        perror("Listen failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    printf("Server is listening on port %d\n", PORT);

    // ক্লায়েন্ট সংযোগ গ্রহণ করা
    while ((client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len)) >= 0) {
        printf("New client connected\n");

        // প্রতিটি ক্লায়েন্টের জন্য নতুন থ্রেড তৈরি করা
        pthread_t thread_id;
        int *new_sock = malloc(sizeof(int));
        *new_sock = client_fd;

        if (pthread_create(&thread_id, NULL, handle_client, (void*)new_sock) != 0) {
            perror("Thread creation failed");
            close(client_fd);
        }

        // থ্রেড detach করা, যাতে সম্পন্ন হলে এটি নিজে থেকেই রিসোর্স মুক্ত করতে পারে
        pthread_detach(thread_id);
    }

    // Server socket বন্ধ করা
    close(server_fd);
    return 0;
}

প্রোগ্রামের বিশ্লেষণ

  1. Socket তৈরি:
    • socket() ফাংশন ব্যবহার করে TCP Socket তৈরি করা হয়েছে।
  2. Binding:
    • bind() ফাংশন ব্যবহার করে Socket-কে একটি নির্দিষ্ট IP Address এবং Port Number-এ সংযুক্ত করা হয়েছে।
  3. Listening:
    • listen() ফাংশন ব্যবহার করে সার্ভার Socket-কে ইনকামিং সংযোগ গ্রহণের জন্য প্রস্তুত করা হয়েছে।
  4. Multithreading ব্যবহার:
    • প্রতিটি নতুন ক্লায়েন্ট সংযোগের জন্য pthread_create() ফাংশন ব্যবহার করে একটি নতুন থ্রেড তৈরি করা হয়েছে। এই থ্রেডগুলো handle_client() ফাংশনের মাধ্যমে ক্লায়েন্টদের সাথে ডেটা আদান-প্রদান পরিচালনা করে।
  5. Thread Detachment:
    • pthread_detach() ফাংশন ব্যবহার করে থ্রেডগুলোকে detach করা হয়েছে, যাতে থ্রেডগুলো সম্পন্ন হলে তাদের রিসোর্স নিজে থেকেই মুক্ত হয়।
  6. Data Transmission:
    • read() এবং write() ফাংশন ব্যবহার করে ক্লায়েন্টের সাথে ডেটা পাঠানো এবং গ্রহণ করা হয়েছে।

অন্যান্য Concurrent Server Design পদ্ধতির উদাহরণ

Multiprocessing Server Design (Forking)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>

#define PORT 8080
#define BUFFER_SIZE 1024

void handle_client(int client_fd) {
    char buffer[BUFFER_SIZE];
    int n;

    // ক্লায়েন্ট থেকে ডেটা গ্রহণ করা
    while ((n = read(client_fd, buffer, sizeof(buffer) - 1)) > 0) {
        buffer[n] = '\0';
        printf("Client: %s\n", buffer);

        // ক্লায়েন্টে ডেটা পাঠানো
        write(client_fd, buffer, strlen(buffer));
    }

    close(client_fd);
}

void sigchld_handler(int s) {
    while (waitpid(-1, NULL, WNOHANG) > 0);
}

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);

    // Signal handler সেট করা
    signal(SIGCHLD, sigchld_handler);

    // Server socket তৈরি করা
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    listen(server_fd, 5);

    printf("Server is listening on port %d\n", PORT);

    // ক্লায়েন্ট সংযোগ গ্রহণ করা
    while ((client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len)) >= 0) {
        printf("New client connected\n");

        if (fork() == 0) {
            close(server_fd);
            handle_client(client_fd);
            exit(0);
        }

        close(client_fd);
    }

    close(server_fd);
    return 0;
}
Content added By
Promotion
NEW SATT AI এখন আপনাকে সাহায্য করতে পারে।

Are you sure to start over?

Loading...