2012-07-05 16 views
5

Uygulamamız, bağlantı ve seçim işlemleri (c kodu) ile engellenmeyen bir soket kullanımı kullanıyor. pusedo kod aşağıda:tcp bağlantısı yüksek yük altında rasgele başarısız oluyor

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 tür düğümleri vardır ve uygulama yuvarlak oturumu tarzında tüm eş bağlanır. Bu aşamada , bazı düğümler bağlamak mümkün değildir (api - + bağlamak seçin) başarı senaryosu için hata numarası (tcpdump çıkışı) altına günlüklerinde 115.

ile biz (görebilirsiniz SYN, SYN + ACK, ACK) ancak tcpdump günlüklerindeki başarısız düğümü için SYN bile girişi yok.

tcpdump'ı günlükleri: bağlantı hatası bildiren

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 

uygulama günlükleri - tcpdump'ı ilk 3 girişlere tekabül eden

[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! 

Başarı tomruk (yani API seçmek + bağlayın). tcpdump herhangi bir etkinlik olduğu yerde Ve başarısızlık log

Sorum şu: istemci başlattığında ( i istemci tarafında tcpdump herhangi bir olayı görmek mümkün değilim, başarısız durum için bile api “bağlamak” başlangıç ​​SYN). Bu rastlantının sebebi ne olabilir?

+0

tcpdump' Eğer kernel' veya interface' düştü' paketler düştü 'paketleri için sıfır olmayan değerler görüyorsunuz? –

cevap

2

EINPROGRESS numaralı ürüne çarptı. connect adam sayfasından:

Soket kilitlenmiyor ve bağlantı hemen tamamlanamıyor. Yazmak için soketi seçerek tamamlanmak üzere (2) veya anketi (2) seçmek mümkündür. Seçim (2), yazılabilirliği işaretledikten sonra, connect() başarıyla (SO_ERROR sıfır) veya başarısız olursa (SO_ERROR, burada listelenen normal hata kodlarından biri olup olmadığını belirlemek için SOL_SOCKET düzeyinde SO_ERROR seviyesini okumak için getsockopt (2) işlevini kullanın. başarısızlık sebebi). Bu EINPROGRESS çekirdek mevcut yerel bağlantı noktaları ve yönlendirme önbellek girdileri bulunmasına rağmen, şimdi bağlantıyı tamamlamak için mümkün olmadığını bir göstergesi olduğunu söylüyor

. Soket durumu henüz "ESTABLISHED" e geçmediği zaman bu gerçekleşir. Yeniden select numaralı yuvada bekleyiniz, ancak daha sonra connect'un tamamlanıp tamamlanmadığını görmek için getsockopt numaralı telefonu arayınız.

Soket, bağlantı sırasında SYN_SENT durumuna geçiş yapar, ancak paket yine de kuyruk kuyruğunda olabilir ve henüz ağ aygıtı arabelleğine henüz gelmemiş olabilir.

+0

Ayarlandığında, sistemde daha fazla sağlamlık sağlayarak bu tür tutarsızlıkları halledebilecek herhangi bir çekirdek (yani TCP/IP yığın katmanı) parametresi var mı? Temel olarak bu gibi durumlarda performans üzerinde istikrarı nasıl sağlayabiliriz? –

+1

@kumar_m_kiran: Eşzamansız olarak bağlanmak istemiyorsanız. Her cihaz, saniyede kaç işlem yapılabileceği konusunda bir sınırlama getirecektir. Bu durumla uğraşmak istemiyorsanız, engelleme modunda “bağlanın” ve ardından başarıdan sonra soketi engellemeyin. – jxh

0

select() döndürdükten sonra, aslında soketin geçerli durumunu almıyorsunuz demektir - errno (eski adıyla connect() çağrısından) eski bir değer görüyorsunuz. Büyük olasılıkla, select(), zaman aşımından sonra geri dönüyor.

select() dönüşlerinden sonra soketin gerçek durumunu öğrenmek için getsockopt(sktConnect, SOL_SOCKET, SO_ERROR, &err, ...) numaralı telefonu aramanız gerekir.Eğer `çıktığınızda

İlgili konular