Socket Programming นั้นเป็นการเขียนโปรแกรมที่ใช้ Socket เป็นช่องทางที่ใช้สำหรับการรับส่งข้อมูลกันระหว่างเครื่องหรือโปรแกรม โดยอาจจะเป็นระหว่าง server กับ client ซึ่งการรับส่งข้อมูลสามารถทำได้ทั้งสองทางและเก็บสถานะการติดต่อแต่ละครั้งเอาไว้ได้ ในขณะที่ถ้าเป็นการรับส่งข้อมูลแบบ REST จะไม่จำสถานะการติดต่อของแต่ละครั้ง และการติดต่อต้องเริ่มจากฝั่งใดฝั่งหนึ่งเท่านั้น
ขั้นตอนการทำงานของ Socket
ในการใช้งาน Socket นั้นจะต้องมีฝั่งหนึ่งที่ทำการเริ่มสร้างช่องทางการเชื่อมต่อขึ้นมา แล้วให้อีกฝั่งหนึ่งเข้ามาเชื่อมต่อ ซึ่งส่วนใหญ่ server จะเป็นฝั่งที่สร้างเอาไว้และให้ client เข้ามาเชื่อมต่อ โดยจุดที่ต่างจาก REST ที่เป็นการ request จาก client ไปยัง server เพื่อส่งและรับข้อมูลเพียงอย่างเดียวก็คือ socket นั้นเมื่อเชื่อมต่อกันแล้ว server เองก็สามารถเริ่มการส่งข้อมูลติดต่อไปยัง client ได้ด้วย ไม่ต้องรอให้ client เป็นเริ่ม
ในภาษาโปรแกรมหลายๆภาษาก็มีการสร้าง library ให้สามารถใช้งาน socket กันได้ โดยอาจจะมีชื่อคำสั่งที่แตกต่างกันออกไปบ้าง แต่ขั้นตอนการทำงานหลักคล้ายกัน ซึ่งถ้าอ้างอิงตามเว็บไซต์ ibm เราจะสามารถแบ่งขั้นตอนการทำงานออกเป็น 7 ขั้นตอนดังนี้
- สร้าง socket object ไว้สำหรับเรียกใช้งาน API ของ socket
- หลังจากได้ตัว socket object มาแล้ว โปรแกรมหรือแอพพลิเคชันฝั่ง server ของเราก็จะสามารถ bind() คือการกำหนดค่าต่างๆที่จำเป้นให้กับ socket object เช่น IP Address และ port เพื่อให้สามารถเข้าถึงด้วยค่าที่กำหนดขึ้นผ่านทางเน็ตเวิร์คได้
- หลังจาก bind() เรียบร้อยแล้ว ฟังก์ชัน listen() จะทำงานโดยรอรับคำขอเชื่อมต่อจาก client
- client จะใช้ conenct() API เพื่อสร้างการเชื่อมต่อไปยัง server
- เมื่อคำขอเชื่อต่อจาก client มาถึง server ฝั่ง server จะยอมรับการเชื่อมต่อนั้นผ่าน accept() API ซึ่งจะใช้งานได้ก็ต่อเมื่อทำการ bind() และ listen() สำเร็จแล้วเท่านั้น
- เมื่อสร้างการเชื่อมต่อระหว่าง client กับ server สำเร็จแล้ว ทั้งสองฝั่งจะสามารถส่งข้อมูลหากันโดยใช้ API สำหรับส่งข้อมูลเช่น send(), recv(), read(), write() ฯลฯ
- ถ้า client กับ server ส่งข้อมูลกันเรียบร้อยแล้วหรือต้องการจะหยุดการเชื่อมต่อ ก็จะเรียกใช้ close() API เพื่อตัดการเชื่อมต่อและคืนทรัพยากรที่ถูกใช้โดย socket ให้กับระบบ
ตัวอย่างโปรแกรมรับส่งข้อมูลด้วย Socket (Python)
สำหรับโค้ดตัวอย่างการใช้งาน socket นี้จะมีอยู่ด้วยกัน 2 ไฟล์ โดยไฟล์แรกจะใช้สำหรับเป็นฝั่ง server ที่ทำการเริ่มสร้าง socket เอาไว้ ส่วนอีกไฟล์เป็นฝั่ง client ที่จะทำการเชื่อมต่อไปยัง server ผ่านทาง socket ในโค้ดจะมีคอมเมนต์อธิบายไล่ตั้งแต่ขั้นตอนที่ 1 ไปถึงขั้นตอนที่ 7 โดยจะทำให้ฝั่ง client ส่งข้อมูลว่า “Hello World” ไปยัง server และให้ server ส่งข้อความที่ได้รับกลับมาที่ client
การรันโค้ดให้รันไฟล์ server ก่อนจน print ว่า “waiting for connection” คือกำลังรอการเชื่อมต่อจาก client แล้วจึงรันไฟล์ฝั่ง client
โปรแกรมฝั่ง server
server.py
import socket
HOST = 'localhost' # IP ของ server
PORT = 5432 # port ที่จะใช้ในการติดต่อ
# จากข้อ 1 : สร้าง socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# จากข้อ 2 : กำหนดข้อมูลพื้นฐานให้กับ socket object
s.bind((HOST, PORT))
# จากข้อ 3 : สั่งให้รอการเชื่อมต่อจาก client
s.listen()
while True:
# รอการเชื่อมต่อจาก client
print("waiting for connection")
# จากข้อ 5 : รับการเชื่อมต่อจาก client
connection, client_address = s.accept()
try:
print("connection from", client_address)
# จากข้อ 6 : รับข้อมูลจาก client
while True:
# กำหนดขนาดข้อมูลที่จะรับใน recv()
data = connection.recv(1024)
print("received:", data)
# ถ้ามีข้อมูลส่งเข้ามาให้ส่งกลับไปหา client
if data:
print("sending data back to the client")
connection.sendall(data)
# ถ้าไม่มีข้อมูลให้จบการรอรับข้อมูล
else:
print("no more data from", client_address)
break
# รับข้อมูลเสร็จแล้วทำการปิดการเชื่อมต่อ
finally:
connection.close()
print("closed connection")
output (ก่อนรัน client)
waiting for connection
output (หลังรัน client)
connection from ('127.0.0.1', 49939)
received: b'Hello World'
sending data back to the client
received: b''
no more data from ('127.0.0.1', 49939)
closed connection
waiting for connection
โปรแกรมฝั่ง client
import socket
HOST = 'localhost'
PORT = 5432
# จากข้อ 1 : สร้าง socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# จากข้อ 4 : client ทำการเชื่อมต่อไปยัง server
s.connect((HOST, PORT))
# ส่งข้อมูลไปหา server
s.sendall(b'Hello World')
# รับข้อมูลที่ส่งมาจาก server
data = s.recv(1024)
print('received:', repr(data))
output
received: b'Hello World'
สำหรับ Socket Programing ถ้าได้ลองใช้ก็น่าจะทำให้การส่งข้อมูลหากันระหว่าง client กับ server เป็นเรื่องง่ายๆ โดยการใช้งานนั้นรายละเอียดอาจจะแตกต่างกันออกไปในแต่ละภาษา แต่ลำดับการทำงานหลักๆนั้นจะคล้ายกัน ยังไงก็ลองก็อปปี้โค้ดตัวอย่างไปรันและทดลองเล่นกันได้นะครับ จะได้เห็นภาพการทำงานของ socket ที่ชัดจนยิ่งขึ้น แต่ถ้าหากว่าใครงงก็ลองเพิ่มการ print แทรกเข้าไประหว่างแต่ละบรรทัดของโค้ดเพื่อดูลำดับการทำงานของโค้ดก็ได้นะครับ ถ้าเข้าได้เข้าใจแล้วจะได้รู้ว่า Socket Programming นั้นง่ายแค่ไหน โปรเจคถัดไปเราอาจจะได้หยิบ socket มาใช้งานกันก็ได้