บทความวันนี้จะนำเสนอการเขียนโปรแกรมเครือข่ายด้วยซ็อกเก็ต โดยใช้ภาษายอดนิยมแห่งยุคนี้คือ python ครับ สำหรับใครที่เพิ่งมาอ่านบทความในซีรีย์นี้เป็นครั้งแรก แนะนำว่าให้ไปอ่านตอนที่ 1 ตอนที่ 2 ก่อนนะครับ เพื่อให้ได้พื้นฐานความเข้าใจเรื่องซ็อกเก็ตก่อน
สำหรับบทความนี้ผมจะแสดงตัวอย่างโปรแกรมที่ทำงานเหมือนกับโปรแกรมภาษา Java ในตอนที่ 3 และตอนที่ 4 ที่มีการทำงานโดยการที่ผู้ใช้จะพิมพ์ข้อความเป็นภาษาอังกฤษทางฝั่งไคลเอนต์ (client) จากนั้นส่งข้อมูลมาให้เซิร์ฟเวอร์ (server) ซึ่งจะแปลงตัวอักษรดังกล่าวให้เป็นตัวพิมพ์ใหญ่ทั้งหมด แล้วส่งกลับไปให้ฝั่งไคลเอนต์แสดงผล
โปรแกรมฝั่งเซิร์ฟเวอร์แสดงได้ดังนี้ครับ
01: # tcpserver.py
02: import socket
03: welcomeSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
04: welcomeSocket.bind(("localhost", 6789))
05: welcomeSocket.listen(5)
06: while True:
07: print("The server is waiting")
08: connectionSocket, address = welcomeSocket.accept()
09: clientSentenceBytes = connectionSocket.recv(4096)
10: clientSentence = clientSentenceBytes.decode("utf-8")
11: connectionSocket.send(str.encode(clientSentence.upper()))
12: connectionSocket.close()
บรรทัดที่ 2 คือการอิมพอร์ต socket โมดูล บรรทัดที่ 3 สร้างเซิร์ฟเวอร์ซ็อกเก็ตเพื่อรอรับการติดต่อ โดยพารามิเตอร์ที่ใช้ในการสร้างมี 2 ตัว ตัวแรกคือ socket.AF_INET ซึ่งหมายถึงเราระบุว่าจะใช้ IP เวอร์ชัน 4 ตัวที่สอง socket.SOCK_STREAM หมายถึงโปรโตคอล TCP
บรรทัดที่ 4 ระบุชื่อโฮสต์และพอร์ตที่จะรอบรับการติดต่อ ใช้ localhost เป็นชื่อโฮสต์ เพราะต้องการจะให้การติดต่ออยู่ภายในเครื่องเดียวกันเท่านั้น ถ้าต้องการให้เครื่องภายนอกติดต่อเข้ามาได้ให้ใช้ สตริงว่าง ("") แทน ส่วนพอร์ตที่จะรอรับการติดต่อคือ 6789
บรรทัดที่ 5 กำหนดจำนวนไคลเอนต์ที่จะเข้าคิวรอรับการบริการ ซึ่งในโปรแกรมนี้กำหนดเป็น 5 ตัว นั่นคือถ้าเซิร์ฟเวอร์ให้บริการไคล์เอนต์ตัวอื่นอยู่ จะมีไคลเอนต์เข้ามารอรับการบริการสูงสุดได้ 5 ตัว คือถ้ามี 5 ตัวรอบริการอยู่จนเต็มแล้ว ตัวที่ 6 ที่เข้ามาจะถูกปฏิเสธ
จากนั้นเซิร์ฟเวอร์ก็จะเข้าสู่ลูปไม่รู้จบตามการทำงานของเซิร์ฟเวอร์ทั่ว ๆ ไป โดยในลูปนี้ บรรทัดที่ 8 เซิร์ฟเวอร์จะบล็อกรอรับการติดต่อจากไคลเอนต์ โดยเมื่อมีไคลเอนต์ติดต่อเข้ามา จะมีการสร้างซ็อกเก็ตเชื่อมต่อ (connection socket) อ้างถึงโดยตัวแปร connectionSocket และหมายเลขไอพี (IP Address) ของเครื่องไคลเอนต์ที่ติดต่อเข้ามา อ้างถึงโดยตัวแปร address
บรรทัดที่ 9 รออ่านข้อมูลที่ไคลเอนต์จะส่งเข้ามา โดยในที่นี้จะรับข้อมูลขนาดไม่เกิน 4096 ไบต์ คำแนะนำสำหรับขนาดที่เราควรระบุก็คือเป็น 2 ยกกำลังที่ไม่มากนัก ในที่นี่ใช้ 2 ยกกำลัง 12 ก็คือ 4096 ไบต์ครับ สมมติถ้าเราต้องการรับข้อมูลขนาดใหญ่ แทนที่จะกำหนดค่าให้ใหญ่ ๆ วิธีที่ดีกว่าก็คือการวนลูปอ่านข้อมูล ครับ ซึ่งในตัวอย่างนี้ผมจะขอละไว้นะครับ เพราะต้องการแสดงแค่แนวคิดการเขียนโปรแกรมเบื้องต้น
บรรทัดที่ 10 เป็นการ decode ข้อมูลที่อ่านมาจากซ็อคเก็ตที่อยู่ในรูปสตรีมของไบต์ (stream of bytes) ให้เป็นสตริง เพื่อที่จะได้เรียกใช้ฟังก์ชัน upper() เพื่อแปลงข้อมูลที่รับมาให้เป็นตัวอักษรภาษาอังกฤษตัวใหญ่
บรรทัดที่ 11 จะซับซ้อนนิดหนึ่งนะครับ เพราะทำหลายอย่าง ในส่วน clientSentence.upper() ก็คือการแปลงข้อมูลเป็นตัวอักษรตัวใหญ่ ในส่วน str.encode(clientSentence.upper()) ก็คือการทำให้สตริงที่จะส่งไป (ในที่นี้คือสตริงที่เราแปลงเป็นตัวใหญ่) อยู่ในรูปสายธารของไบต์ จากนั้นก็ใช้ฟังก์ชัน send() ส่งข้อมูลผ่านซ็อกเก็ตกลับไปให้ไคลเอนต์
บรรทัดที่ 12 ก็คือการปิดซ็อกเก็ตเชื่อมต่อกับไคลเอนต์ หลังจากบรรทัดนี้โปรแกรมก็จะวนกลับไปต้นลูปเพื่อรอรับการติดต่อและให้บริการไคลเอนต์ตัวต่อไป
คราวนี้มาดูโปรแกรมฝั่งไคลเอนต์กันครับ
01: # tcpclient.py
02: import socket
03: sentence = input("Please enter words: ")
04: clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
05: clientSocket.connect(("localhost", 6789))
06: clientSocket.send(str.encode(sentence))
07: modifiedSentenceBytes = clientSocket.recv(4096)
08: modifiedSentence = modifiedSentenceBytes.decode("utf-8")
09: clientSocket.close()
10: print(modifiedSentence)
ไม่มีความคิดเห็น:
แสดงความคิดเห็น