วันศุกร์ที่ 30 ธันวาคม พ.ศ. 2554

เขียนโปรแกรม Client / Server ง่าย ๆ สไตล์ไพธอนบนแอนดรอย

สวัสดีครับ สุดยอดของความรู้ด้านเน็ตเวร์คสำหรับโปรแกรมเมอร์คือ การเข้าใจหลักการของแม่ข่าย และวิธีการในการรับส่งข้อมูลได้ วันนี้ผมจะเอาหัวใจของการรับและส่งข้อมูลระหว่างแม่ข่ายและลูกข่ายมาเล่าให้ฟัง มีใจความดังนี้

พิจารณาโค๊ดแม่ข่ายต่อไปนี้

import socket
PORT = 8037

service = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
service.bind(("", PORT))
service.listen(1)

print "listening on port", PORT

while 1:
channel, info = service.accept()
print "connection from", info
channel.send("Hello")
channel.close()


พิจารณาโค๊ดจากลูกข่ายต่อไปนี้

import socket

# ระบุหมายเลข IP และหมายเลขพอร์ตของเครื่อง Server
Host = "127.0.0.1"
Port = 8037

# สร้างการเชื่้อมต่อไปยังเครื่อง Server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((Host, Port))

# อ่านข้อมูลจากเครื่อง Server จำนวน 5 ตัวอักษร(ไบต์)
t = s.recv(5)
s.close()

# แสดงข้อมูลที่รับมาจากเครื่อง Server ให้ปรากฎที่จอภาพ
print "Received : ",t , " Len : ", len(t)

คำอธิบาย

การทำงานพอเป็นสังเขป :
1. ให้เครื่อง Server รันสคริปต์ทิ้งเอาไว้ในตัวอย่างนี้จะให้เครื่องแอนดรอยทำงานเป็นแม่ข่าย (server)
2. เมื่อไรที่ Client เข้ามาที่เครื่องของเซอร์เวอร์ให้ทำงานตามเงื่อนไข
3. รันโปรแกรมเครื่องแม่ข่ายเอาไว้
4. เครื่อง Client รันโปรแกรมฝั่งลูกข่ายจะได้ผลลัพธ์คือ Received : Hello Len : 5

อธิบายโค๊ดฝั่งแม่ข่าย

1. บรรทัด import socket ขอใช้โมดูล socket
2. บรรทัด PORT = 8037 กำหนดหมายเลขพอร์ทในการสื่อสารระหว่างลูกข่ายและแม่ข่าย
3. service = socket.socket(socket.AF_INET, socket.SOCK_STREAM) อาร์กิวเมนต์ของการสร้างคลาส socket คือ socket.AF_INET และ socket.SOCK_STREAM เป็นการกำหนดข้อตกลงในการเชื่อมต่อแบบสตรีม

4. บรรทัด service.bind(("", PORT)) การผูกหมายเลขพอร์ท

5. บรรทัด service.listen(1) ให้แม่ข่ายคอยฟังว่ามีใครสื่อสารเข้ามามั้ย

6. บรรทัด print "listening on port", PORT แสดงข้อความและหมายเลขพอร์ท

7. บรรทัด while 1:  ทำการวนรอบไม่สิ้นสุด
       channel, info = service.accept()  หากมีการติดต่อเข้ามาให้รับการติดต่อจากลูกข่าย ขณะที่กำลังรอการติดต่อระหว่างเครื่องลูกข่าย อ็อบเจ็ค service จะเรียกฟังก์ชั่น accept() ซึ่งจะคืนค่าเป็นลีสต์ 2 อัน อันแรกคือ ช่องทางการเชื่อมต่อ ผู้เขียนให้เก็บไว้ในตัวแปร channel ในขณะที่ลีสต์อีกตัวหนึ่งสำหรับข้อมูลจากเครื่องลูกข่าย ผู้เขียนกำหนดไว้ในตัวแปร info เมื่อมีการร้องขอจากลูกข่ายจะแสดงคำว่า "connection from" , info ซึ่งตัวแปร info จะเก็บหมายเลข IP และพอร์ทที่ใช้เชื่อมต่อจากลูกข่าย

       print "connection from", info  จากนั้นแสดงข้อความบนแม่ข่ายว่ามีการติดต่อสื่อสารเข้ามา
       channel.send("Hello")  ส่งข้อมูลไปหาลูกข่าย ออกไปยังช่องทางที่ได้รับการเชื่่อมต่อจากแม่ข่ายและลูกข่าย
       channel.close()  เมื่อส่งข้อความเสร็จเรียบร้อย ให้ปิดช่องทางการสื่อสาร




พิจารณาที่ฝั่งลูกข่าย เมื่อเรียกคำสั่ง python client.py ไพธอนจะแปลความดังรายละเอียดต่อไปนี้
ตัวแปร Host ใช้เก็บหมายเลข IP Address ของเครื่องแม่ข่าย (ค่า default คือ 127.0.0.1 สำหรับเครื่องที่จำลองการเชื่อมต่อเน็ตเวอร์ค)

ตัวแปร Port กำหนดให้ตรงกันกับพอร์ทที่แม่ข่ายกำหนดไว้ จากนั้น สร้างอินสแตนท์ของคลาส socket.socket() โดยผู้เขียนให้ชื่ออ็อบเจ็ค s การสร้างอินสแตนท์ทำเหมือนสคริปต์ฝั่งแม่ข่าย

จากนั้นเรียกใช้คำสั่ง connect() ภายในอ็อบเจ็ค s โดยระบุอาร์กิวเมนต์แรกคือหมายเลข IP Address ของเครื่องแม่ข่าย และอาร์กิวเมนต์ที่สองคือหมายเลขพอร์ทที่ใช้เชื่อมต่อกับแม่ข่าย

ลำดับถัดมาทำการอ่านข้อมูลออกมาจากเครื่องแม่ข่ายเป็นจำนวน 5 ไบต์ ด้วยคำสั่ง recv() และเก็บไว้ภายในตัวแปร t จากนั้นปิดคอนเน็คชั่นด้วยคำสั่ง close()

ผลลัพธ์ที่เก็บไว้ในตัวแปร t สามารถนำไปใช้งานต่อไปได้ ในตัวอย่างนี้แสดงให้ปรากฎบนจอภาพคอมพิวเตอร์ และแสดงจำนวนความยาวของตัวแปร t ซึ่งมีค่า 5 ไบต์

เนื้อหาที่นำเสนอวันนี้เป็นหลักการสำคัญมาก ของการอิมพลิเมนต์ระบบแม่ข่ายและลูกข่าย โดยที่ท่านไม่ต้องใช้โปรแกรม apache เลย เพราะท่านกำลังทำตัวเองเป็นโปรแกรม apache ครับ หวังว่าจะเป็นประโยชน์กับท่านทั้งหลาย พบกันใหม่โอกาสต่อไป สำหรับวันนี้สวัสดีครับ

ไม่มีความคิดเห็น:

แสดงความคิดเห็น