برنامه‌نویسی سوکت در پایتون


۲ سال پیش چهارشنبه ۲۶ اسفند ۱۳۹۴ ساعت ۱۵:۳۲

برنامه‌نویسی سوکت

سوکت به زبان ساده

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

چرا برنامه‌نویسی سوکت را بیاموزیم؟

شما برای نوشتن یک وب اپلیکیشن مثل کلاینت‌های چت skype و gtalk نیاز به یادگیری برنامه‌نویسی سوکت دارید و یا در پروژه‌های رباتیک برای اعمال کنترل، می‌توانید از این برنامه‌نویسی سوکت به عنوان یکی از بهترین روش‌های تبادل اطلاعات تحت شبکه استفاده کنید.

پروتکل UDP و TCP

پروتکل UDP و TCP دو پروتکل معروف سوکت هستند.
پروتكل TCP جهت ارسال داده ها همراه با تضمين موفقيت آميز بودن عمل انتقال مانند دانلود و از پروتكل UDP جهت ارسال داده ها با سرعت بالا، اتصال به چند ماشين به طور همزمان و بدون تضمين موفقيت آميز بودن عمل انتقال مانند كاربردهای RealTime‌ از جمله ويدئو كنفرانس، Internet TV و ... استفاده می‌شود.

ساخت یک سوکت

برای ساخت یک سوکت کافیست از تابع socket.socket استفاده‌کنیم.

#Socket client example in python
 
import socket   #for sockets
 
#create an AF_INET, STREAM socket (TCP)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
print 'Socket Created'

تابع socket.socket یک سوکت ایجاد کرده و یک توصیفگر سوکت است که می تواند در دیگر توابع سوکت مربوط مورد استفاده قرار می گرداند  
کد بالا یک سوکت با خصوصیات زیر ایجاد خواهد کرد ...  
Address Family : AF_INET (این IP نسخه 4 یا IPv4 است)
Type : SOCK_STREAM (معنی پروتکل اتصال گرا TCP)

مدیریت خطا

هر کدام از توابع socket ی که با مشکل مواجه شوند یک exception با نام socket.error را بر می‌گرداند.

#handling errors in python socket programs
 
import socket   #for sockets
import sys  #for exit
 
try:
    #create an AF_INET, STREAM socket (TCP)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();
 
print 'Socket Created'

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

اتصال به سرور

ما برای اتصال به یک ریموت سرور به ۲ چیز نیازمندیم، ۱-آدرس آی پی  ۲-شماره پورت، پس نیاز داریم ابتدا آدرس IP سایت google.com را بدست آوریم.

  بدست آوردن آدرس IP با استفاده از URL

import socket   #for sockets
import sys  #for exit
 
try:
    #create an AF_INET, STREAM socket (TCP)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();
 
print 'Socket Created'
 
host = 'www.google.com'
 
try:
    remote_ip = socket.gethostbyname( host )
 
except socket.gaierror:
    #could not resolve
    print 'Hostname could not be resolved. Exiting'
    sys.exit()
     
print 'Ip address of ' + host + ' is ' + remote_ip

خب حالا ما IP سرور مورد نظرمان را داریم و می‌توانیم با یک پورت خاص با استفاده از تابع connect به آن متصل شویم.

import socket   #for sockets
import sys  #for exit
 
try:
    #create an AF_INET, STREAM socket (TCP)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();
 
print 'Socket Created'
 
host = 'www.google.com'
port = 80
 
try:
    remote_ip = socket.gethostbyname( host )
 
except socket.gaierror:
    #could not resolve
    print 'Hostname could not be resolved. Exiting'
    sys.exit()
     
print 'Ip address of ' + host + ' is ' + remote_ip
 
#Connect to remote server
s.connect((remote_ip , port))
 
print 'Socket Connected to ' + host + ' on ip ' + remote_ip

  نتیجه‌ی اجرای برنامه

$ python client.py
Socket Created
Ip address of www.google.com is 74.125.236.83
Socket Connected to www.google.com on ip 74.125.236.83

ارسال اطلاعات

تابع sendall به سادگی داده‌ها را ارسال می‌کند.

import socket   #for sockets
import sys  #for exit
 
try:
    #create an AF_INET, STREAM socket (TCP)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
    sys.exit();
 
print 'Socket Created'
 
host = 'www.google.com'
port = 80
 
try:
    remote_ip = socket.gethostbyname( host )
 
except socket.gaierror:
    #could not resolve
    print 'Hostname could not be resolved. Exiting'
    sys.exit()
     
print 'Ip address of ' + host + ' is ' + remote_ip
 
#Connect to remote server
s.connect((remote_ip , port))
 
print 'Socket Connected to ' + host + ' on ip ' + remote_ip
 
#Send some data to remote server
message = "GET / HTTP/1.1\r\n\r\n"
 
try :
    #Set the whole string
    s.sendall(message)
except socket.error:
    #Send failed
    print 'Send failed'
    sys.exit()
 
print 'Message send successfully'

در کد بالا بعد از متصل شدن به IP، پیغام رشته‌ای "GET / HTTP/1.1\r\n\r\n"  را ارسال کردیم.
این پیغام در واقع یک "http command" برای واکشی صفحه اصلی یک وب‌سایت است.

دریافت اطلاعات

از تابع recv برای دریافت داده ها بر روی یک سوکت استفاده می شود.
در مثال زیر پیغام مثال قبل را ارسال کرده و پاسخ سرور را دریافت می‌کنیم.

#Socket client example in python
 
import socket   #for sockets
import sys  #for exit
 
#create an INET, STREAMing socket
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
    print 'Failed to create socket'
    sys.exit()
     
print 'Socket Created'
 
host = 'www.google.com';
port = 80;
 
try:
    remote_ip = socket.gethostbyname( host )
 
except socket.gaierror:
    #could not resolve
    print 'Hostname could not be resolved. Exiting'
    sys.exit()
 
#Connect to remote server
s.connect((remote_ip , port))
 
print 'Socket Connected to ' + host + ' on ip ' + remote_ip
 
#Send some data to remote server
message = "GET / HTTP/1.1\r\n\r\n"
 
try :
    #Set the whole string
    s.sendall(message)
except socket.error:
    #Send failed
    print 'Send failed'
    sys.exit()
 
print 'Message send successfully'
 
#Now receive data
reply = s.recv(4096)
 
print reply

  خروجی کد بالا

$ python client.py
Socket Created
Ip address of www.google.com is 74.125.236.81
Socket Connected to www.google.com on ip 74.125.236.81
Message send successfully
HTTP/1.1 302 Found
Location: http://www.google.co.in/
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Set-Cookie: expires=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=www.google.com
Set-Cookie: path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=www.google.com
Set-Cookie: domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=www.google.com
Set-Cookie: expires=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com
Set-Cookie: path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com
Set-Cookie: domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com
Set-Cookie: expires=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=google.com
Set-Cookie: path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=google.com
Set-Cookie: domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=google.com
Set-Cookie: expires=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.google.com
Set-Cookie: path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.google.com
Set-Cookie: domain=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.google.com
Set-Cookie: PREF=ID=51f26964398d27b0:FF=0:TM=1343026094:LM=1343026094:S=pa0PqX9FCPvyhBHJ; expires=Wed, 23-Jul-2014 06:48:14 GMT; path=/; domain=.google.com

Google.com در پاسخ محتوای صفحه‌ای که ما درخواست داده بودیم را برمی‌گرداند.
خب حالا ما پاسخ خود را دریافت کرده‌ایم و نوبت این است که سوکت را ببندیم.

بستن سوکت

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

s.close()

نوشتن نظر
مهدیه کاشی - ۲۲ ماه و ۲۵ روز قبل
سلام الان این کد ها رو باید توی چی بنویسیم؟
سید محمدرضا برنتی - ۲۲ ماه و ۲۳ روز قبل
من از pycharm توی ویندوز استفاده می‌کنم، با جست‌وجوی شروع کار با پایتون توی گوگل به لینک‌های خوبی می‌رسید.
محمدرضا - ۱۹ ماه و ۱۵ روز قبل
عالی بود جناب برانتی خیلی مفید و کاربردی , سپاسگزارم :)
سید محمدرضا برنتی - ۱۹ ماه و ۱۳ روز قبل
خوشحالم از اینکه مفید بود، قابلی نداشت ;)
فرزان - ۱۱ ماه و ۲۴ روز قبل
سلام خیلی خوب و واضح بود ممنونم فقط کاش یه اشاره کوچیک ب تغیراتی ک باید توی پایتون3 روی این کدها انجام بدیم هم کرده بودین
علی - ۸ ماه و ۲۶ روز قبل
سلام بله درسته منم با نظر این دوستمون موافقم ،،، مثلا دستور print باید توی پرانتز باشه وگرنه نرم افزار pycharm خطا میده و برنامه رو اجرا نمیکنه ،،، ولی در کل مطلب مفیدی بود ، ممنون
محمد امین شهیدی - ۹ ماه و ۲۰ روز قبل
مرسی خیلی راحت و گویا بود.لطفا این مطلبو ادامه بدید و مباحث پیشرفته تر رو هم قرار بدید.
محمد علوی - ۷ ماه و ۹ روز قبل
با سلام من میخوام بین اندروید و پی سی به وسیله سوکت نویسی ارتباط بر قرار کنم: مثل نرم افزار چت تصویری و.. میخواستم بدونم ایا این امکان وجود دارد با b4a ؟ زبان سمت کلاینت که همان با b4a باشه و برای سرور با سی شارپ یا پایتون و... چه اموزشی پیشنهاد می کنید؟ سپاس
سید محمدرضا برنتی - ۶ ماه و ۲۸ روز قبل
سلام من تا بحال با b4a کار نکردم اما اگر میخواهید کاملا به سوکت مسلط بشید می‌تونید از داکیومنت رسمی سوکت در پایتون استفاده کنید. https://docs.python.org/2/library/socket.html برای انتخاب زبان سمت سرور هم قطعا زبانی برای شما مناسب تر هست که آشنایی بیشتری باهاش دارید.
علی - ۶ ماه و ۷ روز قبل
سلام ببخشید برای اینکه روی (reply = s.recv(4096 که دریافت کردیم یک محدودیتی بذاریم که فقط عدد و با سایز مشخصی رو قبول کنه باید چه تغییری بدیم؟ یعنی یعنی حروف و یا هر چیزی غیر از یک رشته عدد 123456789 رو بریزه دور. ممنون
* من از ایمیل شما برای نمایش تصویر شما توسط سرویس gravatar استفاده خواهم کرد. من هم مثل شما از اسپم متنفرم.