7 ส.ค. 2020 เวลา 12:23 • วิทยาศาสตร์ & เทคโนโลยี
เขียนโปรแกรมเครือข่ายด้วยซ็อกเก็ต (Socket) ตอนที่ 1 รู้จักกับซ็อกเก็ต
แม้ว่าในปัจจุบันการพัฒนาโปรแกรมบนเครือข่ายเราจะพัฒนาในลักษณะที่เป็นเว็บแอพลิเคชัน หรือใช้มิดเดิลแวร์อย่างจาวาอีอี (Java EE) หรือ ไมโครซอฟท์ดอตเน็ต (Microsoft .Net) เป็นหลัก แต่พื้นฐานของโปรแกรมที่ทำงานบนเครือข่ายจะอยู่บนแนวคิดของซ็อกเก็ต (Socket) ยิ่งไปกว่านั้นแอพพลิเคชันหลัก ๆ บนอินเทอร์เน็ตที่เราใช้กันอยู่ในปัจจุบันนี้เช่นการติดต่อเพื่อขอหน้าเว็บระหว่างเว็บเบราว์เซอร์หรือเว็บเซิร์ฟเวอร์ หรือการรับส่งไฟล์โดยใช้โปรโตคอลเอฟทีพี (FTP) ก็ใช้เพียงแค่แนวคิดของซ็อกเก็ต ในการทำงาน
ดังนั้นการรู้จักและเข้าใจการเขียนโปรแกรมเครือข่ายโดยใช้ซ็อคเก็ต จึงยังจัดว่ามีประโยชน์อยู่ ในบทความตอนแรกนี้ผมจะกล่าวถึงว่า ซ็อกเก็ตคืออะไร และในตอนต่อ ๆ ไป จะแสดงตัวอย่างของการเขียนโปรแกรมในภาษาต่าง ๆ อย่างเช่นภาษาจาวา (Java) ภาษาไพธอน (python) และอาจมีภาษาอื่น ๆ ด้วย ตามความขยันของผม แต่จริง ๆ แล้วถ้าเข้าใจแนวคิดในบทความนี้ผมคิดว่าก็สามารถที่จะนำไปประยุกต์กับภาษาอะไรก็ได้ครับ
6
ซ็อกเก็ตถ้าให้ความหมายในภาษาไทยอย่างง่าย ๆ ก็คือ เต้ารับที่เราสามารถเอาอุปกรณ์มาเสียบลงไปได้ (ฮั่นแน่ อย่าคิดลึกนะ) ตัวอย่างเช่นเต้ารับของปลั๊กไฟ การที่ใช้ชื่อซ็อกเก็ตนี้กับการสื่อสารระหว่างโปรแกรมบนเครือข่ายก็เพื่อแสดงให้เห็นภาพว่าโปรแกรมที่ต้องการคุยกันระหว่างเครื่อข่ายแต่ละตัว จะต้องเตรียมเต้ารับ (Socket) ของตัวเองไว้ เมื่อต้องการจะคุยกันก็เอาสายเคเบิลมาเสียบเข้ากับเต้ารับของทั้งสองฝั่ง ก็จะทำให้โปรแกรมจากทั้งสองฝั่งสามารถส่งข้อความกันได้ผ่านทางสายเคเบิลนี้
3
Photo by Greg Rosenke on Unsplash
ในปัจจุบันระบบปฏิบัติการแทบทุกตัวจะรองรับแนวคิดของการติดต่อสื่อสารผ่านเครือข่ายโดยใช้ซ็อกเก็ต และภาษาเขียนโปรแกรมแทบทุกภาษาก็จะมี ซ็อกเก็ตเอพีไอ (Socket API) ให้นักเขียนโปรแกรมเรียกใช้ ข้อดีของการใช้ซ็อกเก็ตเอพีไอ ก็คือนักเขียนโปรแกรมไม่จำเป็นต้องลงไปรู้รายละเอียดของโปรโตคอลในระดับชั้นทรานส์ปอร์ตอย่างเช่น ทีซีพี (TCP) ) และระดับชั้นเน็ตเวิร์คอย่างเช่นไอพี ( IP)
สิ่งที่ต้องเข้าใจก่อนจะลงมือเขียนโปรแกรมโดยใช้ซ็อกเก็ตเอพีไอก็คือเราจะระบุถึงโปรแกรมที่อยู่กันบนคนละเครื่องในเครือข่ายอินเทอร์เน็ตได้อย่างไร คำตอบก็คือเราจะต้องระบุโดยใช้เลขที่อยู่สองตัวคือเลขที่อยู่ของเครื่องที่โปรแกรมนั้นทำงานอยู่ และเลขที่อยู่ของโปรแกรมนั้น ที่ต้องระบุเลขที่อยู่ของโปรแกรมก็เพราะว่าบนเครื่องคอมพิวเตอร์เครื่องหนึ่งอาจมีโปรแกรมที่ทำงานผ่านเครือข่ายทำงานอยู่พร้อม ๆ กันหลายโปรแกรม ถ้าไม่เข้าใจจะขอยกตัวอย่างว่าถ้าเราต้องการเขียนจดหมายถึงเพื่อนของเราที่อยู่คอนโดมิเนียม เราจะต้องจ่าหน้าซองโดยระบุทีอยู่ของคอนโด และหมายเลขห้องของเพื่อนเรา (คอนโดหนึ่งมีหลายห้อง) ที่อยู่ของคอนโดเปรียบได้กับเลขที่อยู่ของเครื่องคอมพิวเตอร์ ส่วนเลขที่ห้องก็คือที่อยู่ของโปรแกรมนั่นเอง
สำหรับบนอินเทอร์เน็ตเลขที่อยู่ของเครื่องคอมพิวเตอร์เราจะระบุโดยใช้หมายเลขไอพี (IP Address) ซึ่งพวกเราอาจเคยเห็นผ่านตามาบ้างในรูปแบบเช่น 192.168.1.2 อันนี้เป็นหมายเลขไอพีในเวอร์ชัน 4 นะครับ ปัจจุบันในเครือข่ายอินเทอร์เน็ตเราใช้ทั้งเวอร์ชัน 4 และเวอร์ชัน 6 ซึ่งจะเป็นเลขฐานสิบหก (อันนี้ขอละไว้ให้ค้นคว้าเพิ่มเติมเอานะครับว่าเวอร์ชัน 4 กับ 6 ต่างกันยังไง และทำไมเราใช้อยู่สองเวอร์ชัน)
ส่วนหมายเลขที่อยู่ของโปรแกรมเราจะใช้หมายเลขพอร์ต (port number) ครับ ซึ่งหมายเลขพอร์ตนี้ก็คือเลขจำนวนเต็มธรรมดานี่เองครับ โดยจะเป็นเลขจำนวนเต็มที่เริ่มจาก 0 ถึง 65,535 ซึ่งก็เท่ากับจำนวน 65,536 หรือพูดง่าย ๆ ก็คือ ตามทฤษฎีแล้ว คอมพิวเตอร์หนึ่งเครื่องสามารถมีโปรแกรมเครือข่ายทำงานอยู่ได้พร้อมกัน 65,536 โปรแกรม ถ้าจะเทียบกับตัวอย่างคอนโด ก็คือคอนโดมีจำนวนห้อง 65,536 ห้อง
Photo by Hadi Yazdi Aznaveh on Unsplash
ช่วงของตัวเลขที่ได้นี้ก็มาจากจำนวนบิตในฟิลด์ที่ใช้เก็บหมายเลขพอร์ตในโปรโตคอลระดับชั้นทรานส์ปอร์ตอย่าง ทีซีพี (TCP) หรือ ยูดีพี (UDP) ที่มีจำนวน 16 บิตนั่นเองครับ 2 ยกกำลัง 16 มีค่าเท่ากับ 65,536 นั่นเอง รายละเอียดมากกว่านี้ของหมายเลขพอร์ตจะพูดถึงต่อไปครับ เอาเป็นว่าจะขอยกตัวอย่างหมายเลขพอร์ตตัวหนึ่งที่เป็นมาตรฐานสำหรับโปรแกรมเว็บเซิร์ฟเวอร์ก็แล้วกันนะครับนั่นก็คือพอร์ตหมายเลข 80 ดังนั้นสมมติว่าถ้าเว็บเบราว์เซอร์ต้องการติดต่อกับโปรแกรมเว็บเซิร์ฟเวอร์ที่ทำงานอยู่บนเครื่องที่มีหมายเลข IP 161.246.123.123 ก็ต้องระบุทั้งหมายเลขไอพีดังกล่าว และหมายเลขพอร์ตซึ่งคือ 80
ถึงตอนนี้หลายคนอาจบอกว่าไม่เคยเห็นต้องใส่เลขไอพีและเลขพอร์ตเลยเวลาเข้าถึงเว็บไซต์ เหตุผลก็คือในอินเทอร์เน็ตจะใช้ DNS (Doamin Name Server) เป็นกลไกในการแปลง URL ของเว็บไซต์ที่เราป้อนเป็นหมายเลขไอพีของเครื่องเซิร์ฟเวอร์ให้เราครับ ส่วนพอร์ต 80 เป็นพอร์ตมาตรฐาน ซึ่งถ้าเว็บเซิร์ฟเวอร์ใช้พอร์ตนี้อยู่แล้วก็ไม่จำเป็นต้องระบุ
1
สำหรับการใช้งานซ็อกเก็ตเอพีไอนั้นแต่ละโปรแกรมก็ต้องระบุที่อยู่ทั้งสองตัวเพื่อสร้างเต้ารับของตัวเอง ซึ่งในการใช้งานซ็อกเก็ตเอพีไอจะเรียกเลขที่อยู่ทั้งสองว่าที่อยู่ซ็อกเก็ต (Socket Address) หรือจะแปลว่าที่อยู่เต้ารับดี :) พูดง่าย ๆ ก็คือ
Socket Address = IP Address + Port Number นั่นเองครับ
5
โดยในส่วนหัวของแพ็กเก็ตข้อมูลที่มีการรับส่งกันจะมีการระบุที่อยู่ซ็อคเก็ตของทั้งฝั่งรับและฝั่งส่ง เปรียบได้กับเวลาเราจ่าหน้าซองจดหมายเราก็จะระบุทั้งที่อยู่ของผู้รับและผู้ส่ง ที่อยู่ของฝั่งส่งจะทำให้ผู้รับถ้าต้องการตอบกลับจะได้รู้ว่าจะต้องส่งข้อมูลกลับไปที่ใคร
ในส่วนของหมายเลขพอร์ตนั้นโปรแกรมเซิร์ฟเวอร์จะมีหมายเลขพอร์ตที่แน่นอนเพื่อที่ให้โปรแกรมไคลเอนต์ติดต่อเข้ามาได้ ส่วนโปรแกรมไคลเอนต์นั้นระบบปฏิบัติการจะเลือกหมายเลขพอร์ตที่ว่าง ณ ตอนนั้นมาให้ นั่นหมายความว่าโปรแกรมไคลเอนต์โปรแกรมเดียวกัน ในการทำงานแต่ละครั้งอาจมีหมายเลขพอร์ตไม่เหมือนกัน เช่นถ้าเราใช้เว็บเบราว์เซอร์เช่น Chrome ติดต่อเข้าไปยังเว็บเซิร์ฟเวอร์หมายเลขพอร์ตที่เว็บเซิร์ฟเวอร์จะมีค่าเดิมทุกครั้งเช่นหมายเลข 80 แต่โปรแกรม Chrome ในการทำงานครั้งแรกระบบปฏิบัติการอาจให้หมายเลข 1234 หลังจากนั้นถ้าปิดไปแล้วเปิดโปรแกรมขึ้นมาใหม่อาจจะได้หมายเลข 2000 ก็ได้
ดังนั้นในการเขียนโปรแกรมฝั่งเซิร์ฟเวอร์นักเขียนโปรแกรมจะต้องระบุหมายเลขพอร์ตที่แน่นอนให้กับโปรแกรม ในขณะที่โปรแกรมฝั่งไคลเอนต์ไม่จำเป็นต้องระบุ สิ่งที่ควรรู้ก็คือโปรแกรมสองโปรแกรมที่ทำงานบนเครื่องเดียวกันในขณะเดียวกัน และใช้โปรโตคอลในชั้นทรานสปอร์ตตัวเดียวกัน เช่นใช้ ทีซีพี (TCP) เหมือนกัน ไม่สามารถใช้หมายเลขพอร์ตเดียวกันได้ เพราะถ้ายอมให้ซ้ำกันได้จะทำให้ไม่รู้ว่าจะต้องส่งข้อมูลไปยังโปรแกรมปลายทางตัวใด ถ้าไม่เข้าใจให้นึกถึงว่าถ้าในคอนโดมิเนียมแห่งหนึ่งมีห้องสองห้องซึ่งมีหมายเลขห้องเดียวกัน ถ้ามีจดหมายมาถึงคนที่มีหน้าที่ส่งจดหมายก็จะไม่รู้ว่าควรจะส่งจดหมายไปที่ห้องใด
ในการเลือกหมายเลขพอร์ตให้กับโปรแกรมเซิร์ฟเวอร์ นักเขียนโปรแกรมควรจะมีความเข้าใจในเรื่องการจัดการหมายเลขพอร์ต โดยหน่วยงานที่มีหน้าที่ในการจัดการหมายเลขพอร์ตก็คือ Internet Assigned Numbers Authority (IANA) ซึ่งเป็นแผนกหนึ่งของ Internet Corporation for Assigned Names and Numbers (ICANN)
การจัดการหมายเลขพอร์ตจะมีการแบ่งหมายเลขพอร์ตออกเป็นช่วง ช่วงแรกคืออ 0-1,023 จะไม่นำมานำมาใช้กับโปรแกรมเรา และระบบปฎิบัติการหลายตัวก็จะไม่ให้เราลงทะเบียนโปรแกรมเราโดยใช้พอร์ตในช่วงนี้ เพราะหมายเลขพอร์ตในช่วงนี้จะเป็นส่วนที่โปรแกรมเซิร์ฟเวอร์ที่เป็นมาตรฐานใช้ เช่นเว็บเซิร์ฟเวอร์ใช้หมายเลข 80 อีเมลเซิร์ฟเวอร์ใช้พอร์ตหมายเลข 25 เป็นต้น
หมายเลข 1,024-49,151 เป็นช่วงหมายเลขพอร์ตที่ IANA กำหนดให้เป็นพอร์ตจดทะเบียน (registered port) คือถ้าหน่วยงานใดที่ต้องการจะจดทะเบียนหมายเลขพอร์ตให้กับโปรแกรมของตัวเอง IANA ก็สามารถนำหมายเลขพอร์ตในช่วงนี้มาจดทะเบียนให้ได้ โปรแกรมเซิร์ฟเวอร์ที่เราเขียนอาจจะใช้หมายเลขพอร์ตในช่วงนี้ก็ได้ แต่ก็ไม่ได้มีการบังคับหรือควบคุมใด ๆ ถ้าเราอยากเขียนโปรแกรมโดยใช้พอร์ตในช่วงนี้
ส่วนช่วงที่เหลือคือ 49,152 ถึง 65,535 เรียกว่าเป็นไดนามิกพอร์ต (dynamic port) เป็นหมายเลขพอร์ตที่ IANA ไม่รับจดทะเบียน และไม่ได้มีการควบคุมใด ๆ คือตั้งใจให้หมายเลขในช่วงนี้ใช้เป็นหมายเลขพอร์ตชั่วคราว หรือใช้สำหรับโปรแกรมหรือบริการที่ใช้ภายในเครื่อง หรือเป็นช่วงหมายเลขพอร์ตที่สุ่มให้โปรแกรมฝั่งไคลเอนต์ได้ใช้
ข้อมูลเพิ่มเติมของพอร์ตต่าง ๆ ที่มีการใช้งานจริงสามารถดูเพิ่มเติมได้จากลิงก์นี้ครับ http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
ก็หวังว่าจะเข้าใจเรื่องหมายเลขพอร์ตมากขึ้นนะครับ แต่ไม่ต้องซีเรียสมาก เอาเป็นว่าโปรแกรมเซิร์ฟเวอร์ที่เราจะเขียนขึ้นต่อไปจะใช้พอร์ตตั้งแต่หมายเลข 1,024 ขึ้นไป ที่ว่างในเครื่องเราแล้วกันนะครับ โดยผมจะเลือกหมายเลขพอร์ตในช่วงของพอร์ตจดทะเบียน (1,024 - 49,151) เป็นหลักนะครับ พบกันต่อไปบทความหน้าครับ
อ่านบทความเรื่องเกี่ยวกับการเขียนโปรแกรมและเรื่องที่เกี่ยวข้องกับวิชาด้านวิทยาการคอมพิวเตอร์ที่ผมสอนได้ที่

ดูเพิ่มเติมในซีรีส์

โฆษณา