امروز شنبه ، ۱۴۰۱/۰۴/۱۱
بدان

TCP CHAT در پایتون: | TCP CHAT IN PYTHON:

TCP CHAT در پایتون:

معرفی:

Python یک زبان برنامه نویسی عالی برای شبکه های رایانه ای است.

این به ما اجازه می دهد تا برنامه های جامد را خیلی سریع و راحت ایجاد کنیم.

در این آموزش ، ما می خواهیم یک گپ کاملاً کاربردی TCP را پیاده سازی کنیم.

ما یک سرور خواهیم داشت که گپ را میزبانی می کند و چندین مشتری که به آن متصل شده و با یکدیگر ارتباط برقرار می کنند.

در پایان ، در صورت تمایل می توانید ویژگی های سفارشی مانند اتاق گفتگو ، دستورات ، نقش ها و غیره را نیز اضافه کنید.

معماری مشتری-سرور:

برای برنامه ما ، ما از معماری سرویس گیرنده-کلاینت استفاده خواهیم کرد.

این بدان معنی است که ما چندین مشتری (کاربران) و یک سرور مرکزی خواهیم داشت که میزبان همه چیز است و داده های این کلاینت ها را فراهم می کند.

بنابراین ، باید دو اسکریپت پایتون بنویسیم.

یکی برای راه اندازی سرور و دیگری برای مشتری خواهد بود.

ابتدا باید سرور را اجرا کنیم تا گپی وجود داشته باشد که مشتریان بتوانند به آن وصل شوند.

مشتریان خود قرار نیست مستقیماً با یکدیگر ارتباط برقرار کنند بلکه از طریق سرور مرکزی برقرار می شوند.

پیاده سازی سرور:

اکنون ابتدا با پیاده سازی سرور شروع می کنیم.

برای این منظور باید دو کتابخانه یعنی socket و threading وارد کنیم.

مورد اول برای اتصال شبکه استفاده می شود و مورد دوم برای انجام همزمان کارهای مختلف ضروری است.

import socket
import threading

وظیفه بعدی این است که داده های اتصال ما را تعریف کنیم و سوکت خود را مقداردهی کنیم.

ما به یک آدرس IP برای میزبان و یک شماره درگاه رایگان برای سرور خود نیاز خواهیم داشت.

در این مثال ، ما از آدرس localhost (127.0.0.1) و پورت 55555 استفاده خواهیم کرد.

درگاه در حقیقت بی ربط است اما باید مطمئن شوید که درگاهی که استفاده می کنید رایگان بوده و رزرو نشده است.

اگر این اسکریپت را روی یک سرور واقعی اجرا می کنید ، آدرس IP سرور را به عنوان میزبان مشخص کنید.

برای اطلاعات بیشتر ، این لیست شماره پورت رزرو شده را بررسی کنید.

 # Connection Data
 port = 55555
 
 # Starting Server
 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 server.bind((host, port))
 server.listen()
 
 # Lists For Clients and Their Nicknames
 clients = []
 nicknames = []

وقتی سوکت خود را تعریف می کنیم ، باید از دو پارامتر عبور کنیم.

این نوع سوکت را می خواهیم استفاده کنیم.

مورد اول (AF_INET) نشان می دهد که ما بیش از سوکت یونیکس از سوکت اینترنت استفاده می کنیم.

پارامتر دوم مخفف پروتکلی است که می خواهیم استفاده کنیم.

SOCK_STREAM نشان می دهد که ما از TCP استفاده می کنیم و نه از UDP.

پس از تعریف سوکت ، با عبور از یک تاپل که حاوی هر دو مقدار است ، آن را به میزبان خود و درگاه مشخص شده متصل می کنیم.

سپس سرور خود را در حالت گوش دادن قرار می دهیم تا منتظر اتصال مشتری باشد.

در پایان ما دو لیست خالی ایجاد می کنیم ، که بعداً برای ذخیره مشتریان متصل و نام مستعار آنها استفاده خواهیم کرد.

 # Sending Messages To All Connected Clients
 def broadcast(message):
     for client in clients:
         client.send(message)

در اینجا ما عملکرد کوچکی را تعریف می کنیم که به ما در پخش پیام کمک می کند و کد را بیشتر خوانا می کند.

کاری که انجام می شود فقط ارسال پیام برای هر مشتری است که متصل است و بنابراین در لیست مشتری است.

ما از این روش در روش های دیگر استفاده خواهیم کرد.

اکنون ما با اجرای اولین عملکرد اصلی شروع خواهیم کرد.

این عملکرد مسئولیت رسیدگی به پیام های مشتری را خواهد داشت.

 # Handling Messages From Clients
 def handle(client):
     while True:
         try:
             # Broadcasting Messages
             message = client.recv(1024)
             broadcast(message)
         except:
             # Removing And Closing Clients
             index = clients.index(client)
             clients.remove(client)
             client.close()
             nickname = nicknames[index]
             nicknames.remove(nickname)
             break

همانطور که مشاهده می کنید ، این عملکرد در یک حلقه while در حال اجرا است.

متوقف نخواهد شد مگر اینکه به دلیل مشکلی که اتفاق افتاده استثنا وجود داشته باشد.

این تابع یک مشتری را به عنوان یک پارامتر می پذیرد.

هر زمان که مشتری به سرور ما متصل می شود ، ما این عملکرد را برای آن اجرا می کنیم و یک حلقه بی پایان شروع می شود.

آنچه پس از آن انجام می شود دریافت پیام از مشتری (در صورت ارسال پیام) و پخش آن برای همه سرویس گیرندگان متصل است.

بنابراین وقتی یک مشتری پیامی ارسال می کند ، بقیه می توانند این پیام را ببینند.

حال اگر به دلایلی خطایی در اتصال به این سرویس گیرنده وجود داشته باشد ، ما آن و نام مستعار آن را حذف می کنیم ، اتصال را می بندیم و پخش می کنیم که این مشتری از چت خارج شده است.

بعد از آن حلقه را می شکنیم و این رشته به پایان می رسد.

کاملاً ساده

تقریباً کار با سرور تمام شده است اما به یک عملکرد نهایی نیاز داریم.

 # Receiving / Listening Function
 def receive():
     while True:
         # Accept Connection
         client, address = server.accept()
         print("Connected with {}".format(str(address)))
 
         # Request And Store Nickname
         nicknames.append(nickname)
         clients.append(client)
 
         # Print And Broadcast Nickname
         print("Nickname is {}".format(nickname))
 
         # Start Handling Thread For Client
         thread = threading.Thread(target=handle, args=(client,))
         thread.start()

هنگامی که ما آماده اجرای سرور خود هستیم ، این عملکرد دریافت را اجرا خواهیم کرد.

همچنین یک حلقه while بی پایان شروع می شود که دائماً ارتباطات جدیدی را از مشتری می پذیرد.

پس از اتصال مشتری ، آن رشته "NICK" را به آن می فرستد ، که به مشتری می گوید نام مستعار آن درخواست شده است.

پس از آن منتظر جواب می ماند (که امیدوارم شامل نام مستعار باشد) و مشتری را با نام مستعار مربوطه به لیست ها اضافه می کند.

پس از آن ، ما این اطلاعات را چاپ و پخش می کنیم.

سرانجام ، ما یک موضوع جدید شروع می کنیم که عملکرد مدیریت قبلاً پیاده سازی شده برای این مشتری خاص را اجرا می کند.

حالا ما فقط می توانیم این عملکرد را اجرا کنیم و سرور ما تمام شده است.

توجه داشته باشید که ما همیشه در اینجا پیام ها را رمزگذاری و رمزگشایی می کنیم.

دلیل این امر این است که ما فقط می توانیم بایت ارسال کنیم و نه رشته ای.

بنابراین وقتی پیام ها را می فرستیم و رمزگشایی می کنیم ، همیشه باید پیام ها را رمزگذاری کنیم (مثلاً با استفاده از ASCII).

 receive()

پیاده سازی مشتری:

یک سرور بدون مشتریانی که به آن متصل می شوند بسیار بی فایده است.

بنابراین اکنون ما می خواهیم مشتری خود را پیاده سازی کنیم.

برای این ، ما دوباره باید همان کتابخانه ها را وارد کنیم.

توجه داشته باشید که این یک اسکریپت جداگانه دوم است.

 import socket
 import threading

اولین مراحل مشتری انتخاب نام مستعار و اتصال به سرور ما است.

ما باید آدرس دقیق و درگاهی را که سرور ما در آن در حال اجرا است بدانیم.

 # Choosing Nickname
 nickname = input("Choose your nickname: ")
 
 # Connecting To Server
 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

همانطور که مشاهده می کنید ، ما در اینجا از یک عملکرد متفاوت استفاده می کنیم.

به جای اتصال داده ها و گوش دادن ، ما در حال اتصال به یک سرور موجود هستیم.

اکنون ، مشتری باید دو رشته داشته باشد که همزمان در حال اجرا هستند.

اولی به طور مداوم داده ها را از سرور دریافت می کند و دومی پیام های شخصی ما را به سرور ارسال می کند.

بنابراین در اینجا به دو عملکرد نیاز خواهیم داشت.

بیایید با قسمت دریافت کننده شروع کنیم.

 # Listening to Server and Sending Nickname
 def receive():
     while True:
         try:
             # Receive Message From Server
             else:
                 print(message)
         except:
             # Close Connection When Error
             print("An error occured!")
             client.close()
             break

باز هم ما در اینجا یک حلقه بدون پایان داریم.

به طور مداوم سعی می کند پیام ها را دریافت کند و آنها را بر روی صفحه چاپ کند.

اگر پیام "NICK" باشد ، آن را چاپ نمی کند اما نام مستعار خود را به سرور می فرستد.

در صورت بروز خطا ، اتصال را می بندیم و حلقه را می شکنیم.

اکنون ما فقط به یک عملکرد برای ارسال پیام نیاز داریم و تقریباً کار ما تمام شده است.

 # Sending Messages To Server
 def write():
     while True:

عملکرد نوشتن کاملاً کوتاه است.

همچنین در یک حلقه بی پایان اجرا می شود که همیشه منتظر ورودی کاربر است.

پس از دریافت مقداری ، آن را با نام مستعار ترکیب کرده و به سرور می فرستد.

خودشه.

آخرین کاری که باید انجام دهیم شروع دو رشته است که این دو عملکرد را اجرا می کند.

 # Starting Threads For Listening And Writing
 receive_thread = threading.Thread(target=receive)
 receive_thread.start()
 
 write_thread = threading.Thread(target=write)
 write_thread.start()

و اکنون کار ما تمام شده است.

ما یک سرور کاملاً فعال و مشتریانی فعال داریم که می توانند به آن متصل شده و با یکدیگر ارتباط برقرار کنند.

اجرای چت:

بیایید برای یک تست آزمایشی برویم.

فقط بخاطر داشته باشید که ما همیشه باید ابتدا سرور را راه اندازی کنیم زیرا در غیر این صورت سرویس گیرنده ها نمی توانند به یک میزبان غیر موجود متصل شوند.

در اینجا می توانید نمونه ای از گپ با دو مشتری را مشاهده کنید (در صورت تمایل می توانید با 20 نفر نیز ارتباط برقرار کنید):