Αναγν. άρθρου: 823764 - Τελευταία αναθεώρηση: Πέμπτη, 27 Ιανουαρίου 2011 - Αναθεώρηση: 4.0

Αργές επιδόσεις παρουσιάζεται όταν αντιγράφετε δεδομένα σε ένα διακομιστή TCP, χρησιμοποιώντας ένα πρόγραμμα των Windows Sockets API

Συμβουλή συστήματοςΑυτό το άρθρο ισχύει για διαφορετικό λειτουργικό σύστημα από αυτό που χρησιμοποιείτε. Το περιεχόμενο του άρθρου που ενδέχεται να μην σας αφορά έχει απενεργοποιηθεί.

Σε αυτήν τη σελίδα

Ανάπτυξη όλων | Σύμπτυξη όλων

Συμπτώματα

Όταν εκτελείτε ένα πρόγραμμα που χρησιμοποιεί το Windows Sockets API, ενδέχεται να αντιμετωπίσετε χαμηλές επιδόσεις όταν αντιγράφετε δεδομένα σε ένα διακομιστή TCP.

Εάν κάνετε ένα ίχνος δικτύου με sniffer δικτύου όπως το Microsoft Network Monitor, του διακομιστή TCP στέλνει ένα TCP ACK στο τελευταίο τμήμα τμήματος TCP σε μια ροή δεδομένων TCP στο την καθυστερημένη χρονιστής (γνωστό και ως η καθυστερημένη χρονιστή ACK). Από προεπιλογή, για λειτουργικά συστήματα των Windows, η τιμή για αυτόν το χρονιστή είναι 200 χιλιοστών του δευτερολέπτου (ms). Μια τυπική δεδομένων ροής για την αποστολή δεδομένων 64 kilobyte (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 αρχιτεκτονικής. Αυτό το ζήτημα προκύπτει αν ισχύουν όλες οι ακόλουθες συνθήκες:
  • Το πρόγραμμα Windows Sockets χρησιμοποιεί υποδοχές που δεν προκαλεί μπλοκάρισμα.
  • Μία μόνοΑποστολήη κλήση ήWSASendκλήση συμπληρώνει το σύνολο υποκείμενο buffer αποστολής υποδοχής.

    Για παράδειγμα, το πρόγραμμα χρησιμοποιεί το Windows Socketssetsockoptσυνάρτηση για να αλλάξετε την προεπιλεγμένη Υποδοχή αποστολή buffer σε 32 KB κατά τη διάρκεια της υποδοχής ρουτίνες προετοιμασίας:
    setsockopt( sock, SOL_SOCKET, 32768, (char *) &val, sizeof( int ) );
    Αργότερα, όταν το πρόγραμμα στέλνει δεδομένα, που εκδίδει μιαΑποστολήη κλήση ή μιαWSASendκλήσης και αποστέλλει 64 KB δεδομένων κατά τη διάρκεια κάθε αποστολή:
    send(socket, pWrBuffer, 65536, 0);
    Σε αυτό το σενάριο, κάθε φορά που τα θέματα προγραμμάτων σεΑποστολήκλήση από 64 KB δεδομένων, το πρόγραμμα επιστρέφει έναSOCKET_ERRORκωδικός σφάλματος εάν το υποκείμενο υποδοχή 32 KB buffer έχει συμπληρωθεί. Μετά από αυτό, καλεί τοWSAGetLastErrorσυνάρτηση, το πρόγραμμα λαμβάνει τοWSAEWOULDBLOCKο κωδικός σφάλματος. Τα περισσότερα προγράμματα που χρησιμοποιούν το Windows SocketsΕπιλέξτεσυνάρτηση για να ελέγξετε την κατάσταση του socket. Σε αυτό το σενάριο, τοΕπιλέξτεσυνάρτηση δεν αναφέρει την υποδοχή ως εγγράψιμη μέχρι ο υπολογιστής-πελάτης λαμβάνει εξαιρετική τμήματος Επιβεβαίωσης TCP. Από προεπιλογή σε περιβάλλον Windows, αυτό μπορεί να διαρκέσει 200 ms εξαιτίας του αλγόριθμου καθυστέρηση επιβεβαίωσης.
  • Ο απομακρυσμένος διακομιστής TCP αναγνωρίσει όλα τα τμήματα TCP πριν ο υπολογιστής-πελάτης αποστέλλει το τελευταίο τμήμα TCP με ορισμένο το bit ώθησης.

Εναλλακτικός τρόπος αντιμετώπισης

Για να επιλύσετε αυτό το ζήτημα, χρησιμοποιήστε οποιαδήποτε από τις ακόλουθες μεθόδους.

Μέθοδος 1: Χρήση αποκλεισμός υποδοχές

Αυτό το ζήτημα προκύπτει μόνο με τις υποδοχές που δεν προκαλεί μπλοκάρισμα. Όταν χρησιμοποιείτε μια υποδοχή αποκλεισμού, αυτό το ζήτημα παρουσιάζεται επειδή Afd.sys χειρίζεται το buffer υποδοχής με διαφορετικό τρόπο. Για περισσότερες πληροφορίες σχετικά με τον αποκλεισμό και δεν προκαλεί μπλοκάρισμα υποδοχής προγραμματισμού, ανατρέξτε στην τεκμηρίωση του Microsoft Platform SDK.

Μέθοδος 2: Αυξάνουν το μέγεθος του Buffer αποστολή υποδοχής μεγαλύτερο από το μέγεθος του Buffer προγράμματος αποστολής

Για να τροποποιήσετε το buffer αποστολής υποδοχής, χρησιμοποιήστε το Windows Socketsκλήση getsockoptλειτουργεί για να προσδιορίσετε την τρέχουσα υποδοχής μέγεθος buffer αποστολής (SO_SNDBUF), και στη συνέχεια χρησιμοποιήστε τοsetsockoptσυνάρτηση για να ορίσετε την υποδοχή αποστολή μέγεθος buffer. Όταν τελειώσετε, η τιμή SO_SNDBUF πρέπει να είναι μεγαλύτερο από το μέγεθος του buffer αποστολής πρόγραμμα τουλάχιστον 1 byte.

Τροποποίηση τουΑποστολήη κλήση ή τοWSASendη κλήση για να καθορίσετε ένα buffer μεγέθους τουλάχιστον 1 byte μικρότερη από την τιμή SO_SNDBUF. Στο προηγούμενο παράδειγμα στην ενότητα "Αιτία" αυτού του άρθρου, μπορείτε να τροποποιήσετε το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. Κλείστε τον Επεξεργαστή μητρώου.
  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. Κλείστε τον Επεξεργαστή μητρώου.
  6. Κάντε επανεκκίνηση των Windows για αυτή η αλλαγή να τεθεί σε ισχύ.

Μέθοδος 4: Τροποποίηση της προσωρινής αποθήκευσης σε buffer συμπεριφοράς σε Afd.sys για υποδοχές που δεν προκαλεί μπλοκάρισμα

ΣημαντικόΑυτή η ενότητα, μέθοδος ή εργασία περιέχει βήματα που σας καθοδηγούν να τροποποιήσετε το μητρώο. Ωστόσο, ενδέχεται να προκύψουν σοβαρά προβλήματα εάν δεν τροποποιήσετε σωστά το μητρώο. Επομένως, βεβαιωθείτε ότι ακολουθείτε προσεκτικά αυτά τα βήματα. Για επιπλέον προστασία, αντίγραφο ασφαλείας του μητρώου πριν το τροποποιήσετε. Στη συνέχεια, μπορείτε να επαναφέρετε το μητρώο, εάν παρουσιαστεί κάποιο πρόβλημα. Για περισσότερες πληροφορίες σχετικά με τον τρόπο δημιουργίας αντιγράφων ασφαλείας και επαναφοράς του μητρώου, κάντε κλικ στον αριθμό του άρθρου παρακάτω, για να προβάλετε το άρθρο της Γνωσιακής Βάσης της Microsoft:
322756  (http://support.microsoft.com/kb/322756/ ) Τρόπος δημιουργίας αντιγράφων ασφαλείας και επαναφοράς του μητρώου στα Windows


ΣημείωσηΑυτό το κλειδί μητρώου είναι διαθέσιμη μόνο για Windows Server 2003 με Service Pack 1 και επόμενα service pack.
  1. Κάντε κλικ στο κουμπίΈναρξη, πληκτρολογήστετο Regedit.exe, και στη συνέχεια κάντε κλικ στο κουμπίOK.
  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 (32-bit x86)
  • Microsoft Windows Server 2003, Standard Edition (32-bit x86)
  • Microsoft Windows Server 2003, Web Edition
  • Microsoft Windows XP Home Edition
  • Microsoft Windows XP Professional
  • 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
Λέξεις-κλειδιά: 
kbprb kbmt KB823764 KbMtel
Μηχανικά μεταφρασμένοΜηχανικά μεταφρασμένο
ΣΗΜΑΝΤΙΚΟ: Αυτό το άρθρο είναι προϊόν λογισμικού μηχανικής μετάφρασης της Microsoft και όχι ανθρώπινης μετάφρασης. Η Microsoft σάς προσφέρει άρθρα που είναι προϊόντα ανθρώπινης αλλά και μηχανικής μετάφρασης έτσι ώστε να έχετε πρόσβαση σε όλα τα άρθρα της Γνωσιακής Βάσης μας στη δική σας γλώσσα. Ωστόσο, ένα άρθρο που έχει προκύψει από μηχανική μετάφραση δεν είναι πάντα άριστης ποιότητας. Ενδέχεται να περιέχει λεξιλογικά, συντακτικά ή γραμματικά λάθη, όπως ακριβώς τα λάθη που θα έκανε ένας μη φυσικός ομιλητής επιχειρώντας να μιλήσει τη γλώσσα σας. Η Microsoft δεν φέρει καμία ευθύνη για τυχόν ανακρίβειες, σφάλματα ή ζημίες που προκύψουν λόγω τυχόν παρερμηνειών στη μετάφραση του περιεχομένου ή χρήσης του από τους πελάτες της. Επίσης, η Microsoft πραγματοποιεί συχνά ενημερώσεις στο λογισμικό μηχανικής μετάφρασης.
Η αγγλική έκδοση αυτού του άρθρου είναι η ακόλουθη:823764  (http://support.microsoft.com/kb/823764/en-us/ )