C ভাষায় সকেট প্রোগ্রামিং নেটওয়ার্ক অ্যাপ্লিকেশন তৈরি করতে ব্যবহৃত হয়, যা ক্লায়েন্ট এবং সার্ভারের মধ্যে যোগাযোগ স্থাপন করে। সি ভাষায় সকেট প্রোগ্রামিং করার জন্য সিস্টেম লেভেল ফাংশন এবং লাইব্রেরি ব্যবহার করা হয়, যেমন socket()
, bind()
, listen()
, accept()
, connect()
, send()
, recv()
ইত্যাদি।
এখানে TCP/IP প্রোটোকল ব্যবহার করে সি ভাষায় সার্ভার এবং ক্লায়েন্ট প্রোগ্রাম তৈরির উদাহরণ দেওয়া হলো।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 65432
int main() {
int server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);
char buffer[1024];
// সকেট তৈরি করা
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// সার্ভারের জন্য ঠিকানা সেট করা
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // সমস্ত IP ঠিকানা গ্রহণ
server_addr.sin_port = htons(PORT); // পোর্ট নম্বর
// সকেটটি বাউন্ড করা
if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(server_socket);
exit(EXIT_FAILURE);
}
// সার্ভার শোনা শুরু করে
if (listen(server_socket, 5) < 0) {
perror("Listen failed");
close(server_socket);
exit(EXIT_FAILURE);
}
printf("Server listening on port %d...\n", PORT);
// ক্লায়েন্টের সাথে সংযোগ গ্রহণ করা
client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &addr_len);
if (client_socket < 0) {
perror("Accept failed");
close(server_socket);
exit(EXIT_FAILURE);
}
printf("Client connected: %s\n", inet_ntoa(client_addr.sin_addr));
// ক্লায়েন্ট থেকে ডেটা গ্রহণ করা
read(client_socket, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
// ক্লায়েন্টকে রিপ্লাই পাঠানো
send(client_socket, "Hello from the server!", 23, 0);
// সংযোগ বন্ধ করা
close(client_socket);
close(server_socket);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 65432
int main() {
int client_socket;
struct sockaddr_in server_addr;
char *message = "Hello, Server!";
char buffer[1024];
// সকেট তৈরি করা
client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT); // সার্ভারের পোর্ট নম্বর
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // সার্ভারের IP ঠিকানা
// সার্ভারের সাথে সংযোগ করা
if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("Connection failed");
close(client_socket);
exit(EXIT_FAILURE);
}
// সার্ভারে ডেটা পাঠানো
send(client_socket, message, strlen(message), 0);
// সার্ভার থেকে রিপ্লাই গ্রহণ করা
read(client_socket, buffer, sizeof(buffer));
printf("Received from server: %s\n", buffer);
// সংযোগ বন্ধ করা
close(client_socket);
return 0;
}
কী হচ্ছে এখানে?
UDP (User Datagram Protocol) একটি কানেকশনলেস প্রোটোকল। এতে সংযোগ স্থাপন করার প্রয়োজন নেই এবং এটি দ্রুত ডেটা পাঠাতে সক্ষম, তবে এটি নির্ভরযোগ্য নয়।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 65432
int main() {
int server_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);
char buffer[1024];
// UDP সকেট তৈরি করা
server_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (server_socket == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // সমস্ত IP ঠিকানা গ্রহণ
server_addr.sin_port = htons(PORT);
// সার্ভারের পোর্টে বাউন্ড করা
if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(server_socket);
exit(EXIT_FAILURE);
}
printf("UDP server is listening on port %d...\n", PORT);
// ক্লায়েন্ট থেকে ডেটা গ্রহণ করা
recvfrom(server_socket, buffer, sizeof(buffer), 0, (struct sockaddr*)&client_addr, &addr_len);
printf("Received message: %s\n", buffer);
// ক্লায়েন্টকে রিপ্লাই পাঠানো
sendto(server_socket, "Hello from UDP server!", 23, 0, (struct sockaddr*)&client_addr, addr_len);
close(server_socket);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 65432
int main() {
int client_socket;
struct sockaddr_in server_addr;
char *message = "Hello, UDP Server!";
char buffer[1024];
// UDP সকেট তৈরি করা
client_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (client_socket == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
// সার্ভারে মেসেজ পাঠানো
sendto(client_socket, message, strlen(message), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
// সার্ভার থেকে রিপ্লাই গ্রহণ করা
recvfrom(client_socket, buffer, sizeof(buffer), 0, NULL, NULL);
printf("Received from server: %s\n", buffer);
close(client_socket);
return 0;
}
কী হচ্ছে এখানে?
নন-ব্লকিং সকেট ব্যবহার করলে কোনো I/O অপারেশন (যেমন ডেটা পাঠানো বা গ্রহণ করা) ব্লক না হয়ে সিস্টেমের অন্যান্য কাজ করার সুযোগ দেয়। এটি একাধিক ক্লায়েন্টের সাথে যোগাযোগ করার জন্য উপকারী।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#define PORT 65432
int main() {
int server_socket;
struct sockaddr_in server_addr;
char buffer[1024];
// সকেট তৈরি করা
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// নন-ব্লকিং সকেট সেট করা
fcntl(server_socket, F_SETFL, O_NONBLOCK);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr =
INADDR_ANY;
server_addr.sin_port = htons(PORT);
// বাউন্ড করা
bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen(server_socket, 5);
printf("Non-blocking server is listening on port %d...\n", PORT);
while (1) {
int client_socket = accept(server_socket, NULL, NULL);
if (client_socket == -1) {
// কোনো ক্লায়েন্ট আসেনি, অন্য কাজ করতে থাকুন
continue;
}
// ক্লায়েন্ট থেকে ডেটা গ্রহণ করা
read(client_socket, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
close(client_socket);
}
close(server_socket);
return 0;
}
এখানে fcntl()
ব্যবহার করে সকেটটি নন-ব্লকিং মোডে রাখা হয়েছে। যদি কোনো ক্লায়েন্ট সংযোগ না দেয়, তখন প্রোগ্রামটি ব্লক না হয়ে অন্য কাজ করবে।
C ভাষায় সকেট প্রোগ্রামিং দিয়ে আপনি TCP/IP এবং UDP প্রোটোকল ব্যবহার করে ক্লায়েন্ট-সার্ভার যোগাযোগ অ্যাপ্লিকেশন তৈরি করতে পারেন। নন-ব্লকিং সকেট এবং অন্যান্য নিরাপত্তা ব্যবস্থাও যোগ করা যায় যাতে অ্যাপ্লিকেশন আরও কার্যকরী এবং সুরক্ষিত হয়।
সকেট প্রোগ্রামিং হল একটি গুরুত্বপূর্ণ প্রযুক্তি যা নেটওয়ার্ক প্রোগ্রামিংয়ের মাধ্যমে একাধিক কম্পিউটার বা প্রোগ্রামকে একে অপরের সাথে যোগাযোগ করতে সহায়তা করে। C ভাষায় সকেট প্রোগ্রামিং দিয়ে ক্লায়েন্ট এবং সার্ভার অ্যাপ্লিকেশন তৈরি করা যায়, যা TCP/IP বা UDP প্রোটোকল ব্যবহার করে ডেটা আদান-প্রদান করে।
সকেট প্রোগ্রামিংয়ে একটি সকেট হল একটি প্রোগ্রামের প্রক্রিয়ার সাথে যুক্ত এক ধরনের পোর্ট, যার মাধ্যমে এটি নেটওয়ার্কের অন্য প্রোগ্রামের সাথে যোগাযোগ স্থাপন করতে পারে। C ভাষায় সকেট প্রোগ্রামিংয়ের মাধ্যমে একটি সার্ভার বা ক্লায়েন্ট অ্যাপ্লিকেশন তৈরি করতে হয় যা TCP বা UDP প্রোটোকল ব্যবহার করে যোগাযোগ করে।
সকেট প্রোগ্রামিং মূলত দুটি প্রকারের প্রোটোকল ব্যবহার করে:
C তে সকেট প্রোগ্রামিং শুরু করার জন্য, sys/socket.h
লাইব্রেরি ইমপোর্ট করতে হয়, যেটি সকেট সম্পর্কিত ফাংশন এবং ডাটা স্ট্রাকচার প্রদান করে।
socket()
ফাংশন ব্যবহার করে সকেট তৈরি করা হয়।bind()
ফাংশন ব্যবহার করে সকেটটিকে একটি পোর্ট এবং আইপি ঠিকানায় বেঁধে দেওয়া হয়।listen()
ফাংশন দ্বারা সার্ভার ক্লায়েন্টের সংযোগের জন্য অপেক্ষা করে।accept()
ফাংশন ব্যবহার করে সার্ভার ক্লায়েন্টের সংযোগ গ্রহণ করে।send()
এবং recv()
ফাংশন ব্যবহার করে ডেটা প্রেরণ এবং গ্রহণ করা হয়।close()
ফাংশন দ্বারা সকেট বন্ধ করা হয়।এখানে একটি TCP সার্ভারের উদাহরণ দেওয়া হল যা একটি ক্লায়েন্ট থেকে বার্তা গ্রহণ করবে এবং তা সাড়া পাঠাবে।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
int main() {
int server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_size;
char buffer[1024];
// সার্ভার সকেট তৈরি করা
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket < 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);
// সকেটটি বেঁধে দেওয়া
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
// সংযোগের জন্য অপেক্ষা করা
if (listen(server_socket, 10) == 0) {
printf("Server listening on port %d\n", PORT);
} else {
perror("Listen failed");
exit(EXIT_FAILURE);
}
addr_size = sizeof(client_addr);
client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &addr_size);
if (client_socket < 0) {
perror("Client connection failed");
exit(EXIT_FAILURE);
}
printf("Client connected\n");
// ক্লায়েন্ট থেকে বার্তা গ্রহণ করা
recv(client_socket, buffer, sizeof(buffer), 0);
printf("Client says: %s\n", buffer);
// ক্লায়েন্টকে সাড়া পাঠানো
send(client_socket, "Hello from server!", strlen("Hello from server!"), 0);
// সংযোগ বন্ধ করা
close(server_socket);
close(client_socket);
return 0;
}
কোডের ব্যাখ্যা:
socket()
: একটি সকেট তৈরি করে যা TCP সেবা প্রদান করবে।bind()
: সার্ভার সকেটকে একটি পোর্ট এবং আইপি ঠিকানায় বেঁধে দেওয়া।listen()
: ক্লায়েন্টের সংযোগের জন্য সার্ভার সকেট অপেক্ষা করছে।accept()
: সার্ভার ক্লায়েন্টের সংযোগ গ্রহণ করছে।recv()
: ক্লায়েন্ট থেকে বার্তা গ্রহণ করা।send()
: ক্লায়েন্টকে সাড়া পাঠানো।close()
: সকেট বন্ধ করা।এখানে একটি TCP ক্লায়েন্টের উদাহরণ দেওয়া হল যা সার্ভারের সাথে সংযোগ স্থাপন করবে এবং বার্তা পাঠাবে।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define SERVER_IP "127.0.0.1"
#define PORT 8080
int main() {
int client_socket;
struct sockaddr_in server_addr;
char *message = "Hello from client!";
char buffer[1024];
// ক্লায়েন্ট সকেট তৈরি করা
client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// সার্ভারের অ্যাড্রেস সেট করা
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
// সার্ভারের সাথে সংযোগ স্থাপন করা
if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Connection failed");
exit(EXIT_FAILURE);
}
// সার্ভারকে বার্তা পাঠানো
send(client_socket, message, strlen(message), 0);
// সার্ভার থেকে সাড়া গ্রহণ করা
recv(client_socket, buffer, sizeof(buffer), 0);
printf("Server says: %s\n", buffer);
// সংযোগ বন্ধ করা
close(client_socket);
return 0;
}
কোডের ব্যাখ্যা:
socket()
: ক্লায়েন্ট সকেট তৈরি করা।connect()
: সার্ভারের সাথে সংযোগ স্থাপন করা।send()
: সার্ভারে বার্তা পাঠানো।recv()
: সার্ভার থেকে সাড়া গ্রহণ করা।close()
: সকেট বন্ধ করা।UDP সকেট প্রোগ্রামিং TCP এর মতো কিন্তু এটি কানেকশনলেস প্রোটোকল, যার ফলে এটি দ্রুত যোগাযোগ করতে সক্ষম, তবে ডেটার সঠিকতা বা অর্ডার গ্যারান্টি দেয় না।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
int main() {
int server_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_size;
char buffer[1024];
// UDP সকেট তৈরি করা
server_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (server_socket < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// সার্ভারের অ্যাড্রেস সেট করা
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
// সার্ভারের অ্যাড্রেসে সকেট বেঁধে দেওয়া
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
printf("UDP Server listening on port %d\n", PORT);
// ক্লায়েন্ট থেকে বার্তা গ্রহণ করা
addr_size = sizeof(client_addr);
recvfrom(server_socket, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &addr_size);
printf("Received: %s\n", buffer);
// ক্লায়েন্টকে সাড়া পাঠানো
sendto(server_socket, "Hello from server!", strlen("Hello from server!"), 0, (struct sockaddr *)&client_addr, addr_size);
// সকেট বন্ধ করা
close(server_socket);
return
0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define SERVER_IP "127.0.0.1"
#define PORT 8080
int main() {
int client_socket;
struct sockaddr_in server_addr;
char *message = "Hello from client!";
char buffer[1024];
// UDP সকেট তৈরি করা
client_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (client_socket < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// সার্ভারের অ্যাড্রেস সেট করা
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
// সার্ভারে বার্তা পাঠানো
sendto(client_socket, message, strlen(message), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
// সার্ভার থেকে সাড়া গ্রহণ করা
recvfrom(client_socket, buffer, sizeof(buffer), 0, NULL, NULL);
printf("Server says: %s\n", buffer);
// সকেট বন্ধ করা
close(client_socket);
return 0;
}
C তে সকেট প্রোগ্রামিংয়ের মাধ্যমে আপনি TCP এবং UDP প্রোটোকল ব্যবহার করে সার্ভার এবং ক্লায়েন্ট অ্যাপ্লিকেশন তৈরি করতে পারবেন। এতে সংযোগ স্থাপন, ডেটা প্রেরণ এবং গ্রহণের জন্য বিভিন্ন ফাংশন ব্যবহার করা হয়। TCP প্রোটোকল যেখানে সঠিকতা এবং ডেটার অর্ডার নিশ্চিত করে, সেখানে UDP প্রোটোকল দ্রুত ডেটা পাঠানোর জন্য ব্যবহৃত হয়, তবে এটি অর্ডার বা সঠিকতা নিশ্চিত করে না।
C প্রোগ্রামিং ভাষায় TCP এবং UDP সকেট প্রোগ্রামিং করা যায়। এখানে, আমি দুটি উদাহরণ দিবো যেখানে TCP এবং UDP প্রোটোকল ব্যবহার করে ক্লায়েন্ট এবং সার্ভার প্রোগ্রাম তৈরি করা হয়েছে।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 65432
#define BUFFER_SIZE 1024
int main() {
int server_fd, client_fd;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len;
char buffer[BUFFER_SIZE] = {0};
// সার্ভার সকেট তৈরি
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // সব IP ঠিকানা গ্রহণ করবে
server_addr.sin_port = htons(PORT); // পোর্ট নম্বর
// সার্ভার সকেট বাইন্ড করা
if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// ক্লায়েন্ট সংযোগের জন্য অপেক্ষা
if (listen(server_fd, 3) < 0) {
perror("listen failed");
exit(EXIT_FAILURE);
}
printf("Waiting for connections...\n");
// ক্লায়েন্ট সংযোগ গ্রহণ
addr_len = sizeof(client_addr);
if ((client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addr_len)) < 0) {
perror("accept failed");
exit(EXIT_FAILURE);
}
printf("Connected to client\n");
// ক্লায়েন্ট থেকে ডেটা গ্রহণ
read(client_fd, buffer, BUFFER_SIZE);
printf("Client: %s\n", buffer);
// ক্লায়েন্টকে উত্তর পাঠানো
send(client_fd, "Hello from server!", 18, 0);
printf("Message sent to client\n");
close(client_fd);
close(server_fd);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 65432
#define BUFFER_SIZE 1024
int main() {
int sock;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE] = {0};
// ক্লায়েন্ট সকেট তৈরি
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket failed");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
// সার্ভারের IP ঠিকানা নির্ধারণ
if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
perror("Invalid address");
exit(EXIT_FAILURE);
}
// সার্ভারের সাথে সংযোগ স্থাপন
if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("connection failed");
exit(EXIT_FAILURE);
}
// সার্ভারে বার্তা পাঠানো
send(sock, "Hello from client!", 18, 0);
printf("Message sent to server\n");
// সার্ভার থেকে উত্তর গ্রহণ
read(sock, buffer, BUFFER_SIZE);
printf("Server: %s\n", buffer);
close(sock);
return 0;
}
ব্যাখ্যা:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 65432
#define BUFFER_SIZE 1024
int main() {
int sock;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len;
char buffer[BUFFER_SIZE] = {0};
// UDP সার্ভার সকেট তৈরি
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // সব IP ঠিকানা গ্রহণ করবে
server_addr.sin_port = htons(PORT);
// সার্ভারের সাথে বাইন্ড
if (bind(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
printf("Server is waiting for messages...\n");
// ক্লায়েন্ট থেকে বার্তা গ্রহণ
addr_len = sizeof(client_addr);
recvfrom(sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &addr_len);
printf("Client: %s\n", buffer);
// ক্লায়েন্টকে উত্তর পাঠানো
sendto(sock, "Hello from UDP server!", 22, 0, (struct sockaddr*)&client_addr, addr_len);
printf("Message sent to client\n");
close(sock);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 65432
#define BUFFER_SIZE 1024
int main() {
int sock;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE] = {0};
// UDP ক্লায়েন্ট সকেট তৈরি
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
// সার্ভারের IP ঠিকানা নির্ধারণ
if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
perror("Invalid address");
exit(EXIT_FAILURE);
}
// সার্ভারে বার্তা পাঠানো
sendto(sock, "Hello from UDP client!", 22, 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
printf("Message sent to server\n");
// সার্ভার থেকে উত্তর গ্রহণ
recvfrom(sock, buffer, BUFFER_SIZE, 0, NULL, NULL);
printf("Server: %s\n", buffer);
close(sock);
return 0;
}
ব্যাখ্যা:
এখানে TCP এবং UDP এর মাধ্যমে C প্রোগ্রামিং ভাষায় Server-Client উদাহরণ দেয়া হয়েছে। TCP প্রোটোকল একটি কানেকশন-অরিয়েন্টেড, নির্ভরযোগ্য প্রোটোকল যা সংযোগ স্থাপন এবং ডেটার আদান-প্রদান নিশ্চিত করে, তবে UDP একটি কানেকশনলেস, দ্রুত কিন্তু কম নির্ভরযোগ্য প্রোটোকল। আপনার প্রয়োজন অনুযায়ী আপনি যে প্রোটোকলটি প্রযোজ্য তা বেছে নিতে পারবেন।
C তে socket
প্রোগ্রামিং করার সময় Non-Blocking এবং Asynchronous সকেট ব্যবহার করে আপনি একাধিক ক্লায়েন্টের সাথে একযোগে যোগাযোগ করতে পারেন, তা সিস্টেমের কোনো থ্রেড বা প্রসেসকে ব্লক না করেই। এতে নেটওয়ার্ক অপারেশনগুলো ব্লক করবে না এবং প্রোগ্রামটি অন্যান্য কাজ করতে সক্ষম হবে।
এই দুটি কৌশল select()
, poll()
বা epoll()
মতো সিস্টেম কল ব্যবহার করে একাধিক সকেটকে পরিচালনা করা সম্ভব করে।
Non-Blocking সকেট সাধারণত সার্ভার প্রোগ্রামিংয়ে ব্যবহৃত হয়, যেখানে সার্ভার সকেট ক্লায়েন্টের সংযোগের জন্য অপেক্ষা না করে অন্যান্য কার্যক্রম সম্পাদন করতে পারে। যখন একটি সকেট নন-ব্লকিং মোডে থাকে, তখন read()
বা write()
ফাংশনগুলো যদি কোনো ডেটা না পায়, তবে তা অবিলম্বে একটি নির্দিষ্ট ত্রুটি প্রদান করে এবং প্রোগ্রামটি ব্লক হওয়ার পরিবর্তে অন্যান্য কাজ করতে থাকে।
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/select.h>
#define PORT 65432
int main() {
int server_socket, client_socket;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
char buffer[1024];
// সার্ভার সকেট তৈরি
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// সার্ভারের IP এবং পোর্ট সেট করা
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
// সার্ভার সকেটে বাইন্ড করা
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
// লিসেনিং শুরু করা
if (listen(server_socket, 5) == -1) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
// নন-ব্লকিং সকেট তৈরি
int flags = fcntl(server_socket, F_GETFL, 0);
fcntl(server_socket, F_SETFL, flags | O_NONBLOCK);
printf("Server is listening on port %d...\n", PORT);
// ক্লায়েন্টের সংযোগের জন্য অপেক্ষা
while (1) {
client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len);
if (client_socket == -1) {
// নন-ব্লকিং মোডে কোনো ক্লায়েন্ট না আসলে, সার্ভার অন্য কাজ করতে পারে
printf("No client connection, doing other work...\n");
sleep(1); // কিছু সময়ের জন্য বিরতি, অন্য কাজ করার জন্য
} else {
// ক্লায়েন্টের সাথে সংযোগ স্থাপন হলে
printf("Client connected\n");
read(client_socket, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
close(client_socket);
}
}
close(server_socket);
return 0;
}
fcntl()
ব্যবহার করে সার্ভার সকেটের ফ্ল্যাগ পরিবর্তন করা হয়েছে, যাতে এটি নন-ব্লকিং মোডে চলে।accept()
কলের মধ্যে কোনো ক্লায়েন্ট না আসলে, এটি অবিলম্বে একটি ত্রুটি দেবে এবং সার্ভার অন্য কাজ করতে থাকবে।Asynchronous সকেটের মাধ্যমে প্রোগ্রামটি কোনো একক থ্রেড বা প্রসেস ব্যবহার না করে, একাধিক সকেটের সাথে যোগাযোগ স্থাপন করতে পারে। এটি সাধারণত select()
বা epoll()
ব্যবহার করে একযোগভাবে একাধিক সকেট থেকে ডেটা গ্রহণ এবং পাঠানোর জন্য ব্যবহৃত হয়। এই পদ্ধতিতে, সকেটগুলোর মাধ্যমে যোগাযোগকে একযোগভাবে পরিচালনা করা যায়।
select()
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <arpa/inet.h>
#define PORT 65432
#define MAX_CLIENTS 10
int main() {
int server_socket, client_socket, max_sd;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);
char buffer[1024];
fd_set readfds;
// সার্ভার সকেট তৈরি
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// সার্ভারের IP এবং পোর্ট সেট করা
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
// সার্ভার সকেটে বাইন্ড করা
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
// লিসেনিং শুরু করা
if (listen(server_socket, 5) == -1) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
printf("Server is listening on port %d...\n", PORT);
// `select()` ব্যবহারের জন্য সকেট সেটআপ
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
max_sd = server_socket;
// ক্লায়েন্টের সংযোগের জন্য অপেক্ষা
while (1) {
fd_set tempfds = readfds;
int activity = select(max_sd + 1, &tempfds, NULL, NULL, NULL);
if (activity == -1) {
perror("select error");
exit(EXIT_FAILURE);
}
// নতুন সংযোগ পাওয়া গেলে
if (FD_ISSET(server_socket, &tempfds)) {
client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_len);
if (client_socket == -1) {
perror("Accept failed");
continue;
}
printf("New client connected\n");
FD_SET(client_socket, &readfds);
if (client_socket > max_sd) max_sd = client_socket;
}
// সকেট থেকে ডেটা পড়া
for (int i = 0; i <= max_sd; i++) {
if (FD_ISSET(i, &tempfds)) {
int valread = read(i, buffer, sizeof(buffer));
if (valread == 0) {
printf("Client disconnected\n");
close(i);
FD_CLR(i, &readfds);
} else {
printf("Received from client: %s\n", buffer);
send(i, "Message received", 16, 0);
}
}
}
}
close(server_socket);
return 0;
}
select()
ব্যবহার: select()
ফাংশন একাধিক সকেটের জন্য অপেক্ষা করে এবং যখন কোনো সকেট প্রস্তুত থাকে (যেমন ক্লায়েন্ট থেকে ডেটা আসে), তখন তা যথাযথভাবে পড়া হয়।select()
, poll()
, বা epoll()
ব্যবহারের মাধ্যমে আপনি একাধিক সকেটকে একযোগভাবে পরিচালনা করতে পারবেন, যা মাল্টি-ক্লায়েন্ট সার্ভারের জন্য অত্যন্ত উপকারী।এই দুটি কৌশলই উচ্চ পারফরম্যান্স এবং স্কেলেবল নেটওয়ার্ক অ্যাপ্লিকেশন তৈরি করতে সাহায্য করে, যেখানে একাধিক ক্লায়েন্টের সাথে একযোগে কাজ করা সম্ভব।
C Socket Programming হল একটি শক্তিশালী প্রক্রিয়া যা নেটওয়ার্ক অ্যাপ্লিকেশন তৈরি করতে ব্যবহৃত হয়। এটি সিস্টেমের মধ্যে বিভিন্ন প্রোগ্রামের মধ্যে যোগাযোগ বা নেটওয়ার্কের মাধ্যমে ডেটা আদান-প্রদান করতে সহায়তা করে। Advanced C socket programming বিভিন্ন কৌশল ব্যবহার করে, যেমন নন-ব্লকিং সকেট, মাল্টিপল ক্লায়েন্ট হ্যান্ডলিং, থ্রেডিং, এবং সিকিউর সকেট সংযোগ। এখানে Error Handling সম্পর্কে বিস্তারিত আলোচনা করা হবে যাতে আপনি সকেট প্রোগ্রামিংয়ে ত্রুটি হ্যান্ডলিং আরও দক্ষভাবে করতে পারেন।
C socket programming এ, সকেট দুটি প্রধান উপাদান হিসাবে কাজ করে:
একটি TCP সার্ভার যা একাধিক ক্লায়েন্টের সাথে যোগাযোগ স্থাপন করে এবং ডেটা গ্রহণ করে পাঠায়।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define MAX_CLIENTS 5
void handle_client(int client_socket) {
char buffer[1024] = {0};
int valread = read(client_socket, buffer, sizeof(buffer));
if (valread == -1) {
perror("Error reading from socket");
return;
}
printf("Client message: %s\n", buffer);
send(client_socket, "Hello from server", 18, 0);
close(client_socket);
}
int main() {
int server_fd, client_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, MAX_CLIENTS) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
printf("Server listening on port %d\n", PORT);
while (1) {
if ((client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("Accept failed");
continue;
}
printf("New client connected\n");
handle_client(client_socket);
}
return 0;
}
এই কোডটি একটি TCP সার্ভার তৈরি করে যা একাধিক ক্লায়েন্টের সাথে সংযোগ স্থাপন করতে সক্ষম এবং ক্লায়েন্টের পাঠানো বার্তা গ্রহণ এবং উত্তর পাঠায়।
UDP ব্যবহার করে একটি সার্ভার যা নির্দিষ্ট পোর্টে ডেটা গ্রহণ করবে।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define MAX_BUFFER_SIZE 1024
int main() {
int sockfd;
struct sockaddr_in server_addr, client_addr;
char buffer[MAX_BUFFER_SIZE];
socklen_t addrlen = sizeof(client_addr);
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("Server listening on UDP port %d\n", PORT);
while (1) {
int n = recvfrom(sockfd, (char *)buffer, MAX_BUFFER_SIZE, MSG_WAITALL,
(struct sockaddr *) &client_addr, &addrlen);
buffer[n] = '\0';
printf("Client message: %s\n", buffer);
sendto(sockfd, "Hello from server", 18, MSG_CONFIRM, (const struct sockaddr *) &client_addr, addrlen);
}
return 0;
}
এই কোডে, UDP সার্ভার নির্দিষ্ট পোর্টে ডেটা গ্রহণ করে এবং ক্লায়েন্টকে একটি উত্তর পাঠায়।
C Socket Programming-এ Error Handling অত্যন্ত গুরুত্বপূর্ণ কারণ এটি নেটওয়ার্ক কমিউনিকেশনে ব্যর্থতা রোধ করতে সহায়তা করে। সঠিক ত্রুটি পরিচালনা ছাড়া, একটি সিস্টেম বা অ্যাপ্লিকেশন যে কোনো মুহূর্তে ক্র্যাশ হতে পারে।
Socket Creation Error:
socket()
ফাংশন যদি সঠিকভাবে কাজ না করে, তখন এটি -1
রিটার্ন করে এবং errno
সেট করে।perror()
অথবা strerror()
ব্যবহার করে ত্রুটি বার্তা বের করা।int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
Bind Error:
bind()
ফাংশন পোর্ট বা আইপি ঠিকানায় সঠিকভাবে সংযুক্ত না হয়, এটি -1
রিটার্ন করে।if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}
Listen Error:
listen()
ফাংশন যদি কাজ না করে তবে এটি -1
রিটার্ন করে।if (listen(sockfd, 5) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}
Accept Error:
accept()
যদি ক্লায়েন্ট থেকে সংযোগ গ্রহণ করতে ব্যর্থ হয়, তাহলে এটি -1
রিটার্ন করে।int new_socket = accept(sockfd, (struct sockaddr *)&client_addr, &addr_len);
if (new_socket < 0) {
perror("Accept failed");
continue;
}
Send/Receive Error:
send()
বা recv()
ফাংশন ডেটা পাঠানোর বা গ্রহণের সময় ত্রুটি হতে পারে।int n = recv(new_socket, buffer, sizeof(buffer), 0);
if (n == -1) {
perror("Receive failed");
close(new_socket);
}
perror()
এবং strerror()
ব্যবহার করুন: সঠিক ত্রুটি বার্তা প্রিন্ট করতে perror()
বা strerror()
ব্যবহার করা উচিত।exit()
ব্যবহার করে প্রোগ্রাম থেকে বের হওয়ার পরিবর্তে, পুনরায় চেষ্টা বা সিস্টেম সম্পাদনের সঠিক কোড ব্যবহার করুন।Advanced C Socket Programming এবং Error Handling অত্যন্ত গুরুত্বপূর্ণ, কারণ এটি নেটওয়ার্ক প্রোগ্রামিংয়ের নির্ভরযোগ্যতা এবং স্থিতিশীলতা নিশ্চিত করে। ত্রুটি হ্যান্ডলিং প্রোগ্রামে ডেটা ট্রান্সফার এবং নেটওয়ার্ক সংযোগের ক্ষেত্রে ব্যর্থতার কারণে সিস্টেমের ক্র্যাশ বা অন্যান্য সমস্যা প্রতিরোধ করতে সহায়ক। C ভাষায় সকেট প্রোগ্রাম
িং ব্যবহার করে নেটওয়ার্ক অ্যাপ্লিকেশন তৈরি করার সময় সঠিক ত্রুটি পরিচালনা এবং নিরাপদ সংযোগ নিশ্চিত করা আবশ্যক।
common.read_more