ขนาดแพ็คเก็ตสูงสุดสำหรับการเชื่อมต่อ TCP


197

ขนาดแพ็คเก็ตสูงสุดสำหรับการเชื่อมต่อ TCP คืออะไรหรือฉันจะได้รับขนาดแพ็คเก็ตสูงสุดได้อย่างไร


24
TCP เป็นแบบสตรีม มีเหตุผลเฉพาะที่คุณกังวลเกี่ยวกับแพ็คเก็ตของแต่ละคนหรือ
— Matti Virkkunen

27
เนื่องจากเลเยอร์ด้านล่างเป็นแพ็คเก็ตที่ใช้ ... การใช้งานทั่วไป -> เลเยอร์ 1 - Ethernet PHY, เลเยอร์ 2 - อีเทอร์เน็ต MAC (ข้อกำหนดแพ็คเก็ต MAC, เลเยอร์ 3 - โพรโทคอลอินเทอร์เน็ต (คำจำกัดความแพ็คเก็ต IP), เลเยอร์ 4 - TCP ) - ใช้บริการแบบแพ็คเก็ตด้านล่าง

2
ไม่มีสิ่งเช่น 'แพ็คเก็ต TCP' มีเซ็กเมนต์ TCP ซึ่งมีความยาวอธิบายโดยคำศัพท์ 32 บิตและมีอยู่ในหรือภายในแพ็กเก็ตIPซึ่งมีความยาวอธิบายไว้ใน 16 บิต นอกจากนี้ยังมีเฟรม Ethernet ซึ่งมีสิ่งเหล่านี้ทั้งหมด คุณกำลังถามสิ่งใดจากสิ่งเหล่านี้ ไม่ว่าในกรณีใดถ้าคุณใช้ TCP คุณไม่ต้องกังวลกับสิ่งใด ๆ ก็ตาม: TCP และ IP ดูแลทุกอย่างให้คุณ
— มาร์ควิสแห่ง Lorne

คำตอบ:


178

ข้อ จำกัด ที่แน่นอนของขนาดแพ็คเก็ต TCP คือ 64K (65535 bytes) แต่ในทางปฏิบัตินี่เป็นขนาดที่ใหญ่กว่าขนาดของแพ็คเก็ตใด ๆ ที่คุณเห็นเพราะชั้นล่าง (เช่นอีเทอร์เน็ต) มีขนาดแพ็คเก็ตที่ต่ำกว่า

MTU (Maximum Transmission Unit) สำหรับอีเธอร์เน็ตเช่น 1500 ไบต์ เครือข่ายบางประเภท (เช่นโทเค็นริง) มี MTU ที่ใหญ่กว่าและบางประเภทมี MTU ที่เล็กกว่า แต่ค่าจะได้รับการแก้ไขสำหรับแต่ละเทคโนโลยีทางกายภาพ


15
"แต่ค่าเหล่านั้นได้รับการแก้ไขสำหรับแต่ละเทคโนโลยีทางกายภาพ" - นี่ไม่เป็นความจริง อีเธอร์เน็ตเคยมี MTU สูงสุด 1500 แต่คุณสามารถใช้ MTU ที่ต่ำกว่าได้ ด้วยการถือกำเนิดของจัมโบ้เฟรมไม่มีค่าสูงสุดที่ระบุจริงและค่าสูงสุดจะแตกต่างกันไปตามฮาร์ดแวร์และไดรเวอร์
— WhirlWind

4
@Whirl: จริงพวกเขาสามารถกำหนดค่าได้ แต่โดยทั่วไปแล้วพวกเขาไม่ได้; "configurable" เป็นแบบอัตนัยเพราะจะต้องเจาะเข้าไปในเคอร์เนลเพื่อทำเช่นนั้น ไม่ใช่สิ่งที่คนจรจัดสามารถทำได้ในระดับแอปพลิเคชันซึ่งเป็นที่ที่ OP ดูเหมือนว่าจะเป็น
— อีเธอร์

3
@HiroProtagonist: สูงสุดคือ 1500 ดังนั้นการมี 600 จึงไม่น่าแปลกใจ
— Nicolas Raoul

30
ทำไมถึงมีข้อ จำกัด 64K (65535 bytes) เนื่องจากขนาดของหน้าต่างในส่วนหัวของ TCP เป็นเพียง 16 บิต ฉันแค่อยากจะพูดถึงสามารถช่วยใครซักคนในบางครั้ง ..... คำตอบที่ดี btw @Ether!
— Cacho Santa

2
นอกจากนี้ยังเป็นไปได้ที่จะเพิ่มขึ้นโดยใช้การปรับขนาดหน้าต่าง ในกรณีนั้นค่าสูงสุดคือ 1 GiB
— Martin Melka

86

นี่เป็นคำถามที่ยอดเยี่ยมและฉันใช้งานจริงมาก มีคำตอบ "ถูกต้องทางเทคนิค" มากมายเช่น 65k และ 1500 ฉันได้ทำการเขียนอินเตอร์เฟซเครือข่ายจำนวนมากและการใช้ 65k นั้นโง่และ 1500 ก็สามารถทำให้คุณประสบปัญหาใหญ่ได้ งานของฉันทำงานบนฮาร์ดแวร์ / แพลตฟอร์ม / เราเตอร์ที่แตกต่างกันมากมายและตามจริงแล้วที่ที่ฉันเริ่มต้นคือ 1,400 ไบต์ หากคุณต้องการมากกว่า 1,400 คุณสามารถเริ่มที่จะเพิ่มขึ้นคุณอาจจะไปที่ 1,450 และบางครั้งถึง 1480'ish? หากคุณต้องการมากกว่านั้นแน่นอนคุณต้องแบ่งเป็น 2 แพ็คเก็ตซึ่งมีหลายวิธีที่ชัดเจนในการทำ ..

ปัญหาคือคุณกำลังพูดถึงการสร้างแพ็กเก็ตข้อมูลและเขียนมันออกมาทาง TCP แต่แน่นอนว่ามีข้อมูลส่วนหัวติดอยู่เรื่อย ๆ ดังนั้นคุณมี "สัมภาระ" ที่ทำให้คุณเหลือ 1500 หรือมากกว่านั้น .. และยังเป็น ฮาร์ดแวร์จำนวนมากมีขีด จำกัด ต่ำกว่า

หากคุณ "ผลักดัน" คุณจะได้รับสิ่งแปลก ๆ เกิดขึ้น ข้อมูลที่ถูกตัดทอนหรือลดลงอย่างเห็นได้ชัดที่ฉันไม่ค่อยเห็น ข้อมูลที่เสียหายยังไม่ค่อยมี แต่จะเกิดขึ้นอย่างแน่นอน


เหตุใด GET จึงร้องขอโดยเฉลี่ยประมาณ 600 ไบต์

10
คุณหมายถึง 64K ไม่ใช่ 65K ฉันไม่รู้ว่าคุณหมายถึงอะไร 'สถานที่ที่ฉันเริ่มคือ 1,400 ไบต์' คุณไม่ต้องกังวลกับขนาดแพ็กเก็ตใน TCP API ดูแลการกำหนดและการสังเกตเส้นทาง MTU ไม่มีเหตุผลใดที่คุณไม่สามารถเขียน 2G ในหนึ่งเดียวsend()หากสะดวก
— มาร์ควิสแห่ง Lorne

19
คุณควรจะเป็น1480'ish 1460ส่วนหัวของ IP และส่วนหัวของ TCP ใช้เวลาถึง 20 ไบต์แต่ละอย่างน้อย (ยกเว้นสาขาหัวตัวถูกนำมาใช้) และทำให้สูงสุดของ (กรอบไม่ใช่จัมโบ้) 1500 - 20 -20 = 1460อีเธอร์เน็ต
— Eugene Beresovsky

2
ฉันได้เห็นผ่าน wireshark ว่าเซิร์ฟเวอร์ส่งแพ็กเก็ตขนาดใหญ่ (มากกว่า 1,400 ไบต์) และลูกค้าได้รับมันถอดชิ้นส่วนเป็นแพ็คเก็ตไม่กี่แห่งที่สูงสุด 1,400 ไบต์ ใครเป็นผู้รับผิดชอบในการถอดแยกแพ็คเก็ต @Nektario ... ?
— inbaly

2
@EugeneBeresovsky ได้ดีกับส่วนหัวที่เป็นทางเลือกนั่นคือ + ไบต์สูงสุด 40 ขึ้นไป แต่มันเป็นตัวแปรดังนั้น 1420 จึงดูเหมือนว่าจะมีข้อ จำกัด ด้วยคำแนะนำของ 1,400 คุณจะได้รับการขยายเล็กน้อย ฉันจะไปกับ 1408 เพราะมันหารด้วย 128
— Garet Claborn

22

ที่ระดับแอปพลิเคชันแอปพลิเคชันใช้ TCP เป็นโปรโตคอลที่มุ่งเน้นกระแส TCP มีเซ็กเมนต์และสรุปรายละเอียดของการทำงานกับแพ็กเก็ต IP ที่ไม่น่าเชื่อถือ

TCP จัดการกับเซกเมนต์แทนแพ็กเก็ต แต่ละเซ็กเมนต์ TCP มีหมายเลขลำดับซึ่งอยู่ภายในส่วนหัว TCP ข้อมูลจริงที่ส่งในเซ็กเมนต์ TCP เป็นตัวแปร

มีค่าสำหรับgetsockoptที่รองรับในบางระบบปฏิบัติการที่คุณสามารถใช้เรียกว่า TCP_MAXSEG ซึ่งดึงขนาดเซ็กเมนต์ TCP สูงสุด (MSS) ไม่รองรับในทุกระบบปฏิบัติการ

ฉันไม่แน่ใจว่าสิ่งที่คุณกำลังพยายามทำ แต่ถ้าคุณต้องการลดขนาดบัฟเฟอร์ที่ใช้คุณสามารถดู: SO_SNDBUF และ SO_RCVBUF


ฉันสงสัยว่าคุณสามารถใช้ TCP เป็นคิวข้อความได้หรือไม่หากคุณสามารถใส่ข้อความทั้งหมดในแพ็คเก็ต TCP ขนาดใหญ่ได้หรือไม่
— CMCDragonkai


4

ไม่มีแพ็กเก็ตใน TCP API

มีแพ็คเก็ตในโปรโตคอลพื้นฐานบ่อยครั้งเช่นเมื่อ TCP ทำผ่าน IP ซึ่งคุณไม่สนใจเพราะพวกเขาไม่มีส่วนเกี่ยวข้องกับผู้ใช้ยกเว้นการเพิ่มประสิทธิภาพที่ละเอียดอ่อนมากซึ่งคุณอาจไม่สนใจ (อ้างอิงจาก การกำหนดคำถาม)

หากคุณถามจำนวนไบต์สูงสุดที่คุณสามารถทำได้send()ในการเรียก API หนึ่งครั้งการดำเนินการนี้ขึ้นกับการตั้งค่า คุณมักจะโทร send () สำหรับชิ้นงานที่มีขนาดไม่เกินหลายกิโลไบต์และพร้อมเสมอที่ระบบจะปฏิเสธที่จะยอมรับทั้งหมดหรือบางส่วนซึ่งในกรณีนี้คุณจะต้องจัดการแยกชิ้นส่วนด้วยตัวเองเล็ก ๆ เพื่อป้อนข้อมูลของคุณลงใน TCP send () API


8
TCP มีแพ็คเก็ตเช่นเดียวกับส่วนหัวของแพ็กเก็ตส่วนหนึ่งของที่ทับซ้อนกันส่วนหัว IP เพียงเพราะคุณไม่ควรเห็นมันไม่ได้หมายความว่าไม่มีอยู่ TCP จะทำผ่าน IP เสมอ คุณไม่สามารถทำได้หากไม่มี IP เพราะส่วนหัวทับซ้อนกัน
— WhirlWind

23
@WhirlWind TCP มีเซกเมนต์ IP มีแพ็คเก็ต
— มาร์ควิสแห่ง Lorne

1
TCP มีเซกเมนต์ (หรือเรียกมันว่าแพ็กเก็ตมันก็โอเค) TCP API ไม่มีแพ็กเก็ต
— Pavel Radzivilovsky

13
@NathanLong อันตรายคือคุณทำให้เกิดความสับสนโดยไม่จำเป็น TCP มีเซกเมนต์, UDP มีดาตาแกรม, IP มีแพ็คเก็ต, อีเธอร์เน็ตมีเฟรม, ...
— มาร์ควิสแห่ง Lorne

1
@Chexxor แล้วภาษาใดที่คุณจะใช้เพื่ออธิบายส่วน TCP ภายในแพ็กเก็ต IP ภายในเฟรม Ethernet ไม่จำเป็นต้องสร้างความสับสนให้กับปัญหาโดยใช้คำเดียวกันสำหรับสิ่งต่าง ๆ เมื่อผู้เขียนสิ่งเหล่านี้มีปัญหามากมายในการใช้คำที่แตกต่างกัน
— มาร์ควิสแห่ง Lorne

3

โดยทั่วไปจะขึ้นอยู่กับอินเทอร์เฟซที่ใช้ในการเชื่อมต่อ คุณอาจใช้ ioctl () เพื่อรับ MTU และถ้าเป็นอีเธอร์เน็ตคุณมักจะได้ขนาดแพ็คเก็ตสูงสุดโดยการลบขนาดของส่วนหัวของฮาร์ดแวร์จากนั้นคือ 14 สำหรับอีเทอร์เน็ตที่ไม่มี VLAN

นี่เป็นกรณีเฉพาะถ้า MTU นั้นมีขนาดใหญ่อย่างน้อยในเครือข่าย TCP อาจใช้การค้นพบพา ธ MTU เพื่อลด MTU ที่มีประสิทธิภาพของคุณ

คำถามคือทำไมคุณสนใจ


6
นั่นจะทำให้คุณได้รับขนาดแพ็คเก็ตสูงสุดในลิงค์แรก เท่าที่ฉันรู้โหนดอื่น ๆ ตามเส้นทางได้รับอนุญาตให้ไม่ชอบแพ็คเก็ตขนาดใหญ่และมันอาจแยกออกจากกันได้ทุกที่ตามเส้นทาง
— Matti Virkkunen

ใช่นั่นเป็นความจริง ... ดังนั้นคำถามของคุณดี - ทำไมคุณต้องการสิ่งนี้
— WhirlWind

ฉันต้องการส่งวิดีโอ / ภาพผ่านการเชื่อมต่อ LAN
— Alexa

1
เนื่องจาก TCP เป็นแบบ stream-oriented ทำไมถึงเป็นเช่นนั้น
— WhirlWind

3

หากคุณอยู่กับเครื่อง Linux "ifconfig eth0 mtu 9000 up" เป็นคำสั่งเพื่อตั้งค่า MTU สำหรับอินเตอร์เฟส อย่างไรก็ตามฉันต้องบอกว่า MTU ขนาดใหญ่มีข้อเสียบางอย่างถ้าการส่งผ่านเครือข่ายไม่เสถียรและอาจใช้หน่วยความจำพื้นที่เคอร์เนลมากขึ้น


3

ดูเหมือนว่าเว็บไซต์ส่วนใหญ่ในอินเทอร์เน็ตใช้ 1460 ไบต์สำหรับค่าของ MTU บางครั้งอาจเป็น 1452 และถ้าคุณใช้ VPN มันจะลดลงมากขึ้นสำหรับส่วนหัวของ IPSec

ขนาดหน้าต่างเริ่มต้นจะแตกต่างกันไปเล็กน้อยถึง 65535 ไบต์ ฉันใช้http://tcpcheck.comเพื่อดูค่า IP ต้นทางของฉันเองและเพื่อตรวจสอบว่าผู้ขายอินเทอร์เน็ตรายอื่นกำลังใช้งานอะไรอยู่


2

วิธีแก้ปัญหาหนึ่งคือการตั้งค่าตัวเลือกซ็อกเก็ต TCP_MAXSEG ( http://linux.die.net/man/7/tcp ) เป็นค่าที่ "ปลอดภัย" ด้วยเครือข่ายพื้นฐาน (เช่นตั้งค่าเป็น 1400 เพื่อความปลอดภัยบนอีเธอร์เน็ต) จากนั้น ใช้บัฟเฟอร์ขนาดใหญ่ในการส่งการเรียกระบบ วิธีนี้อาจมีการเรียกระบบน้อยซึ่งมีราคาแพง เคอร์เนลจะแบ่งข้อมูลให้ตรงกับ MSS

วิธีนี้คุณสามารถหลีกเลี่ยงข้อมูลที่ถูกตัดทอนและแอปพลิเคชันของคุณไม่ต้องกังวลเกี่ยวกับบัฟเฟอร์ขนาดเล็ก


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.