কম্পিউটার টিউটোরিয়াল

পাইথনে সকেট প্রোগ্রামিং মাল্টি-থ্রেডিং সহ


মাল্টি-থ্রেডিং কনসেপ্ট

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

একটি থ্রেড হলো একটি প্রোগ্রামের সাব-প্রোগ্রাম যা কোডের অন্যান্য অংশ থেকে স্বাধীনভাবে এক্সিকিউট হতে পারে। একটি থ্রেড একই কনটেক্সটে এক্সিকিউট হয় প্রোগ্রামের রাননেবল রিসোর্স (যেমন: মেমরি) শেয়ার করে।

যখন একটি সিঙ্গেল প্রসেসে, আমরা একসাথে একাধিক থ্রেড এক্সিকিউট করি, তাকে মাল্টি-থ্রেডিং বলা হয়।

থ্রেড বাস্তবায়নের জন্য পাইথন মাল্টি-থ্রেডিং মডিউল

প্রোগ্রামে থ্রেড বাস্তবায়ন করার জন্য পাইথন দুটি মডিউল প্রদান করে:

  • thread (পাইথন ২.x জন্য) বা _thread (পাইথন ৩.x জন্য) মডিউল
  • threading মডিউল

thread মডিউল একটি ফাংশন হিসেবে থ্রেড তৈরি করে, অন্যদিকে threading মডিউল অবজেক্ট-ওরিয়েন্টেড পদ্ধতিতে থ্রেড তৈরি করার সুবিধা দেয়।

সিনট্যাক্স

_thread.start_new_thread(func, args[, kwargs])

উপরের কোডটি একটি নতুন থ্রেড শুরু করে এবং এর আইডেন্টিফায়ার রিটার্ন করে। প্রথম আর্গুমেন্ট হলো একটি ফাংশন func যা থ্রেডটি এক্সিকিউট করবে দ্বিতীয় আর্গুমেন্টের সাথে যা একটি টাপল যা পজিশনাল আর্গুমেন্টের তালিকা ধারণ করে। অপশনাল kwargs আর্গুমেন্টটি কীওয়ার্ড আর্গুমেন্টের একটি ডিকশনারি নির্দিষ্ট করে। ফাংশন রিটার্ন করলে থ্রেড সাইলেন্টলি এক্সিট করে।

এখানে আমরা একটি বেসিক ক্লায়েন্ট-সার্ভার অ্যাপ্লিকেশন দেখব। যেখানে ক্লায়েন্টরা মূলত একটি সকেট কানেকশন খুলে সার্ভারের কাছে কুয়েরি পাঠায়। সার্ভার প্রতিক্রিয়া জানায়।

আর্গুমেন্ট ছাড়া চালালে, এই প্রোগ্রামটি একটি TCP সকেট সার্ভার হিসেবে শুরু হয় যা 127.0.0.1 এর পোর্ট ৮০০০-এ কানেকশন লিসেন করে।

client_thread1.py

import socket
import sys

def main():
    soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = "127.0.0.1"
    port = 8000
    try:
        soc.connect((host, port))
    except:
        print("Connection Error")
        sys.exit()
    print("Please enter 'quit' to exit")
    message = input(" -> ")
    while message != 'quit':
        soc.sendall(message.encode("utf8"))
        if soc.recv(5120).decode("utf8") == "-":
            pass  # নাল অপারেশন
        message = input(" -> ")
    soc.send(b'--quit--')

if __name__ == "__main__":
    main()

অন্যদিকে সার্ভার প্রোগ্রামটি:

server_thread1.py

import socket
import sys
import traceback
from threading import Thread

def main():
    start_server()

def start_server():
    host = "127.0.0.1"
    port = 8000  # আربیট্রারি নন-প্রিভিলেজড পোর্ট
    soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    print("Socket created")
    try:
        soc.bind((host, port))
    except:
        print("Bind failed. Error : " + str(sys.exc_info()))
        sys.exit()
    soc.listen(6)  # ৬ রিকোয়েস্ট কিউ করুন
    print("Socket now listening")
    # ইনফিনিট লুপ - প্রতিটি রিকোয়েস্টের জন্য রিসেট না করে
    while True:
        connection, address = soc.accept()
        ip, port = str(address[0]), str(address[1])
        print("Connected with " + ip + ":" + port)
        try:
            Thread(target=client_thread, args=(connection, ip, port)).start()
        except:
            print("Thread did not start.")
            traceback.print_exc()
    soc.close()

def clientThread(connection, ip, port, max_buffer_size=5120):
    is_active = True
    while is_active:
        client_input = receive_input(connection, max_buffer_size)
        if "--QUIT--" in client_input:
            print("Client is requesting to quit")
            connection.close()
            print("Connection " + ip + ":" + port + " closed")
            is_active = False
        else:
            print("Processed result: {}".format(client_input))
            connection.sendall("-".encode("utf8"))

def receive_input(connection, max_buffer_size):
    client_input = connection.recv(max_buffer_size)
    client_input_size = sys.getsizeof(client_input)
    if client_input_size > max_buffer_size:
        print("The input size is greater than expected {}".format(client_input_size))
    decoded_input = client_input.decode("utf8").rstrip()
    result = process_input(decoded_input)
    return result

def process_input(input_str):
    print("Processing the input received from client")
    return "Hello " + str(input_str).upper()

if __name__ == "__main__":
    main()

উপরের স্ক্রিপ্ট চালাতে, টার্মিনালে server_thread1.py রান করুন:

python server_thread1.py
Socket created
Socket now listening

সার্ভার উইন্ডোটি পর্যবেক্ষণ করুন এবং ফ্লো বুঝুন। এখন একাধিক ক্লায়েন্ট টার্মিনাল খুলে ক্লায়েন্ট থ্রেড রান করুন:

python client_thread1.py
Enter 'quit' to exit
-> Zack
->

আরেকটি টার্মিনালে অন্য ক্লায়েন্ট প্রোগ্রাম রান করুন এবং সার্ভার টার্মিনাল ও দেখুন:

python client_thread1.py
Enter 'quit' to exit
-> Python
-> quit

আরেকটি টার্মিনালে ক্লায়েন্ট থ্রেড রান করুন:

python client_thread1.py
Enter 'quit' to exit
-> world!
-> Anothny
->

আমরা দেখতে পাবো সার্ভার উইন্ডোতে আউটপুট কিছু এই রকম আসছে:

Socket created
Socket now listening
Connected with 127.0.0.1:50275
Processing the input received from client
Processed result: Hello ZACK
Connected with 127.0.0.1:50282
Processing the input received from client
Processed result: Hello PYTHON
Processing the input received from client
Client is requesting to quit
Connection 127.0.0.1:50282 closed
Connected with 127.0.0.1:50285
Processing the input received from client
Processed result: Hello WORLD!
Processing the input received from client
Processed result: Hello ANOTHNY

সুতরাং, থ্রেড একাধিক সকেট কানেকশন এবং ক্লায়েন্ট হ্যান্ডেল করার সবচেয়ে সাধারণ টেকনিকlerden একটি।

  1. পাইথনে Tkinter প্রোগ্রামিং

  2. উইন্ডোজে পাইথন প্রোগ্রামিং-এ IDE সমূহ

  3. পাইথনে মেটাক্লাস ব্যবহার করে মেটা প্রোগ্রামিং

  4. পাইথনে Turtle গ্রাফিক্স: আঙ্কন ও অ্যানিমেশন