2013-07-21 15 views
9

Bloke olmayan bir bağlantı oluşturmak istiyorum. Bunun gibi : Bunun içinLinux, soketler, engellemesiz bağlantı

socket.connect(); // returns immediately 

, ben başka bir iş parçacığı, sonsuz döngüye ve Linux epoll kullanın. Bu (pseudocode) gibi:

// in another thread 
{ 
    create_non_block_socket(); 
    connect(); 

    epoll_create(); 
    epoll_ctl(); // subscribe socket to all events 
    while (true) 
    { 
    epoll_wait(); // wait a small time(~100 ms) 
    check_socket(); // check on EPOLLOUT event 
    } 
} 

Ben bir sunucu ve sonra bir istemci çalıştırırsanız, çalışır hepsi. İlk önce bir istemci çalıştırırsam, biraz bekle, sunucu çalıştır, sonra istemci bağlanmaz.

Neyi yanlış yapıyorum? Belki farklı yapılabilir?

+0

Bağlantıyı gerçekleştirmek için başka bir konu açıyorsanız, neden asenkronize yapıyorsunuz? Ayrıca, buradaki haberlerin geri kalanı da koyabilir. –

+0

Peki, epoll ve nonblocking olmadan nasıl yapılır? Eğer sadece connect() öğesini çağırırsam, o zaman bloke eder ve bağlantı için bekler (doğru muyum?). Ama eğer bu bağlantı parçasını ana iş parçacığına bağlamak istersem, bunu yapamam çünkü bağlantı parçacığı engelleme durumunda olacak. Üzgünüm eğer yanılıyorsam. – herolover

+1

Bu 'async' değil. Bu engelleme değil. – EJP

cevap

28

bağlayabilir bir zaman uyumsuz için aşağıdaki adımları kullanmalısınız:

  • oluşturmak soket
  • connect(fd, ...)
  • dönüş değeri ise
  • ne 0 ne de EINPROGRESS ile başlangıç ​​bağlantısı socket(..., SOCK_NONBLOCK, ...) ile, daha sonra hata
  • ile iptal
  • fd ürününün
  • çıkış için hazır olarak işaretlenmiş olduğunu kontrol edin getsockopt(fd, SOL_SOCKET, SO_ERROR, ...)
  • ile yuvasından tus

yok döngüler yapılır - Eğer EINTR işlemek için istemedikçe.

İstemci ilk kez başlatılmışsa, son adımda ECONNREFUSED hatasını görmelisiniz. Bu olursa, soketi kapatın ve baştan başlayın.

Daha fazla ayrıntı görmeden kodunuzda neyin yanlış olduğunu söylemek zor. Sanırım, check_socket işleminizdeki hataları iptal etmediğiniz.

+0

Bunun eski bir yorum olduğunu biliyorum, ancak sadece ETIMEDOUT'u yakalamak için okumak için beklemek zorunda kaldım. Bu SYN yanıtı iade edilmediğinde meydana geldi. Eğer sadece yazmak için beklediysem, soket netstattan (SYN_SENT durumundan) kaybolur, ancak soketin getsockopt'u aramak ve ETIMEDOUT'u bulmak için yazılabilir olduğunu bildirmezdim. Ayrıca yoklamadan hemen önce herhangi bir anında hata olup olmadığını görmek için getsockopt'a bağlandıktan hemen sonra bir çağrı ekledim. – DreamWarrior

+0

@DreamWarrior: Bu garip. [Connect (2)] (http://linux.die.net/man/2/connect) ve [connect (3)] (http://linux.die.net/man/3/connect adresine bakınız)) ve "anket" için arama yapın. Her iki man sayfası da, belirtmek için beklemeniz gerektiğini, _socket_ _writable_. Beklenmeyen davranışları gösteren minimal bir örnek oluşturabilir misiniz? – nosid

+0

man sayfası "Yazmak için soketi seçerek tamamlanmak üzere (2) veya anketi (2) seçmek mümkündür". Benim tahminim anahtar kelime "tamamlanma" dır. Asla tamamlanmadığı için, SYN-ACK (veya el sıkışmalarını tamamlayan fakat başarısızlıkla sonuçlanan RST) hiç alınmadığı için asla yazılabilir olmadı. – DreamWarrior