หมายเลขบทความ (Article ID): 823764 - รีวิวครั้งสุดท้าย: 28 มกราคม 2554 - Revision: 5.0

ประสิทธิภาพการทำงานที่ช้าลงเกิดขึ้นเมื่อคุณคัดลอกข้อมูลไปยังเซิร์ฟเวอร์ TCP โดยใช้โปรแกรม Windows Sockets API

เคล็ดลับของระบบThis article applies to a different operating system than the one you are using. Article content that may not be relevant to you is disabled.

เนื้อหาบนหน้านี้

ขยายทั้งหมด | ยุบทั้งหมด

อาการ

เมื่อคุณเรียกใช้โปรแกรมที่ใช้ api ของ Windows Sockets คุณอาจพบประสิทธิภาพการทำงานที่ช้าลงเมื่อคุณคัดลอกข้อมูลไปยังเซิร์ฟเวอร์ของ TCP

ถ้าคุณทำการสืบค้นกลับของเครือข่าย ด้วย sniffer ในเครือข่ายเช่นการตรวจสอบเครือข่าย Microsoft, TCP server ส่งเซ็ก TCP ACK เมนต์สุดท้าย TCP เซ็กเมนต์ในกระแสข้อมูลข้อมูล TCP ในตัวจับเวลาตอบรับที่ล่าช้า (หรือเรียกอีกอย่างหนึ่งว่าการล่าช้า ACK เมอร์) โดยค่าเริ่มต้น สำหรับระบบปฏิบัติการ Windows ค่าสำหรับตัวจับเวลานี้คือ 200 มิลลิวินาที (ms) แบบกระแสข้อมูลทั่วไปสำหรับการส่งข้อมูล 64 กิโลไบต์ (KB) มีลักษณะคล้ายกับลำดับต่อไปนี้:
Client->Server 1460 bytes
Client->Server 1460 bytes
Server->Client ACK
Client->Server 1460 bytes
Client->Server 1460 bytes
Server->Client ACK
....
Client->Server 1460 bytes
Client->Server 1460 bytes
Server->Client ACK-PUSH
Client->Server 1296 bytes
-> delayed ACK 200 ms


สาเหตุ

ปัญหานี้เกิดขึ้นเนื่องจากการทำงานของ Windows Sockets API และ Afd.sys architectural ปัญหานี้เกิดขึ้นหากเงื่อนไขต่อไปนี้ทั้งหมด:
  • โปรแกรม Windows Sockets ใช้ซ็อกเก็ตที่ไม่มีการบล็อค
  • เพียงอย่างเดียวส่งโทร หรือWSASendโทรกรอกข้อมูลส่งบัฟเฟอร์ทั้งต้นแบบของซ็อกเก็ต

    ตัวอย่างเช่น โปรแกรมใช้ซ็อกเก็ต Windowssetsockoptฟังก์ชันการเปลี่ยนซ็อกเก็ตเริ่มต้นส่งบัฟเฟอร์ไปยัง 32 KB ในระหว่างการซ็อกเก็ตของงานประจำในการเตรียมใช้งาน:
    setsockopt( sock, SOL_SOCKET, 32768, (char *) &val, sizeof( int ) );
    ภายหลัง เมื่อโปรแกรมส่งข้อมูล โปรแกรมออกแบบส่งเรียก หรือการWSASendโทรและส่งข้อมูลระหว่างแต่ละ 64 กิโลไบต์ส่ง:
    send(socket, pWrBuffer, 65536, 0);
    ในสถานการณ์สมมตินี้ แต่ละครั้งปัญหาโปรแกรมส่งการเรียกข้อมูล 64 กิโลไบต์ กลับโปรแกรมSOCKET_ERRORรหัสข้อผิดพลาดถ้าบัฟเฟอร์ซ็อกเก็ต 32 KB พื้นฐานอย่างสมบูรณ์ถูกกรอกข้อมูล หลังจากนั้นเรียกตัวWSAGetLastErrorฟังก์ชัน โปรแกรมได้รับการWSAEWOULDBLOCKรหัสข้อผิดพลาด โปรแกรมส่วนใหญ่ใช้ซ็อกเก็ต Windowsเลือกฟังก์ชันเพื่อตรวจสอบสถานะของซ็อกเก็ต ในสถานการณ์สมมตินี้ การเลือกฟังก์ชันรายงานซ็อกเก็ตเป็นแบบเขียนได้จนกว่าไคลเอ็นต์เซ็กเมนต์ TCP ACK คงเหลือที่ได้รับ โดยค่าเริ่มต้นในสภาพแวดล้อมของ Windows นี้อาจใช้เวลานาน 200 ms เนื่องจากของอัลกอริทึมการรับรองล่าช้า
  • TCP เซิร์ฟเวอร์ระยะไกลให้การเซ็กเมนต์ TCP ทั้งหมดก่อนที่ไคลเอนต์ส่งเซ็กเมนต์ TCP ล่าสุด มีการตั้งค่าบิตกด

การหลีกเลี่ยงปัญหา

เมื่อต้องหลีกเลี่ยงปัญหานี้ ใช้อย่างใดอย่างหนึ่งในวิธีต่อไปนี้

วิธีที่ 1: ใช้ซ็อกเก็ตที่บล็อก

ปัญหานี้เกิดขึ้นกับบล็อกไม่ใช่ซ็อกเก็ตเท่านั้น เมื่อคุณใช้ซ็อกเก็ตที่บล็อก ปัญหานี้ไม่เกิดขึ้นเนื่องจาก Afd.sys ให้จัดการกับบัฟเฟอร์ของซ็อกเก็ตที่แตกต่างออกไป สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการบล็อก และ บล็อกไม่ใช่ซ็อกเขียนโปรแกรม ดูเอกสารประกอบของ Microsoft Platform SDK

วิธีที่ 2: ทำให้ขนาดของบัฟเฟอร์ที่ส่งซ็อกเก็ตใหญ่กว่าขนาดของบัฟเฟอร์ที่ส่งโปรแกรม

เมื่อต้องการปรับเปลี่ยนการบัฟเฟอร์ส่งซ็อกเก็ต ใช้ซ็อกเก็ต Windowsเรียกgetsockoptทำการตรวจสอบซ็อกเก็ตขนาดบัฟเฟอร์ที่ส่ง (SO_SNDBUF) ปัจจุบัน จากนั้น ใช้การsetsockoptทำงานกับการตั้งค่าที่ใช้ซ็อกเก็ตส่งบัฟเฟอร์ขนาด เมื่อเสร็จเรียบร้อยแล้ว ค่า SO_SNDBUF ต้องมีขนาดใหญ่กว่าขนาดของบัฟเฟอร์ส่งโปรแกรมน้อย 1 ไบต์

ปรับเปลี่ยนการส่งเรียก หรือการWSASendการเรียกเพื่อระบุขนาดของบัฟเฟอร์มีขนาดเล็กกว่าค่า SO_SNDBUF น้อย 1 ไบต์ ในตัวก่อนหน้าอย่างในส่วน "สาเหตุ" ของบทความนี้ คุณสามารถปรับเปลี่ยนการsetsockoptเรียกค่าต่อไปนี้
setsockopt( sock, SOL_SOCKET, 65537, (char *) &val, sizeof( int ) );
หรือคุณสามารถปรับเปลี่ยนการส่งเรียกค่าต่อไปนี้:
send(socket, pWrBuffer, 32767, 0);
นอกจากนี้คุณยังสามารถใช้รวมกันของค่าเหล่านี้

วิธีที่ 3: ปรับเปลี่ยนการตั้งค่า TCP/IP บนเซิร์ฟเวอร์ TCP

สิ่งสำคัญนี้ส่วน วิธีการ หรืองานประกอบด้วยขั้นตอนที่บอกให้คุณทราบวิธีการแก้ไขรีจิสทรี อย่างไรก็ตาม ปัญหาร้ายแรงอาจเกิดขึ้นหากคุณปรับเปลี่ยนรีจิสทรีอย่างไม่ถูกต้อง ดังนั้น ให้แน่ใจว่า คุณทำตามขั้นตอนเหล่านี้อย่างระมัดระวัง สำหรับการป้องกันเพิ่มเติม สำรองรีจิสทรีก่อนที่คุณแก้ไข แล้ว คุณสามารถคืนค่ารีจิสทรีหากเกิดปัญหา สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการสำรองข้อมูล และคืนค่ารีจิสทรี คลิกหมายเลขบทความต่อไปนี้เพื่อดูบทความในฐานความรู้ของ Microsoft:
322756  (http://support.microsoft.com/kb/322756/ ) วิธีการสำรองข้อมูล และคืนค่ารีจิสทรีใน Windows


ปรับเปลี่ยนการตั้งค่า TCP/IP บนเซิร์ฟเวอร์ TCP เพื่อยอมรับการเซ็กเมนต์ TCP ขาเข้าทันที วิธีแก้ปัญหานี้ทำงานได้ดีในสภาพแวดล้อมที่มีการติดตั้งไคลเอนต์ที่ใหญ่พื้นฐาน และโดยที่คุณไม่สามารถเปลี่ยนแปลงลักษณะการทำงานของโปรแกรม สำหรับสถานการณ์สมมติที่ TCP เซิร์ฟเวอร์ระยะไกลที่เรียกใช้บนเซิร์ฟเวอร์ที่ใช้ Windows คุณต้องแก้ไขรีจิสทรีของเซิร์ฟเวอร์ระยะไกล สำหรับระบบปฏิบัติการอื่น ๆ ดูที่ส่วนเอกสารของระบบปฏิบัติการสำหรับข้อมูลเกี่ยวกับวิธีการเปลี่ยนเวลาตอบรับที่ล่าช้า

บนเซิร์ฟเวอร์ที่รัน Windows 2000 ให้ทำตามขั้นตอนเหล่านี้:
  1. เริ่มตัวแก้ไขรีจิสทรี (Regedit.exe)
  2. ค้นหา และคลิ กที่คีย์ย่อยของรีจิสทรีต่อไปนี้:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<interface guid=""></interface>
  3. บนเครื่องแก้ไขเมนู คลิกเพิ่มค่าแล้ว สร้างค่ารีจิสทรีต่อไปนี้:

    ชื่อของค่า:TcpDelAckTicks
    ชนิดข้อมูล:REG_DWORD
    ข้อมูลค่า:0
  4. ออกจาก Registry Editor
  5. รีสตาร์ท Windows สำหรับการเปลี่ยนแปลงนี้มีผล
บนเซิร์ฟเวอร์ที่เรียกใช้ Windows XP หรือ Windows Server 2003 ให้ทำตามขั้นตอนเหล่านี้:
  1. เริ่มตัวแก้ไขรีจิสทรี
  2. ค้นหา และคลิ กที่คีย์ย่อยของรีจิสทรีต่อไปนี้:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\<interface guid=""></interface>
  3. บนเครื่องแก้ไขเมนู การชี้ไปที่ใหม่แล้ว คลิกค่า DWORD.
  4. ชื่อค่าใหม่TcpAckFrequencyและกำหนดค่าเป็น 1
  5. ออกจาก Registry Editor
  6. รีสตาร์ท Windows สำหรับการเปลี่ยนแปลงนี้มีผล

วิธีที่ 4: การปรับเปลี่ยนพฤติกรรมบัฟเฟอร์ใน Afd.sys สำหรับบล็อกไม่ใช่ซ็อกเก็ต

สิ่งสำคัญนี้ส่วน วิธีการ หรืองานประกอบด้วยขั้นตอนที่บอกให้คุณทราบวิธีการแก้ไขรีจิสทรี อย่างไรก็ตาม ปัญหาร้ายแรงอาจเกิดขึ้นหากคุณปรับเปลี่ยนรีจิสทรีอย่างไม่ถูกต้อง ดังนั้น ให้แน่ใจว่า คุณทำตามขั้นตอนเหล่านี้อย่างระมัดระวัง สำหรับการป้องกันเพิ่มเติม สำรองรีจิสทรีก่อนที่คุณแก้ไข แล้ว คุณสามารถคืนค่ารีจิสทรีหากเกิดปัญหา สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการสำรองข้อมูล และคืนค่ารีจิสทรี คลิกหมายเลขบทความต่อไปนี้เพื่อดูบทความในฐานความรู้ของ Microsoft:
322756  (http://support.microsoft.com/kb/322756/ ) วิธีการสำรองข้อมูล และคืนค่ารีจิสทรีใน Windows


หมายเหตุรีจิสทรีคีย์นี้จะพร้อมใช้งานสำหรับ Windows Server 2003 Service Pack 1 และต่อมาเซอร์วิสแพ็คเท่านั้น
  1. คลิกเริ่มการทำงานชนิดregedit.exeแล้ว คลิกตกลง.
  2. ค้นหา และคลิ กที่คีย์ย่อยของรีจิสทรีต่อไปนี้:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters
  3. บนเครื่องแก้ไขเมนู การชี้ไปที่ใหม่แล้ว คลิกค่า DWORD.
  4. ชื่อค่าใหม่NonBlockingSendSpecialBufferingและกำหนดค่าเป็น 1
  5. ออกจากตัวแก้ไขรีจิสทรี
  6. รีสตาร์ท Windows สำหรับการเปลี่ยนแปลงนี้มีผล

สถานะ

Microsoft ยืนยันว่า ปัญหานี้เป็นปัญหาที่เกิดขึ้นกับผลิตภัณฑ์ของ Microsoft ซึ่งแสดงไว้ในส่วน"ใช้งาน"

ข้อมูลอ้างอิง

328890  (http://support.microsoft.com/kb/328890/ ) รายการรีจิสทรีใหม่สำหรับการควบคุมพฤติกรรมการยอมรับ TCP (ACK) ใน Windows XP และ ใน Windows Server 2003

ใช้กับ
  • Microsoft Windows Server 2003 Enterprise Edition
  • Microsoft Windows Server 2003 Standard Edition
  • Microsoft Windows Server 2003 Web Edition
  • Microsoft Windows XP Home Edition
  • Microsoft Windows XP Professional Edition
  • Microsoft Windows 2000 Advanced Server
  • Microsoft Windows 2000 Professional Edition
  • Microsoft Windows 2000 Server
  • Windows Server 2008 Datacenter without Hyper-V
  • Windows Server 2008 Enterprise without Hyper-V
  • Windows Server 2008 for Itanium-Based Systems
  • Windows Server 2008 Standard without Hyper-V
  • Windows Server 2008 Datacenter
  • Windows Server 2008 Enterprise
  • Windows Server 2008 Standard
  • Windows Web Server 2008
Keywords: 
kbprb kbmt KB823764 KbMtth
แปลโดยคอมพิวเตอร์แปลโดยคอมพิวเตอร์
ข้อมูลสำคัญ: บทความนี้แปลโดยซอฟต์แวร์การแปลด้วยคอมพิวเตอร์ของ Microsoft แทนที่จะเป็นนักแปลที่เป็นบุคคล Microsoft มีบทความที่แปลโดยนักแปลและบทความที่แปลด้วยคอมพิวเตอร์ เพื่อให้คุณสามารถเข้าถึงบทความทั้งหมดในฐานความรู้ของเรา ในภาษาของคุณเอง อย่างไรก็ตาม บทความที่แปลด้วยคอมพิวเตอร์นั้นอาจมีข้อบกพร่อง โดยอาจมีข้อผิดพลาดในคำศัพท์ รูปแบบการใช้ภาษาและไวยากรณ์ เช่นเดียวกับกรณีที่ชาวต่างชาติพูดผิดเมื่อพูดภาษาของคุณ Microsoft ไม่มีส่วนรับผิดชอบต่อความคลาดเคลื่อน ความผิดพลาดหรือความเสียหายที่เกิดจากการแปลเนื้อหาผิดพลาด หรือการใช้บทแปลของลูกค้า และ Microsoft มีการปรับปรุงซอฟต์แวร์การแปลด้วยคอมพิวเตอร์อยู่เป็นประจำ
ต่อไปนี้เป็นฉบับภาษาอังกฤษของบทความนี้:823764  (http://support.microsoft.com/kb/823764/en-us/ )