บันทึกการเขียนโปรแกรมส่งไฟล์ด้วย Golang
สร้างโปรแกรมส่งไฟล์แบบง่าย ๆ ด้วย Golang ใช้งานบน CLI แต่สามารถ embed กับโปรแกรมอื่นได้ด้วย MessagePack
ปัญหา/ที่มา
Windows สามารถส่งไฟล์ได้ในตัวเอง, Linux ก็สามารถส่งไฟล์หากันได้ (สามารถส่งข้ามไป Windows ได้ด้วย Samba (SMB/CIFS protocol)), MacOS ก็มี Airdrop ส่งข้ามอุปกรณ์ได้สบาย ๆ
ปัญหาคือ ความหลากหลายนี้เป็นที่มาของปัญหาเมื่อต้องการส่งไฟล์เมื่อทีมใช้ระบบปฏิบัติการคนละอย่างกัน
ทำไมเลือก Go
จริง ๆ ต้องการสร้างเป็น GUI Application ไม่ใช่ CLI แต่งานนี้มี performance เป็นเดิมพัน รวมถึงต้องเขียนระบบที่เข้าถึง interface ของ network ด้วย ครั้นจะเอา Electron, Nodejs ไปเขียนเพียว ๆ ก็น่าจะยาก (มากกว่า Go)
Go เป็นภาษาที่ compile เป็น native ทำให้มีประสิทธิภาพที่ดีกว่า และเก่งมากเรื่อง networking เพราะถูกสร้างมาเพื่อด้านนี้เฉพาะ
ผมจึงเลือกที่จะสร้าง Backend ขึ้นมาด้วย Go แล้วค่อยนำไป embed ใน GUI Application ซึ่งทำให้การเขียนส่วนที่ต้องทำงานเกี่ยวกับระบบนั้นง่ายและมีประสิทธิภาพมาก ⚡
ผมเลือกใช้ MessagePack สำหรับการ serialize ข้อมูล เพื่อให้ข้อมูลมีความกระทัดรัด ใช้เมื่อต้องการ embed โปรแกรม ดูรายละเอียดได้ที่เว็บไซต์หลัก
โครงสร้างโปรแกรม 🔧
มีองค์ประกอบสองส่วนสำคัญคือ Relay และ CMD
Relay เป็นเซิร์ฟเวอร์ ที่รอรับการส่งไฟล์ สามารถปฏิเสธไฟล์หรือยอมรับได้ เป็นเซอร์วิสที่ต้องเปิดไว้ตลอด เพื่อให้สามารถถูกพบเจอได้ใน Network
CMD หรือ Command เป็นส่วนที่ใช้สำหรับควบคุม ออกคำสั่ง เช่นการส่งไฟล์ไปยัง address หรือ scan หาอุปกรณ์ใน network ที่มี Relay เปิดใช้งานอยู่
การพัฒนา
ดังตัวอย่างเป็นการใช้งาน Relay และ CMD (โค้ดเนม Fire 🔥) ซึ่ง CMD ได้แสดงให้เห็น command ที่สำคัญสองอย่างคือ send และ scan
Scan
เป็นคำสั่งที่ใช้สำหรับสแกนหาอุปกรณ์ที่เปิดใช้งาน relay อยู่ใน network
การพัฒนาคำสั่งนี้น่าจะเป็นคำสั่งที่ซับซ้อนที่สุดในโปรแกรมนี้ เพราะต้องอาศัยการคำนวณ Subnet mask เพื่อหา range ของ host ที่อยู่ใน network เดียวกันแล้ว dial เพื่อทดสอบว่ามีเซอร์วิส relay เปิดอยู่หรือไม่
Send
ใช้สำหรับส่งไฟล์ข้อมูลไปยังปลายทาง ซึ่งได้รับมาจากคำสั่ง scan
การพัฒนาก็ง่าย ๆ เป็นเพียงการส่ง body data ไปยัง relay ด้วยโปรโตคอล HTTP (จริง ๆ อยากจะทำ protocol ของตัวเองขึ้นมา แต่ว่ามันคง overkill ไปสำหรับโปรเจคง่าย ๆ แบบนี้)
ทั้ง Relay และ CMD สามารถใส่ flag “ — msgpack” ได้ เพื่อ output เป็น messagepack แทน
สรุป 📃
ในตอนนี้เราได้พัฒนาจนเสร็จแล้ว เป็นครั้งแรกที่ได้เขียนโปรแกรม CLI แบบนี้ ได้เรียนรู้อะไรเยอะมาก ๆ 🚀
ต่อไปเป็นการพัฒนาส่วน GUI โดยใช้โปรแกรมนี้มา embed สำหรับ functionality
จนกว่าจะเจอกันใหม่ สวัสดีครับผม