2016-04-07 18 views
1

C++'da çok iş parçacıklı bir istemci/sunucu oluşturdum. İyi çalışıyor. 'Protokol' metin tabanlı. Ben bir iş parçacığı sunucu() bağlantı yeni bir bağlantı için bekledikten sonra bir bağlantı ile bir şey olur veya istemci incelikle keser olana kadar bir sonsuz döngü içinde çalışan bir sockethandler işlevi var. Şimdi, bu özel program için bir seferde sadece bir müşteriye izin vereceğim. Şimdiye kadar müşteri her zaman başlatıcı oldu ve sunucu cevap verdi. Ancak, istemci programını diğer konulardan çok sayıda veri (boyut, frekans) göndermem gerekiyor ve nasıl yapacağımı bilmiyorum. Kodum çapraz platform - Aynı kaynaktan gelen pencereler ve linux için derledim. İstemci/sunucu kodu çapraz platform da veriyor ya da birkaç satır atıyor ... Bunu yapmanın en iyi yolu nedir? kuyruklar? veya daha hızlı yöntemler var mı? Birisi bana doğru yönde işaret edebilir veya bana bir örnek kod verebilir misiniz? Bunu ayırmaya çalıştım ve tasarımla uğraştım. Bir udp dinleyiciyi istemciye ve bir udp göndericiye sunucuya eklemeyi düşünüyorum, böylece 2 iletişim kanalım var ama bu iyi bir uygulama olup olmadığını bilmiyorum .. Şu anda bir iş parçacığındaki bir soketim var ancak bunu yalnızca bir yönden nasıl kullanacağımı biliyorum - bu benim ana sorunum ...C++ tcp çok iş parçacıklı istemci/sunucu - dişli sockethandler ile nasıl iletişim kurabilirim?

+0

evet ama sunucunun istemciye veri göndermesi gerekiyor - istemcinin herhangi bir zamanda istemediği veriler - hızlı - İstemcim her zaman yoklamam mümkün değil ... – ZoOl007

+0

Bir sunucu veri gönderemiyor varolmayan bir müşteri. Birisinin bir kişiye veri göndermesi için, istemcinin ilk önce kanalı açması ve kanalın müşterinin sonsuza dek açık olması gereken veriyi alabilmesi için. Bunun yerine sunucu istemci modelinden hoşlanmıyorsanız, bunun farklı bir yaklaşımı vardır. –

+0

Herhangi bir uçtan farklı bir yaklaşımı tercih ederseniz, udp iletişimini kullanarak herhangi bir zamanda veri gönderebilir. Dolayısıyla, herhangi bir son, beklenmedik partilerden iletişim almalı ve gönderebilmelidir. –

cevap

0

tasarım bakımından ben 2 iletişim kanalları olması için bir udp müşteriye dinleyici ve sunucuya bir udp gönderen ekleyerek düşünüyorum ama eğer bu iyi bir uygulama olduğunu bilmiyorum ...

(bırakılan paketleri içeren olağan UDP sorunların dışında) orada karşılaşmak olasıdır asıl sorun genellikle istemci makine engelleyen tüm gelen UDP paketleri bir güvenlik duvarı yayınlanmaya başlayacak olmasıdır. Böyle bir durumda, kullanıcıyı kullanmakta olduğunuz bağlantı noktasında gelen UDP paketlerine izin vermek için güvenlik duvarını devre dışı bırakmak veya güvenlik duvarına kural eklemek için talimat vermeniz gerekir (makul bir talep olabilir veya olmayabilir). kullanıcılar, ama kesinlikle bir güçlük olacaktır).

Verilen gibi, istemci her zamanki gibi TCP ile sunucuya bağlanabilseniz ve istemciyi istemciye geri yüklediyseniz, istemciyi aynı TCP bağlantısı üzerinden istemciye geri göndermeniz daha iyi olur. Bu şekilde güvenlik duvarı sorunları önlenir.

İstemci/sunucu kodu çapraz platform olsun ya da birkaç tane satırını alsın ... Bunu yapmak için en iyi yöntem nedir? kuyruklar? veya daha hızlı yöntemler var mı? Birisi bana doğru yönde işaret edebilir veya bana bazı örnek kodu verebilir misiniz?

yorumlarda size temel sorun burada, çapraz iplik haberleşme benim çok kanallı programlarda ben idare yol olduğunu göstermiştir beri:

  1. benim ipliğin her biri olmayan kullanır I/O ve bir engelleme çağrısı etrafında dolaşan bir olay döngüsünü() seçmek için engelleme. Fikir, iş parçacığının engellemesi gereken yegane yerin select() çağrısında olmasıdır ve select() çağrısı yalnızca iş parçacığı için daha fazla iş olduğunda döndürülmelidir.B iplik bir mesaj göndermek için iplik A amacıyla

  2. , iplik A aşağıdakileri yapmanız gerekir:

    a. B iş parçacığı gelen

  3. Yukarıdakilerin hepsi (d) - ipin B uyandırılması için güvenilir olması dışında basittir. Bunu yapmak için (başlangıçta) pipe veya socket-pair'u (A iş parçacığı) gönderebileceği ve B iş parçacığının() öğesini seçebileceğini() açtım. Böylece, (d) 'nin bir parçası olarak, A dişi, borunun (veya prizin) ucundaki sokete bir bayt yazar ve bu da, thread B soketinin okumaya hazır olarak() seçmesine neden olur. B iş parçacığı bunu gördüğü zaman, bayt (lar) ı yuvadan okur (dersi engellemeyen okuma), onları atar, sonra gelen iletileri-kuyruğunu kilitler, tüm iletileri o sıradan alır, tekrar açar, daha sonra yakalanan Mesajları sırayla işler. verimli şeyleri tutmak için, muhtemelen Mesaj onlar büyük miktarda veri içeren olacak, özellikle mümkün olduğunca sıfır kopya olarak nesneleri yapmak isteyeceksiniz o

Not. Bunu, sıraya eklediğiniz tek şeylerin, işaret ettikleri daha büyük Message/data değil, göreceli olarak küçük olan shared_ptr nesneleri olmasını sağlamak için shared_ptr veya benzerlerini kullanarak yapabilirsiniz. Akıllı işaretçiler kullanmak ayrıca Mesajların/verilerin bellek sızıntısına yol açmamasını sağlar.

Bu tür bir şey, G/Ç'yi de engelleme ile işe yarayabilir; ancak, G/Ç'yi engelliyorsanız, bir iş parçacığının, gönderdiğiniz bir iletiye yanıt vermek için ne kadar süre alacağı konusunda hiçbir garantiniz olmayacaktır. - özellikle bir ağ sorunu varsa, bir TCP soketindeki bir ileti dizisi() 'nin birden fazla dakika için geri dönüşü olmayabilir ve bu konuda yapabileceğiniz fazla bir şey yoktur - ve elbette recv()' ye bir çağrı olabilir. istemciden gelen veri yoksa sonsuza kadar engellenir. Bu yüzden, mümkünse her zaman engellemeyen G/Ç kullanıyorum.

+0

Windows'ta socketpair() bulunmadığını, ancak bazı örnekler için Windows altında derlerken kullanılmak üzere socketpair() uygulamanızın yuvarlanmasının zor olmadığını unutmayın. Bazı örnekler için google "Windows socketpair". –

0

Sunucuya bir istemci bağlandığında, sunucuda bir giriş ve çıkış dosyası. Bu nedenle, sunucunuzdaki çeşitli görevlerden erişebileceğiniz, yalnızca bir paylaşılan iletişim kanalına ihtiyacınız varsa, iletişimi alan ve iletişim kanallarını (temizlik hizmetini) açan bir göreviniz olmalıdır. Daha sonra, bu "paylaşımlı kaynağı", her bir iş parçacığından, bozulmayı engellemek için kilitler kullanarak genel bir değişken olarak kullanabilirsiniz.

İlgili konular