TCP กับ UDP ต่างกันอย่างไร

     จินตนาการง่ายๆ แบบนี้นะ
TCP เหมือนโทรศัพท์บ้าน ที่ว่า เมื่อโทรไปแล้ว ต้องมีคนรับ การสื่อสารถึงจะสมบูรณ์
UDP เหมือนวิทยุ เปิดแล้ว จะมีคนฟังหรือไม่มีคนฟังก็ถือว่า การสื่อสารสมบูรณ์แล้ว   
     TCP และ UDP เป็นโพรโตคอลในทรานสปอร์ตเลเยอร์ของตระกูล TCP/IP ที่ให้บริการแก่แอพพลิเคชันทั่วไป และโพรโตคอลในแอพพลิเคชันเลเยอร์ (รวมไปถึง HTTP, SMTP, SNMP, FTP, และ Telnet) ซึ่งทั้งสองโพรโตคอลนี้ จะใช้บริการของ IP ในการส่งแพ็กเกตไปยังระบบเครือข่ายปลายทาง โดยการส่งข้อมูลของ TCP จะเป็นแบบ connection-oriented และรับรองความถูกต้องของข้อมูล (reliable) ในขณะที่ UDP จะเป็นแบบ connectionless และไม่รับรองความถูกต้องของข้อมูล (unreliable) โดยทั้งสองโพรโตคอลจะส่งข้อมูลแบบ byte-stream ซึ่งเราจะอธิบายถึงความหมายของคำเหล่านี้ในภายหลัง
     โพรโตคอลแบบ connection-oriented จะสร้างลิงก์จากต้นทางไปถึงปลายทางก่อนที่จะส่งข้อมูล การทำงานของ ATM และเฟรมรีเลย์ก็เป็นแบบ connection-oriented เช่นกัน แต่ว่าโพรโตคอลทั้งสองนี้ทำงานในดาต้าลิงก์เลเยอร์ ไม่ใช่ในทรานสปอร์ตเลเยอร์ การติดต่อผ่านทางโทรศัพท์ก็นับเป็นการทำงานแบบ connection-oriented ด้วยเช่นกัน
     โพรโตคอลแบบที่รับรองความถูกต้องของข้อมูล (reliable) จะช่วยป้องกันความผิดพลาดที่เกิดขึ้นในระหว่างการส่งข้อมูล เมื่อคุณได้รับแพ็กเกตที่ปลายทางแล้ว คุณสามารถเปรียบเทียบข้อมูล checksum ที่อยู่ในแพ็กเกต กับ checksum ที่ได้จากการคำนวณของอัลกอริทึม เพื่อตรวจสอบว่าข้อมูลผิดพลาดหรือไม่ ถ้าใช่ คุณก็ต้องส่งแพ็กเกตนั้นซ้ำอีกครั้ง ดังนั้นโพรโตคอลชนิดนี้จึงต้องมีวิธีการที่ยอมให้เครื่องที่ปลายทางส่งสัญญาณมายังต้นทาง ในกรณีที่ข้อมูลเกิดความผิดพลาดขึ้น เมื่อข้อมูลถูกแบ่งเป็นหลายแพ็กเกตแล้ว อาจเดินทางมาถึงปลายทางโดยไม่เรียงตามลำดับของแพ็กเกตก็เป็นได้ ดังนั้นตัวโพรโตคอลจึงต้องมีความสามารถในการตรวจเช็กลำดับของแพ็กเกต, จัดเก็บแพ็กเกตไว้ในบัฟเฟอร์, และส่งแพ็กเกตที่เรียงลำดับเรียบร้อยแล้วไปยังแอพพลิเคชันเลเยอร์ต่อไป อีกทั้งต้องตรวจสอบได้ว่า เมื่อใดมีการส่งข้อมูลซ้ำ และทิ้งข้อมูลซ้ำนั้นไป ในกรณีที่เกิดการผิดพลาดในการสื่อสารโพรโตคอลอาจต้องส่งข้อมูลเดิมนั้นซ้ำอีกครั้ง หรืออาจต้องสร้างลิงก์เชื่อมต่อระหว่างต้นทางกับปลายทางขึ้นมาใหม่ ดังนั้นจึงจำเป็นต้องมีระบบการนับเวลา (timer) เพื่อใช้ในการรอสัญญาณตอบรับ (acknowledgement) จากเครื่องที่อยู่ฟากตรงข้าม
     สำหรับโพรโตคอลแบบ byte-stream จะไม่ทำงานกับหน่วยของข้อมูลแบบอื่นนอกเหนือจากหน่วย "ไบต์" ซึ่ง TCP จะไม่สามารถประกอบไบต์เป็นโครงสร้างข้อมูลภายในแพ็กเกตได้ รวมถึงไม่สามารถทำงานในระดับบิตได้เช่นกัน โดยตัว TCP จะทำงานได้แต่เพียงการส่งตัวอักษรขนาด 1 ไบต์ ในลักษณะของสายอักขระแบบไม่มีโครงสร้างไปยังปลายทาง
โพรโตคอลแบบ connectionless จะไม่สร้างลิงก์ผ่านระบบเครือข่ายก่อนที่จะส่งข้อมูล แต่โหนดระหว่างทางแต่ละตัว จะค้นหาเส้นทางในการส่งแพ็กเกต (หรืออาจเรียกว่า ดาต้าแกรม สำหรับในกรณีเช่นนี้) อย่างเป็นอิสระต่อกัน เมื่อปราศจากลิงก์ระหว่างต้นทางกับปลายทาง โพรโตคอลชนิดนี้ อย่าง UDP จะไม่รับรองความถูกต้องของข้อมูล (unreliable) เมื่อแพ็กเกตของ UDP ถูกส่งผ่านไปยังระบบเครือข่าย ผู้ส่งจะไม่มีทางทราบว่าแพ็กเกตไปถึงปลายทาง นอกเสียจากว่าโพรเซสในแอพพลิเคชันเลเยอร์ส่งสัญญาณตอบรับกลับมา การตรวจสอบว่ามีการส่งข้อมูลซ้ำ หรือแพ็กเกตไม่มาตามลำดับ ก็ไม่สามารถทำได้เช่นกัน แม้ว่าในระบบเครือข่ายยุคใหม่นี้ การสื่อสารผ่าน UDP จะมีแนวโน้มในการรับส่งข้อมูลผิดพลาดน้อยลงมาก แต่คุณก็คงจะเรียกการทำงานเช่นนี้ว่า reliable ไม่ได้เช่นกัน
     ส่วนของไอพีแพ็กเกตที่อยู่ถัดจากส่วนของไอพีเฮดเดอร์ โดย 16 บิตแรกจะแสดงหมายเลขพอร์ตต้นทาง ส่วน 16 บิตหลังจะเป็นหมายเลขพอร์ตปลายทาง หมายเลขพอร์ตจะช่วยให้เครื่องไอพีโฮสต์สามารถรับส่งข้อมูลหลากหลายชนิด ไปยังไอพีแอดเดรสหนึ่งในเวลาเดียวกันได้ หมายเลขไอพีแอดเดรสขนาด 32 บิต และหมายเลขพอร์ตขนาด 16 บิต จะรวมกันเป็นระบบซ็อกเกตที่ใช้กันอยู่ทั่วไปในระบบปฏิบัติการยุคใหม่ ซึ่งซ็อกเกตต้นทาง และซ็อกเกตปลายทาง จะรวมกันเป็นหนึ่งคอนเน็กชันของ TCP โดยจะมีพอร์ตทั้งหมดอยู่ 216 หรือ 65,536 พอร์ต ซึ่งพอร์ต 1024 พอร์ตแรก จะเป็นพอร์ตที่รู้จักกันดีและถูกใช้กันอยู่ทั่วไป (well-known port) ทั้งหมดนี้ถูกตั้งค่าไว้ตั้งแต่แรก สำหรับนำมาใช้งานในโพรโตคอลบนแอพพลิเคชันเลเยอร์ ยกตัวอย่างเช่น HTTP จะใช้พอร์ต 80 ในขณะที่ POP3 จะใช้พอร์ต 110 ส่วนแอพพลิเคชันอื่นก็สามารถใช้หมายเลขพอร์ตที่สูงกว่านี้ได้ ส่วนหมายเลข sequence number และ acknowledgement number นั้นเป็นกุญแจสำคัญสำหรับการตรวจสอบความถูกต้องของข้อมูล เมื่อสร้างคอนเน็กชันของ TCP แล้ว ผู้ส่งจะส่งหมายเลข sequence number พร้อมกับแพ็กเกตไปยังผู้รับ ผู้รับจะบวก 1 เข้ากับหมายเลข sequence number แล้วเก็บหมายเลขนั้นไว้ใน acknowledgement number ของแพ็กเกตตอบรับ เพื่อบอกถึงหมายเลขของไบต์ถัดไปที่ควรถูกส่งมา จากนั้นก็จะส่งแพ็กเกตตอบรับกลับไปยังผู้ส่ง เมื่อการสื่อสารข้อมูลเริ่มต้นขึ้น หมายเลข sequence และ acknowledgement จะถูกใช้ตรวจสอบว่าข้อมูลไบต์ใดที่ถูกส่งไปแล้ว และข้อมูลใดที่ถูกตอบกลับมาแล้ว เนื่องจากว่าหมายเลขทั้งสองนี้แต่ละหมายเลขจะใช้พื้นที่ 32 บิต ทำให้มีค่าได้ทั้งหมด 232 ค่า โดยแต่ละหมายเลขจะมีค่าได้ตั้งแต่ 0 ไปจนถึง 4,294,967,295 และวกกลับมาที่ 0 เมื่อเกินค่าสูงสุดแล้ว ส่วนฟิลด์ของ HLEN ขนาด 4 บิตจะบอกถึงจำนวนของเวิร์ดขนาด 32 บิตที่ส่วนเฮดเดอร์มีอยู่ ข้อมูลส่วนนี้จำเป็นมาก เพราะว่าเฮดเดอร์มีฟิลด์บางฟิลด์ที่เป็นออปชัน คืออาจมีหรือไม่มีก็ได้ ซึ่งฟิลด์ HLEN นี้ก็จะบอกถึงตำแหน่งในแพ็กเกตว่าเฮดเดอร์จบที่ใด และข้อมูลจริงเริ่มต้นตรงไหน
     ผู้ออกแบบ TCP ไม่ได้ใช้พื้นที่ 6 บิตถัดไป เนื่องจากต้องการเก็บไว้ใช้สำหรับการพัฒนาในอนาคต ซึ่งตั้งแต่เกิด RFC793 (Transmission Control Protocol) จนถึง1981 ก็ไม่มีใครจำเป็นจะต้องใช้บิตสำรองเหล่านี้เลย Jon Postel และกลุ่มผู้ร่วมพัฒนาเหล่านั้นคงจะระวังกันเกินกว่าเหตุไปหน่อย
สำหรับอีก 6 บิตถัดไปนั้น แต่ละบิตจัดเป็นแฟล็ก เมื่อแฟล็ก URG (urgent) มีค่า 1 จะบอกว่าข้อมูลในฟิลด์ urgent pointer ในเฮดเดอร์นั้นเป็นข้อมูลสำคัญ ส่วนแฟล็ก ACK (acknowledgement) ใช้บอกว่าหมายเลข acknowledgement นั้นสำคัญ (นั่นคือเป็นแพ็กเกตตอบรับนั่นเอง) แฟล็ก SYN (synchronization) บอกว่าหมายเลข sequence เป็นข้อมูลสำคัญ (นั่นหมายถึง เลข acknowledgement ไม่สำคัญไปด้วย เพราะว่าแพ็กเกตนั้นจะไม่ใช่แพ็กเกตตอบรับ) แฟล็ก PSH (push) ช่วยป้องกันข้อมูลจากการที่ต้องรอถูกส่งและรอรับการจัดการโดยโพรเซสผู้รับ แฟล็ก RST (reset) ใช้ปิดคอนเน็กชันของการสื่อสาร ส่วนแฟล็ก FIN (finish) ใช้บอกว่าผู้ส่งหมดข้อมูลที่ต้องการส่งแล้ว
     ฟิลด์ window ขนาด 16 บิตนั้นจะบอกถึงขนาดของ sliding window ซึ่งใช้บอกผู้ส่งว่าตัวเองพร้อมจะรับข้อมูลจำนวนกี่ไบต์ โพรโตคอล TCP จะควบคุมการไหลของข้อมูลและภาวะการสื่อสารติดขัด โดยปรับที่ขนาดของ window นี่เอง ซึ่งถ้าค่านี้เท่ากับ 0 จะเป็นการบอกกับผู้ส่งว่าผู้รับไม่สามารถรับข้อมูลเพิ่มได้อีกในขณะนี้ และจะส่งแพ็กเกตตอบรับพร้อมค่า window ใหม่เมื่อสามารถรับข้อมูลได้อีก โดย window ที่มีขนาดใหญ่จะทำให้ส่งข้อมูลออกไป แม้ในขณะที่ยังไม่ได้รับสัญญาณตอบรับ ได้มากที่สุดถึง 65,536 ไบต์ ณ ช่วงเวลาใดเวลาหนึ่ง แต่ภาวะการสื่อสารติดขัด (congestion) ที่เกิดขึ้นเมื่อไทเมอร์ของ retransmission หมดลงก่อนที่จะได้รับสัญญาณตอบรับ จะทำให้ขนาดของ window ลดลงไปครึ่งหนึ่ง ส่งผลให้อัตราเร็วในการสื่อสารลดลงไปอย่างมาก
ฟิลด์ checksum ขนาด 16 บิต จะป้องกันความปลอดภัยของข้อมูลในแพ็กเกต รวมไปถึงฟิลด์บางฟิลด์ภายในเฮดเดอร์ ผู้ส่งจะคำนวณค่า checksum และใส่ค่าที่คำนวณได้ไว้ในฟิลด์นี้ จากนั้นผู้รับจะหาค่า checksum นี้ใหม่ โดยคำนวณจากแพ็กเกตที่ได้รับ จากนั้นนำค่าที่ได้ไปเปรียบเทียบกับค่าในฟิลด์นี้ ถ้าเท่ากัน ข้อมูลก็น่าจะปลอดภัย และมีความถูกต้อง
     ค่า urgent pointer ขนาด 16 บิต จะชี้ไปที่ไบต์สุดท้ายของข้อมูลเร่งด่วนในกรณีที่แฟล็ก urgent มีค่าเป็นหนึ่ง ส่วนฟิลด์ options นั้นอาจมีจำนวนของเวิร์ด (32 บิต) ได้ตั้งแต่ 0 เวิร์ดหรือมากกว่านั้น เพื่อใช้เพิ่มความสามารถของโพรโตคอล TCP โดยค่าของ options ที่นิยมใช้กันมากที่สุดนั้นจะรองรับขนาดของ window ได้มากกว่า 65,536 ไบต์ ช่วยให้ลดเวลาในการรอสัญญาณตอบรับ โดยเฉพาะอย่างยิ่งในกรณีของการรับส่งข้อมูลด้วยความเร็วสูง
การทำงานของ TCP นั้นต้องใช้ไทเมอร์จำนวนมาก ไทเมอร์สำหรับการส่งข้อมูลเดิมซ้ำ จะเริ่มเมื่อข้อมูลถูกส่งไป และจะหยุดเมื่อได้รับสัญญาณตอบรับจากผู้รับ ถ้าเวลาหมดก่อนที่จะได้รับสัญญาณนั้น ข้อมูลเดิมจะถูกส่งซ้ำอีกครั้ง การตั้งเวลาของไทเมอร์ให้พอเหมาะนับเป็นปัญหายุ่งยากอย่างหนึ่ง ถ้านานไป โพรโตคอลก็จะเสียเวลาในการรอ แม้ว่าในขณะนั้นข้อมูลจะสูญหายไประหว่างทางแล้วก็ตาม แต่ถ้าเร็วไป ข้อมูลเดิมก็จะถูกส่งซ้ำไปเป็นจำนวนมาก โดยเฉพาะในกรณีที่เกิดความล่าช้าในการรับส่งสัญญาณตอบรับ ซึ่งในปัจจุบัน ค่าไทเมอร์นี้จะถูกตั้งโดยดูจากสถานะ และสภาพแวดล้อมของระบบเครือข่าย
ไทเมอร์ persistence ถูกใช้เพื่อป้องกันไม่ให้เกิดภาวะ deadlock ขึ้น ถ้าเน็ตเวิร์กได้รับแพ็กเกตตอบรับที่มี window ขนาด 0 และจากนั้นไม่ได้รับแพ็กเกตตอบรับที่จะใช้ในการเริ่มต้นการสื่อสารใหม่ ไทเมอร์นี้ก็จะหมดเวลาและส่งสัญญาณตรวจเช็กไป ซึ่งค่าที่ได้รับกลับมาจะเป็นขนาดของ window (ซึ่งอาจจะยังเป็น 0 อยู่ โดยในกรณีนี้ ไทเมอร์จะทำงานเหมือนเดิมใหม่อีกครั้ง)
ไทเมอร์ keepalive จะใช้เช็กว่า ยังมีโพรเซสทำงานอยู่ที่อีกฟากหนึ่งของคอนเน็กชันหรือไม่ หลังจากไม่มีการทำงานได้ระยะหนึ่ง ตัวไทเมอร์นี้จะปิดคอนเน็กชันลงถ้าไม่มีสัญญาณตอบรับกลับมา
ในการปิดคอนเน็กชันนั้น ไทเมอร์ที่ใช้ปิดคอนเน็กชันจะตั้งเวลาให้มีค่าเป็นสองเท่าของค่าอายุของแพ็กเกตที่มากที่สุด (maximum packet lifetime) เพื่อให้แน่ใจว่า ไม่มีข้อมูลสื่อสารค้างอยู่ในคอนเน็กชันนั้นก่อนที่ตัวเองจะถูกปิด
     ไม่ว่ากระบวนการการรับส่งข้อมูลจะถูกสร้างให้มีประสิทธิภาพเพียงใด จำนวนแพ็กเกตที่สูญหายไปแม้เพียงเล็กน้อย ก็สามารถส่งผลกระทบรุนแรงต่อทรูพุตของคอนเน็กชันบน TCP เนื่องจากโพรโตคอลจะทราบว่าแพ็กเกตที่หายไปหรือไม่ ก็ต่อเมื่อหมดเวลาของไทเมอร์แล้วเท่านั้น และโพรเซสผู้รับจำเป็นต้องส่งข้อมูลตามลำดับ การส่งข้อมูลเดิมซ้ำในกรณีที่ข้อมูลสูญหายจะทำให้การสื่อสารข้อมูลหยุดชะงักจนกว่าจะได้รับข้อมูลที่หายไปนั้น การส่งข้อมูลซ้ำเช่นนี้ส่งผลให้ลิงก์ของ TCP มีประสิทธิภาพขึ้นๆ ลงๆ ในบางครั้ง
     ถ้านำโครงสร้างของแพ็กเกต UDP มาเปรียบเทียบกับแพ็กเกตของ TCP แล้ว จะเห็นได้ชัดว่า UDP ขาดกลไกอันซับซ้อนในการควบคุมและรับรองความถูกต้องของข้อมูลเหมือนดังที่มีอยู่ใน TCP หมายเลขพอร์ตต้นทาง และปลายทางของ UDP ยินยอมให้มีการทำงานกับแอพพลิเคชันหลายตัวในเครื่องเดียวกันได้ เหมือนกับใน TCP ส่วนค่าในฟิลด์ UDP length จะเท่ากับความยาวของเฮดเดอร์ขนาดสองไบต์ รวมกับความยาวของข้อมูลจริง โดยค่าในฟิลด์ checksum จะช่วยตรวจสอบความถูกต้องและปลอดภัยของข้อมูล (ในปัจจุบันนี้ แอพพลิเคชันจำนวนมากที่ใช้ UDP เช่น โปรแกรมรับส่งสัญญาณเสียง จะไม่ใช้ประโยชน์จากความสามารถนี้ และจะไม่ส่งข้อมูลที่สูญหายหรือผิดพลาดไปซ้ำอีกครั้ง แม้ว่าจะทราบถึงความผิดพลาดนั้นก็ตาม)
     TCP นับเป็นโพรโตคอลสำหรับการรับส่งข้อมูลที่ให้ความสำคัญกับความถูกต้องของข้อมูลมากกว่าประสิทธิภาพ ในขณะที่ UDP เป็นตัวเลือกที่ดีที่สุดในกรณีที่ประสิทธิภาพมีความสำคัญกว่า ดังเช่นในแอพพลิเคชันทางด้านมัลติมีเดีย UDP ยังนับเป็นตัวเลือกที่ดีสำหรับการสื่อสารข้อมูลที่ใช้ระยะเวลาที่สั้นมากจนเวลาที่เสียไปในการสร้างลิงก์นับเป็นส่วนใหญ่ของการสื่อสารทั้งหมด ยกตัวอย่างเช่น การแลกเปลี่ยนข้อมูลของ DNS สำหรับการตัดสินใจใช้ UDP ใน SNMP นั้น
ส่วนหนึ่งมาจากความเชื่อของผู้ออกแบบว่า ด้วยโอเวอร์เฮดของ UDP ที่น้อยกว่า TCP น่าจะทำให้ UDP มีโอกาสที่ดีกว่าในการรับส่งข้อมูลด้านการจัดการในขณะที่การสื่อสารบนเครือข่ายกำลังติดขัด เมื่อพิจารณาถึงฟังก์ชันการทำงานของ TCP ที่มีเป็นจำนวนมาก ในบางครั้งก็ก่อให้เกิดผลลัพธ์ที่คาดเดาไม่ได้ แต่ถ้ากล่าวถึงคอนเน็กชันแบบ end-to-end ที่รับรองความถูกต้องของข้อมูลจาก TCP นั้น ก็เชื่อว่าน่าจะสามารถทำงานกับแอพพลิเคชันระบบเครือข่ายได้เกือบทั้งหมดในอนาคตอันใกล้นี้