2012-07-05 11 views
5

के तहत यादृच्छिक रूप से विफल रहता है हमारा एप्लिकेशन कनेक्ट और चयन ऑपरेशंस (सी कोड) के साथ एक गैर-अवरुद्ध सॉकेट उपयोग का उपयोग करता है। pusedo कोड के रूप में नीचे है:टीसीपी कनेक्ट उच्च लोड

unsigned int ConnectToServer(struct sockaddr_in *pSelfAddr,struct sockaddr_in *pDestAddr) 
    { 
     int sktConnect = -1; 
     sktConnect = socket(AF_INET,SOCK_STREAM,0); 
     if(sktConnect == INVALID_SOCKET) 
      return -1; 
     fcntl(sktConnect,F_SETFL,fcntl(sktConnect,F_GETFL) | O_NONBLOCK); 
     if(pSelfAddr != 0) 
     { 
      if(bind(sktConnect,(const struct sockaddr*)(void *)pSelfAddr,sizeof(*pSelfAddr)) != 0) 
      { 
       closesocket(sktConnect); 
       return -1; 
      } 
     } 
     errno = 0; 
     int nRc = connect(sktConnect,(const struct sockaddr*)(void *)pDestAddr, sizeof(*pDestAddr)); 
     if(nrC != -1) 
     { 
      return sktConnect; 
     } 
     if(errno != EINPROGRESS) 
     { 
      int savedError = errno; 
      closesocket(sktConnect); 
      return -1; 
     } 
     fd_set scanSet; 
     FD_ZERO(&scanSet); 
     FD_SET(sktConnect,&scanSet); 
     struct timeval waitTime; 
     waitTime.tv_sec = 2; 
     waitTime.tv_usec = 0; 
     int tmp; 
     tmp = select(sktConnect +1, (fd_set*)0, &scanSet, (fd_set*)0,&waitTime); 
     if(tmp == -1 || !FD_ISSET(sktConnect,&scanSet)) 
     { 
      int savedErrorNo = errno; 
      writeLog("Connect %s failed after select, cause %d, error %s",inet_ntoa(pDestAddr->sin_addr),savedErrorNo,strerror(savedErrorNo)); 
      closesocket(sktConnect); 
      return -1; 
     } 
    .  .  .  .  .} 

80 ऐसे नोड्स रहे हैं और आवेदन राउंड-रोबिन फैशन में अपने सभी साथियों के को जोड़ता है। इस चरण में, नोड्स के कुछ कनेक्ट करने में सक्षम नहीं हैं (एपीआई - + से कनेक्ट करें चुनें) सफलता परिदृश्य के लिए त्रुटि संख्या 115.

नीचे दिए गए लॉग में (tcpdump उत्पादन की) के साथ, हम देख सकते हैं (एसईएन, एसवाईएन + एसीके, एसीके) लेकिन टीसीपीडम्प लॉग में विफल नोड के लिए भी SYN का कोई प्रविष्टि मौजूद नहीं है।

tcpdump लॉग हैं:

387937 2012-07-05 07:45:30.646514 10.18.92.173   10.137.165.136  TCP  33728 > 8441 [SYN] Seq=0 Ack=0 Win=5792 Len=0 MSS=1460 TSV=1414450402 TSER=912308224 WS=8 
387947 2012-07-05 07:45:30.780762 10.137.165.136  10.18.92.173   TCP  8441 > 33728 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=912309754 TSER=1414450402 WS=8 
387948 2012-07-05 07:45:30.780773 10.18.92.173   10.137.165.136  TCP  33728 > 8441 [ACK] Seq=1 Ack=1 Win=5888 Len=0 TSV=1414450435 TSER=912309754 
All the above three events indicate the success information. 
387949 2012-07-05 07:45:30.782652 10.18.92.173   10.137.165.136  TCP  33728 > 8441 [PSH, ACK] Seq=1 Ack=1 Win=5888 Len=320 TSV=1414450436 TSER=912309754 
387967 2012-07-05 07:45:30.915615 10.137.165.136  10.18.92.173   TCP  8441 > 33728 [ACK] Seq=1 Ack=321 Win=6912 Len=0 TSV=912309788 TSER=1414450436 
388011 2012-07-05 07:45:31.362712 10.18.92.173   10.137.165.136  TCP  33728 > 8441 [PSH, ACK] Seq=321 Ack=1 Win=5888 Len=320 TSV=1414450581 TSER=912309788 
388055 2012-07-05 07:45:31.495558 10.137.165.136  10.18.92.173   TCP  8441 > 33728 [ACK] Seq=1 Ack=641 Win=7936 Len=0 TSV=912309933 TSER=1414450581 
388080 2012-07-05 07:45:31.702336 10.137.165.136  10.18.92.173   TCP  8441 > 33728 [PSH, ACK] Seq=1 Ack=641 Win=7936 Len=712 TSV=912309985 TSER=1414450581 
388081 2012-07-05 07:45:31.702350 10.18.92.173   10.137.165.136  TCP  33728 > 8441 [ACK] Seq=641 Ack=713 Win=7424 Len=0 TSV=1414450666 TSER=912309985 
388142 2012-07-05 07:45:32.185612 10.137.165.136  10.18.92.173   TCP  8441 > 33728 [PSH, ACK] Seq=713 Ack=641 Win=7936 Len=320 TSV=912310106 TSER=1414450666 
388143 2012-07-05 07:45:32.185629 10.18.92.173   10.137.165.136  TCP  33728 > 8441 [ACK] Seq=641 Ack=1033 Win=8704 Len=0 TSV=1414450786 TSER=912310106 
388169 2012-07-05 07:45:32.362622 10.18.92.173   10.137.165.136  TCP  33728 > 8441 [PSH, ACK] Seq=641 Ack=1033 Win=8704 Len=320 TSV=1414450831 TSER=912310106 
388212 2012-07-05 07:45:32.494833 10.137.165.136  10.18.92.173   TCP  8441 > 33728 [ACK] Seq=1033 Ack=961 Win=9216 Len=0 TSV=912310183 TSER=1414450831 
388219 2012-07-05 07:45:32.501613 10.137.165.136  10.18.92.173   TCP  8441 > 33728 [PSH, ACK] Seq=1033 Ack=961 Win=9216 Len=356 TSV=912310185 TSER=1414450831 
388220 2012-07-05 07:45:32.501624 10.18.92.173   10.137.165.136  TCP  33728 > 8441 [ACK] Seq=961 Ack=1389 Win=10240 Len=0 TSV=1414450865 TSER=912310185 

आवेदन कनेक्ट होने पर त्रुटि को सूचित लॉग्स (अर्थात एपीआई - + से कनेक्ट चयन)

[5258: 2012-07-05 07:45:30]Connect [10.137.165.136 <- 10.18.92.173] success. 
[5258: 2012-07-05 07:45:32]Connect 10.137.165.137 fail after select, cause:115, error Operation now in progress. Check whether remote machine exist and the network is normal or not. 
[5258: 2012-07-05 07:45:32]Connect to server([10.137.165.137 <- 10.18.92.173], port=8441) Failed! 

सफलता लॉग tcpdump के पहले 3 प्रविष्टियों के लिए इसी। और विफलता लॉग ऑन जहां tcpdump में कोई इवेंट देखते हैं

मेरा प्रश्न है: जब ग्राहक शुरू की विफल रही है मामले के लिए एपीआई "कनेक्ट", मैं ग्राहक के पक्ष में tcpdump में किसी भी घटना को देखने के लिए सक्षम नहीं हूँ (यहां तक ​​कि प्रारंभिक एसवाईएन)। इस यादृच्छिकता का कारण क्या हो सकता है।

+0

जब आप 'tcpdump' से बाहर निकलते हैं तो क्या आपको 'कर्नेल द्वारा छोड़े गए पैकेट' या 'इंटरफ़ेस द्वारा छोड़े गए पैकेट' के लिए कोई गैर-शून्य मान दिखाई देता है? –

उत्तर

2

आपने EINPROGRESS मारा है। connect मैन पेज से:

सॉकेट अनब्लॉकिंग है और कनेक्शन तुरंत पूरा नहीं किया जा सकता है। लेखन के लिए सॉकेट चुनकर पूरा करने के लिए (2) या मतदान (2) चुनना संभव है। चयन (2) के बाद उत्तरदायित्व इंगित करता है, यह निर्धारित करने के लिए कि कनेक्ट() सफलतापूर्वक पूर्ण हो गया है (SO_ERROR शून्य है) या असफल (SO_ERROR यहां सूचीबद्ध सामान्य त्रुटि कोडों में से एक है, यह निर्धारित करने के लिए स्तर SOL_SOCKET पर SO_ERROR विकल्प को पढ़ने के लिए getockopt (2) का उपयोग करें। विफलता का कारण)।

यह कह रही है कि EINPROGRESS कि कर्नेल अब कनेक्शन पूरा करने के लिए, भले ही उपलब्ध स्थानीय बंदरगाहों और मार्ग कैश प्रविष्टि नहीं कर पा रहा है सूचक है। ऐसा लगता है कि ऐसा तब होता है जब सॉकेट स्थिति अभी तक "स्थापित" में परिवर्तित नहीं हुई है। select में सॉकेट पर बस प्रतीक्षा करें, लेकिन यह देखने के लिए कि connect पूरा हो गया है, getsockopt पर कॉल करें।

क्यों, सॉकेट कनेक्ट होने के दौरान SYN_SENT स्थिति में सॉकेट संक्रमण, लेकिन पैकेट अभी भी आउटपुट कतार में हो सकता है और वास्तव में इसे अभी तक नेटवर्क डिवाइस बफर में नहीं बनाया गया है।

+0

क्या कोई कर्नेल (यानी टीसीपी/आईपी स्टैक लेयर) पैरामीटर है जो ट्यून किए जाने पर सिस्टम में अधिक मजबूती लाकर इन तरह की असंगतताओं को संभाल सकता है। असल में हम ऐसे मामलों में प्रदर्शन पर स्थिरता कैसे सुनिश्चित कर सकते हैं? –

+1

@kumar_m_kiran: यदि आप असीमित रूप से कनेक्ट करना चाहते हैं तो नहीं। अंततः प्रत्येक डिवाइस एक सीमा को हिट करेगा कि यह कितना संचालन कर सकता है। यदि आप इस स्थिति से निपटना नहीं चाहते हैं, तो ब्लॉकिंग मोड में 'कनेक्ट' करें, और फिर सफलता के बाद सॉकेट को गैर-अवरुद्ध करें। – jxh

0

select() रिटर्न के बाद, आप वास्तव में सॉकेट की वर्तमान स्थिति नहीं ले रहे हैं - आप errno (connect() कॉल से ऊपर) में एक पुराना मान देख रहे हैं। सबसे अधिक संभावना है कि select() बस टाइमआउट के बाद वापस आ रहा है।

select() रिटर्न के बाद सॉकेट की वास्तविक स्थिति प्राप्त करने के लिए आपको getsockopt(sktConnect, SOL_SOCKET, SO_ERROR, &err, ...) पर कॉल करने की आवश्यकता है।

संबंधित मुद्दे