ขนาดแพ็คเก็ตสูงสุดสำหรับการเชื่อมต่อ 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.