সি-তে একটি কলব্যাক এমন একটি ফাংশন যা অন্য ফাংশনটি যখন অন্য ফাংশনটি তার কাজটি সম্পাদন করে তখন এক পর্যায়ে "কল টু ব্যাক" সরবরাহ করা হয়।
আছে দুটি উপায়ে যে একটি কলব্যাক ব্যবহৃত হয় সমকালীন কলব্যাক এবং অ্যাসিঙ্ক্রোনাস কলব্যাক। একটি সিঙ্ক্রোনাস কলব্যাক অন্য ফাংশনে সরবরাহ করা হয় যা কিছু কাজ করতে চলেছে এবং তারপরে টাস্কটি সম্পন্ন করে কলারে ফিরে আসবে। একটি অ্যাসিঙ্ক্রোনাস কলব্যাক অন্য ফাংশনে সরবরাহ করা হয় যা কোনও কাজ শুরু করতে চলেছে এবং তারপরে কলিংয়ের কাছে ফিরে আসা কার্যটি সম্পন্ন না করে।
একটি সিঙ্ক্রোনাস কলব্যাক সাধারণত অন্য ফাংশনে একটি প্রতিনিধি সরবরাহ করতে ব্যবহৃত হয় যেখানে অন্য ফাংশনটি কাজের কিছু ধাপকে প্রতিনিধিত্ব করে। এই প্রতিনিধিদলের ক্লাসিক উদাহরণ ফাংশন হয় bsearch()
এবং qsort()
সি স্ট্যান্ডার্ড লাইব্রেরী থেকে। এই উভয় ফাংশনই একটি কলব্যাক নেয় যা ফাংশনটি প্রদান করা টাস্ক চলাকালীন ব্যবহৃত হয় যাতে ডাটা যে ধরণের অনুসন্ধান করা হচ্ছে তার ক্ষেত্রে bsearch()
বা সাজানোর ক্ষেত্রে qsort()
ফাংশনটির দ্বারা তা জানা প্রয়োজন হবে না ব্যবহার করা হয়েছে।
উদাহরণস্বরূপ, এখানে bsearch()
বিভিন্ন তুলনা ফাংশন, সিঙ্ক্রোনাস কলব্যাক্স সহ একটি ছোট নমুনা প্রোগ্রাম । কলব্যাক ফাংশনটির সাথে আমাদের তুলনা করে ডেটা অর্পণ করার অনুমতি দিয়ে, bsearch()
ফাংশনটি আমাদের কোন ধরণের তুলনা ব্যবহার করতে চাই তা রান সময়ে সিদ্ধান্ত নিতে দেয়। এটি সিঙ্ক্রোনাস কারণ bsearch()
ফাংশনটি যখন ফিরিয়ে দেয় তখন টাস্কটি সম্পূর্ণ হয়।
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int iValue;
int kValue;
char label[6];
} MyData;
int cmpMyData_iValue (MyData *item1, MyData *item2)
{
if (item1->iValue < item2->iValue) return -1;
if (item1->iValue > item2->iValue) return 1;
return 0;
}
int cmpMyData_kValue (MyData *item1, MyData *item2)
{
if (item1->kValue < item2->kValue) return -1;
if (item1->kValue > item2->kValue) return 1;
return 0;
}
int cmpMyData_label (MyData *item1, MyData *item2)
{
return strcmp (item1->label, item2->label);
}
void bsearch_results (MyData *srch, MyData *found)
{
if (found) {
printf ("found - iValue = %d, kValue = %d, label = %s\n", found->iValue, found->kValue, found->label);
} else {
printf ("item not found, iValue = %d, kValue = %d, label = %s\n", srch->iValue, srch->kValue, srch->label);
}
}
int main ()
{
MyData dataList[256] = {0};
{
int i;
for (i = 0; i < 20; i++) {
dataList[i].iValue = i + 100;
dataList[i].kValue = i + 1000;
sprintf (dataList[i].label, "%2.2d", i + 10);
}
}
// ... some code then we do a search
{
MyData srchItem = { 105, 1018, "13"};
MyData *foundItem = bsearch (&srchItem, dataList, 20, sizeof(MyData), cmpMyData_iValue );
bsearch_results (&srchItem, foundItem);
foundItem = bsearch (&srchItem, dataList, 20, sizeof(MyData), cmpMyData_kValue );
bsearch_results (&srchItem, foundItem);
foundItem = bsearch (&srchItem, dataList, 20, sizeof(MyData), cmpMyData_label );
bsearch_results (&srchItem, foundItem);
}
}
একটি অ্যাসিঙ্ক্রোনাস কলব্যাক এর মধ্যে আলাদা হয় যখন কল কলটি আমরা কলব্যাক রিটার্ন সরবরাহ করি তখন টাস্কটি সম্পন্ন নাও হতে পারে। এই ধরণের কলব্যাক প্রায়শই অ্যাসিনক্রোনাস আই / ও এর সাথে ব্যবহৃত হয় যার মধ্যে একটি আই / ও ক্রিয়াকলাপ শুরু হয় এবং তারপরে এটি শেষ হয়ে গেলে কলব্যাকটি চাওয়া হয়।
নিম্নলিখিত প্রোগ্রামে আমরা টিসিপি সংযোগের অনুরোধগুলির জন্য শোনার জন্য একটি সকেট তৈরি করি এবং যখন কোনও অনুরোধ পাওয়া যায়, শ্রবণটি করে ফাংশনটি প্রদত্ত কলব্যাক ফাংশনটি আহ্বান করে। এই সাধারণ অ্যাপ্লিকেশনটি telnet
অন্য উইন্ডোতে সংযোগ স্থাপনের চেষ্টা করতে ইউটিলিটি বা ওয়েব ব্রাউজার ব্যবহার করার সময় এটি একটি উইন্ডোতে চালিত করে ব্যবহার করা যেতে পারে ।
মাইক্রোসফ্ট https://msdn.microsoft.com/en-us/library/windows/desktop/ms737526(vvv..85).aspxaccept()
এ মাইক্রোসফ্ট ফাংশনটি সরবরাহ করে তার উদাহরণ থেকে আমি বেশিরভাগ উইনসক কোডটি তুলেছি
এই অ্যাপ্লিকেশনটি listen()
স্থানীয় হোস্টে, 127.0.0.1 থেকে একটি পোর্ট 8282 ব্যবহার করে আরম্ভ করবে যাতে আপনি হয় telnet 127.0.0.1 8282
বা ব্যবহার করতে পারেন http://127.0.0.1:8282/
।
এই নমুনা অ্যাপ্লিকেশনটি ভিজ্যুয়াল স্টুডিও 2017 সম্প্রদায়ের সংস্করণ সহ একটি কনসোল অ্যাপ্লিকেশন হিসাবে তৈরি করা হয়েছিল এবং এটি সকেটের মাইক্রোসফ্ট উইনসক সংস্করণ ব্যবহার করছে। একটি লিনাক্স অ্যাপ্লিকেশনের জন্য উইনসক ফাংশনগুলি লিনাক্স বিকল্পগুলির সাথে প্রতিস্থাপন করা প্রয়োজন এবং উইন্ডোজ থ্রেড লাইব্রেরির pthreads
পরিবর্তে ব্যবহার করা হবে।
#include <stdio.h>
#include <winsock2.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
// function for the thread we are going to start up with _beginthreadex().
// this function/thread will create a listen server waiting for a TCP
// connection request to come into the designated port.
// _stdcall modifier required by _beginthreadex().
int _stdcall ioThread(void (*pOutput)())
{
//----------------------
// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
printf("WSAStartup failed with error: %ld\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for listening for
// incoming connection requests.
SOCKET ListenSocket;
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
struct sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(8282);
if (bind(ListenSocket, (SOCKADDR *)& service, sizeof(service)) == SOCKET_ERROR) {
printf("bind failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
//----------------------
// Listen for incoming connection requests.
// on the created socket
if (listen(ListenSocket, 1) == SOCKET_ERROR) {
printf("listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
//----------------------
// Create a SOCKET for accepting incoming requests.
SOCKET AcceptSocket;
printf("Waiting for client to connect...\n");
//----------------------
// Accept the connection.
AcceptSocket = accept(ListenSocket, NULL, NULL);
if (AcceptSocket == INVALID_SOCKET) {
printf("accept failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
else
pOutput (); // we have a connection request so do the callback
// No longer need server socket
closesocket(ListenSocket);
WSACleanup();
return 0;
}
// our callback which is invoked whenever a connection is made.
void printOut(void)
{
printf("connection received.\n");
}
#include <process.h>
int main()
{
// start up our listen server and provide a callback
_beginthreadex(NULL, 0, ioThread, printOut, 0, NULL);
// do other things while waiting for a connection. In this case
// just sleep for a while.
Sleep(30000);
}