ซ็อกเก็ต TCP ส่งจำนวนไบต์น้อยลง

ฉันกำลังพยายามส่งไบต์จำนวนมากโดยใช้ไลบรารี boost.asio ดังต่อไปนี้:

void tcp_send(boost::asio::io_service &io, const char *dst_ip, uint16 dst_port)
{
    uint8 *sbuff;
    size_t slen;
    ip::tcp::socket sock(io);

    sock.connect(ip::tcp::endpoint(ip::address::from_string(dst_ip), dst_port));

    sbuff = new uint8[100412];
    sbuff[0] = 67;
    sbuff[1] = 193;
    sbuff[2] = 136;
    sbuff[3] = 60;

    boost::asio::async_write(sock, boost::asio::buffer(sbuff, 100412),
             boost::bind((&send_handler), placeholders::error));
}

เมื่อฉันตรวจสอบจำนวนไบต์ที่ส่งโดยใช้ wireshark ผู้ส่งจะส่งข้อมูลเสมอและมีเพียง 65536 ไบต์เท่านั้น ไม่รวมไบต์ของส่วนหัว TCP แล้วจะมีปัญหาอะไรล่ะ? มีพารามิเตอร์ใดบ้างที่ฉันจำเป็นต้องแก้ไข

ฉันกำลังรันแอปพลิเคชันบน linux ubuntu ดูเหมือนว่าจำนวนไบต์ที่ส่งสูงสุดคือ 2^16

กระแสสตรีม Wireshark TCP


person IoT    schedule 21.05.2014    source แหล่งที่มา


คำตอบ (2)


TCP คือ กระแสข้อมูล จำนวนไบต์ที่ปรากฏในดาตาแกรม IP หรือเฟรมอีเธอร์เน็ตไม่ควรเป็นกังวลสำหรับคุณ

การเรียก send ได้สำเร็จไม่ได้แปลว่าข้อมูลถูกส่งไปแล้วเสมอไป เพียงแค่ว่าสแต็ก TCP ยอมรับข้อมูลและสัญญาว่าจะส่งข้อมูลนั้น (เว้นแต่คุณจะระบุ PSH)

person Jonathon Reinhart    schedule 21.05.2014
comment
แล้วฉันควรทำอย่างไรในกรณีของฉันเพื่อให้ไบต์ทั้งหมด 1,00412 ไบต์หายไป จริงๆ แล้วฉันไม่ได้มีปัญหาเมื่อฉันใช้ซ็อกเก็ต Berkeley โดยตรง แต่ตอนนี้ฉันมีปัญหานี้กับตัวห่อเสริม - person IoT; 22.05.2014
comment
ไม่แน่ใจว่าคุณนำเนื้อหาที่เหลือไปใช้อย่างไร แต่คุณอาจลองติดตามได้ใน send_handler - person Captain Obvlious; 22.05.2014
comment
โปรดตรวจสอบการแก้ไขใหม่ของฉันที่ฉันให้เอาต์พุต wireshark ไว้ send_handler ใช้สำหรับการจัดการข้อผิดพลาดเท่านั้น - person IoT; 22.05.2014
comment
send_handler จะถูกเรียกเมื่อการส่งเสร็จสมบูรณ์ ไม่ว่าจะสำเร็จหรือไม่ก็ตาม ให้มันบอกคุณว่าบัฟเฟอร์เต็มถูกส่งไปแล้ว หรือการส่งล้มเหลวหรือไม่ มีโอกาสที่มันจะล้มเหลวหลังจากส่ง 65536 ไบต์ TCP ไม่สามารถส่ง 100412 ไบต์ในแพ็กเก็ตเดียว ดังนั้น async_write() ควรส่งหลายแพ็กเก็ตจนกว่า buffer จะหมดหรือมีข้อผิดพลาดเกิดขึ้น - person Remy Lebeau; 22.05.2014
comment
ตอนนี้ฉันพยายามแทนที่ boost::asio::async_write() ด้วย boost::asio::write และการดำเนินการก็สำเร็จ ฉันสามารถดูไบต์ทั้งหมดใน wireshark ได้ ใครช่วยอธิบายให้ฉันฟังหน่อยว่าเกิดอะไรขึ้น? @Remy คุณถูกต้อง แต่ฉันไม่ได้รับข้อผิดพลาดใด ๆ ใน send_handler เลย - person IoT; 22.05.2014

ฉันพบสาเหตุของปัญหาแล้ว ก่อนอื่นฉันพยายามส่งข้อความโดยใช้ฟังก์ชัน tcp_Send และหลังจากที่มันกลับมาจากการโทรฉันก็มีโปรแกรมอยู่ ด้วยเหตุนี้สแต็ก TCP จึงไม่มีเวลาเพียงพอที่จะส่งแพ็กเก็ตทั้งหมดในบัฟเฟอร์ ฉันจึงควรให้เวลามันบ้าง

ในการทดลองใช้ครั้งที่สอง ฉันยังคงให้แอปพลิเคชันทำงานต่อไปหลังจากส่งข้อความ แต่ตอนนี้ฉันได้รับข้อผิดพลาดใน send_handler ซึ่งระบุว่า bad file descriptor และนี่เป็นเพราะว่าซ็อกเก็ตที่ถูกประกาศถูกทำลายหลังจากออกจากฟังก์ชัน tcp_send ดังนั้นเพื่อแก้ไขปัญหานี้ ฉันควรกำหนดซ็อกเก็ตให้เป็นตัวชี้ หรือสิ่งที่ดีที่สุดคือใช้การเขียนแทน async_Write

person IoT    schedule 22.05.2014
comment
ที่จะไม่ทำให้ข้อมูลสูญหาย เมื่อคุณทำลาย ip::tcp::socket ซ็อกเก็ตที่ซ่อนอยู่จะถูกปิด แต่ข้อมูลที่ค้างอยู่ทั้งหมดจะยังคงอยู่ในบัฟเฟอร์การส่งซ็อกเก็ตสำหรับการส่งข้อมูลในที่สุด ตามด้วยการปิดอย่างเป็นระเบียบ (TCP FIN) อย่างไรก็ตาม อาจไม่ได้ส่งทั้งหมดในขณะที่โปรแกรมของคุณออก - person user207421; 22.05.2014
comment
ฉันยังไม่ได้ทดสอบเมื่อเร็ว ๆ นี้ แต่เคยเป็นว่าใน Windows (XP และรุ่นก่อนหน้า) การออกจากกระบวนการจะทิ้งข้อมูลที่ยังไม่ได้ส่งใด ๆ จากสแต็กเครือข่าย ในขณะที่ระบบ *nix ข้อมูลจะยังคงถูกส่งไปในที่สุด PITA ที่แท้จริงสำหรับโปรแกรมเมอร์ Windows เนื่องจากไม่มีวิธีที่ดีในการถามว่าข้อมูลถูกส่งจริงหรือไม่ - person Dale Wilson; 22.05.2014