Jump to page: 1 2
Thread overview
socket uygulama için çoklu port desteği ?
Sep 14, 2013
darkofpain
Sep 15, 2013
darkofpain
Sep 15, 2013
darkofpain
Sep 16, 2013
Salih Dinçer
Sep 16, 2013
darkofpain
Sep 16, 2013
darkofpain
Sep 16, 2013
darkofpain
September 15, 2013

arkadaşlar kodlarını verdiğim şekilde bir http sınıfı yazıyorum ancak yapmak istediğim birden fazla porta destek vermek sınır olmadan.

şuanda sadece 9000 portu dinliyor bense 8080,8085,8090,8095,9000

gibi portları yazarak bunlara destek vermesini sağlamak istiyorum bunu nasıl yapabilirim.

import std.stdio;
import std.socket;
import std.concurrency;
import core.thread;

class http {

	char[1000] buffer;

	public void httpHeaders()
	{

	}

	private void httpRequests()
	{
		auto listener = new TcpSocket();
		auto internet = new InternetAddress(8080);

		listener.setOption(SocketOptionLevel.SOCKET,SocketOption.REUSEADDR,true);
		listener.bind(internet);
		listener.listen(1);

		try
		{
			while(true)
			{
				Thread.sleep(500.msecs);

				auto client = listener.accept();
				auto received = client.receive(buffer);

				string response =
				(
					"HTTP/1.1 200 OK \n"
					"Content-Type: text/html; charset=utf-8 \n\n"
					"<b>Hello World</b> \n"
				);

				client.send(response);
				client.shutdown(SocketShutdown.BOTH);
				client.close();

				writefln("%s",buffer);
			}
		}
		catch(Exception error)
		{
			writefln("%s",error.msg);
		}
	}

	public void listenLoop()
	{
		httpRequests();
	}

}
void main()
{
   auto application = new http;
   application.listenLoop();
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 15, 2013

Teşekkür ederim acehreli,

Düşündüğüm denediğim gibi yapmışssınız ama benim hatam parallelism ile dağıtmadım :(

Peki yapmak istediğim birşey var non-blocking bir yapı yapmam lazım istekler arttıkça çökmeler ve tıkanmalar olmaması ve isteklerin hepsi kabul edip işleme alması için bu yüzden multithread yada multiprogressing özelliği getirmek istiyorum tabi yanlış yolda olabilirim önerinizi almak istiyorum ve nasıl yapacağımıda.

ben buradaki yazınızı okuyarak http://ddili.org/ders/d/es_zamanli.html

Spawn ile gelen isteklere işçi atamak ve işçi işlemini bitirene çıktıyı gönderene kadar çalıştırmak istedim ama başarılı olamadım. Tabiki bu doğru yolmu onuda bilemedim.

Birde şöyle bir düşüncem var.

Uygulamanın çalıştığı server daki var olan işlemci(ler) toplamında 8 çekirdeğimiz olduğunuz farz edelim her çekirdeği ayrı ayrı kullanarak gelen istekleri işlemci çekirdekleri üzerinde işçilerle dağıtmak.

tabiki daha tecrübeli biri olarak son söz sizde acehreli nasıl yapacağım konusunda ve önerileriniz le bana yardımcı olursanız sevinirim.

Alıntı:

>

Sorun: çözemedim neden olduğunu ama 9000 portuna kadar çalışıyor 9000 portunda çalışmıyor

portları şöyle yaptım ushort[] portlar = [8050,8055,8060,8065,8070,8075,8080,8085,8090,8095];

8060 dan sonrası işlemiyor mesela 8075 olarak giriyorum ekrana görüntü gelmiyor ama buffer dan data terminal ekranına geliyor :/

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 15, 2013

Bir port meşgulken diğerlerinin istemci kabul etmelerini de istediğimizi tahmin ediyorum. O zaman iş parçacıkları olarak işleyecekler. Bu gibi durumlarda uygulanacak basit kural şu:

  • Eğer iş parçacıkları birbirlerinden bağımsızsa std.parallelism, birbirleriyle konuşacaklarsa std.concurrency.

Bağımsız olduklarını düşündüğüm için programını aşağıdaki gibi değiştirdim. Değiştirdiğim her noktaya bir açıklama ekledim:

import std.stdio;
import std.socket;
import std.concurrency;
// Sunucuları koşut olarak işleteceğiz
import std.parallelism;
import core.thread;

class http {

   char[1000] buffer;
   // Her sunucu hangi portu kullandığını bilmeli
   ushort port;

   // Hangi portu kullanacağı kurulurken bildirilmeli
   this(ushort port)
   {
       this.port = port;
   }

   public void httpHeaders()
   {

   }

   private void httpRequests()
   {
       auto listener = new TcpSocket();
       // 8080 sabit portu yerine ona verilen portu dinlemeli
       auto internet = new InternetAddress(port);

       listener.setOption(SocketOptionLevel.SOCKET,SocketOption.REUSEADDR,true);
       listener.bind(internet);
       listener.listen(1);

       try
       {
           while(true)
           {
               Thread.sleep(500.msecs);

               auto client = listener.accept();
               auto received = client.receive(buffer);

               string response =
               (
                   "HTTP/1.1 200 OK \n"
                   "Content-Type: text/html; charset=utf-8 \n\n"
                   "<b>Hello World</b> \n"
               );

               client.send(response);
               client.shutdown(SocketShutdown.BOTH);
               client.close();

               // Sonundaki fazladan karakterleri yazdırmasın diye buffer'ı
               // yalnızca aldığını gösterecek biçimde dilimledim.
               writefln("%s",buffer[0..received]);
           }
       }
       catch(Exception error)
       {
           writefln("%s",error.msg);
       }
   }

   public void listenLoop()
   {
       httpRequests();
   }

}

void main()
{
   // Bu portları dinleyeceğiz. (Benim ortamımda 9000 kapalı.)
   ushort[] portlar = [ 8080,8085,8090,8095,9000 ];

   // Her porttan gelen isteği koşut olarak işleteceğiz
   foreach (port; parallel(portlar)) {
       auto application = new http(port);
       application.listenLoop();
   }
}

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 15, 2013

Alıntı (batuhangoksu):

>

non-blocking bir yapı yapmam lazım

Bu konular eş zamanlı (! ;) ) olarak Ceviz'de de konuşulmuştu. Şu konuyu ve özellikle şu mesajdaki programı okumanı öneririm:

http://forum.ceviz.net/d-dili/127048-ddili-socket-okuma-veri-gonderme-quotnon-blocking-i-oquot-2.html#post734381

Alıntı:

>

istekler arttıkça çökmeler ve tıkanmalar olmaması ve isteklerin hepsi kabul edip işleme alması

Ama öyle yaparsan sistem aşırı yüklenebilir. Artık bir noktada bekletmeye başlatman gerek. Buna rağmen, yukarıda bağlantısı verdiğim program da her geleni kabul ediyor. (Onun sayaçlarla nasıl önlenebileceği daha sonraki bir mesajda geçiyor.)

Alıntı:

>

multithread yada multiprogressing

std.parallelism ve std.concurrency programı multithread haline getiriyorlar zaten.

Alıntı:

>

Spawn ile gelen isteklere işçi atamak ve işçi işlemini bitirene çıktıyı gönderene kadar çalıştırmak istedim ama başarılı olamadım. Tabiki bu doğru yolmu onuda bilemedim.

Gösterdiğim programdaki işçiİşlevi() işini bitirip yanıtı veriyor ve sonlanıyor. Onun yerine sahip ile işçi arasında mesajlaşma da yapılabilir.

Alıntı:

>

8 çekirdeğimiz olduğunuz farz edelim her çekirdeği ayrı ayrı kullanarak gelen istekleri işlemci çekirdekleri üzerinde işçilerle dağıtmak.

Kullandığımız işletim sistemleri çekirdeklere doğrudan erişim sağlamıyorlar. Biz yaptığımız, iş parçacıkları başlatmaktır. Biz 8 iş parçacığı başlattığımızda belki de sistemdeki etkin 200 iş parçacığına eklenmiş oluruz. Onları çekirdeklere dağıtarak işletmek işletim sisteminin görevidir.

Yani, std.parallelism ve std.concurrency'yi kullandığında zaten amacına erişiyorsun. İstersen core.thread ile daha alt düzeylere de inebilirsin ama sonuçta std.parallelism ve std.concurrency'nin zaten yaptıklarını yapmak zorunda kalacaksın.

Alıntı:

>

9000 portuna kadar çalışıyor 9000 portunda çalışmıyor

Bütün portlar senin programına ait değil. Bazıları zaten kullanımda olabilir. Portların durumunu Linux'ta şu komutla görebilirsin:

'$ netstat -an'

Şurada da standart veya yarı standart port listesi var:

http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 16, 2013

Teşekkür ederim acehreli,

Peki performanslı ve güçlü olması neler önerirsiniz ne yapmalıyım sizce ?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 16, 2013

Benim şöyle bir önerim (alışkanlığım) var ve genelde öyle yapıyorum...

Kullandığım kodların yapabildiğimce derinine iniyorum. Yani sarma, kapsülleme veya adına her ne denildiyse araştırıyor ve sadece işime yarar kısmını alıp çıkarıyorum. Kısaca kendi sınıf ailemi (moduls) oluşturuyorum. Elbette modern derleyiciler ihtiyaç duymadıklarını zaten elemekteler ama aynı döngü içinde halledilebilecekleri tekrar uzatmanın (sağ elimizle sol kulağımızla tutmanın) manası yok.

Evet, birazcık OOP'i bozuyorum ama ondan çok uzaklaşmadan kişiselleştirilmiş bir çalışma ortamı oluşturuyorum.

Örnek vereyim:

Elinizde, konumuzla paralel giden bir uygulama olsun. Örneğin birden fazla portu koşut bir şekilde dinleyip gelen verileri aynı anda derlemesi gerekiyor. Klasik OOP mantığına göre her birim kendi üzerine düşen görevi yapar. Veriyi alır ve "nihai değerlendirme" nesnesi içine tam zamanında gönderir. Peki her port'dan gelen veri benzer şekillerde işlenecekse aynı döngü içinde ve aynı anda (burada çok çekirdekli işlemcilerin önemi ortaya çıkıyor) ama farklı muamele ile veriler işlenir. İşlenen veri yine bir sonraki adıma geçmeden evvel hemen oracıkta "nihai değerlendirmeye" sokulur. Tıpkı foreach() içinde yapabildiğimiz koşut işlemler gibi.

Bilmiyorum tam olarak derdi mi anlatabildim mi? Gerçi klasik foreach() içinde yaptığımız olayda nesneler ayn türden olması gerekir. Benim söylediğim ise biraz farklı. Daha doğrusu gerçekten de nesneler de farklı ama koşut işletilebilme yeteneğini güçlendirme odaklı. Sanırım kafiyeli olsa da biraz kafa karıştırıcı oldu...:)

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 16, 2013

Salih Dinçer bilgilendirmeniz için teşekkürler ancak kafam karıştı yazınızı okurken :)

ben sınıfımı son hali ile şu şekle getirdim ancak listenLoop içinde spawn başlatamıyorum hata veriyor neden kaynaklanır nasıl çözebilirim.

birde Thread.sleep(1.seconds); fonksiyonunu doğru yerdemi kullandım acaba ?

import std.stdio;
import std.socket;
import std.concurrency;
import std.parallelism;
import core.thread;

class http : Thread {

	char[1000] buffer;
	ushort listenPort;

	// thread(ları) başlatıyoruz
	this(){ super(&listenLoop); }

	public void httpHeaders()
	{

	}

	private void httpRequests(ushort port)
	{
		auto listener = new TcpSocket();
		auto internet = new InternetAddress(port);

		listener.setOption(SocketOptionLevel.SOCKET,SocketOption.REUSEADDR,true);
		listener.bind(internet);
		listener.listen(1);

		// Portları dinliyoruz gelen istekleri kabul ediyoruz
		// herhangi bir sorun ile karşılaşıldığında try...catch
		// ile hatayı yakalıyor ve yazdırıyoruz
		try
		{
			Thread.sleep(1.seconds);

			while(true)
			{
				auto client = listener.accept();
				auto received = client.receive(buffer);

				string response =
				(
					"HTTP/1.1 200 OK \n"
					"Content-Type: text/html; charset=utf-8 \n\n"
					"<b>Hello World</b> \n"
				);

				client.send(response);
				client.shutdown(SocketShutdown.BOTH);
				client.close();

				// Sonundaki fazladan karakterleri yazdırmasın diye buffer(ı)
				// yalnızca aldığını gösterecek biçimde bölelim.
				writefln("%s",buffer[0..received]);
			}
		}
		catch(Exception error)
		{
			writefln("%s",error.msg);
		}
	}

	public void listenLoop()
	{
		ushort[] listenPort = [8050,8080,8085];

		// Her porttan gelen isteği koşut olarak işleteceğiz
		foreach(port; parallel(listenPort))
		{
			auto tid = spawn(&httpRequests,port);
		}
	}

}

Hata mesajı

Error: template std.concurrency.spawn(F, T...)(F fn, T args) if (isSpawnable!(F, T))
cannot deduce template function from argument types !()(void delegate(ushort port), ushort)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 16, 2013

peki acehreli şöyle anlatim.

3 yada daha fazla port desteğini unutalım ozaman tek port üzerinden yürüyelim.

sınıfın içinde şöyle fonksiyonum var.

public void listenLoop(ushort port)
	{
		httpRequests(port);
	}

şimdi bu fonksiyonu şu şekilde işletiyoruz.

void main()
{
	auto application = new http();
	application.listenLoop(9000);
}

böylece listenLoop fonksiyonumuz çalışıyor listenLoop fonksiyonu ise httpRequests(); fonksiyonunu çalıştırıyor ama o anda localhost:9000 üzerinden gelen 200,500 yada 1000 tane istek var yada daha fazla bunları kabul edip engellenmeden ve hızlıca işlemesi gelen istek sayısı kadar gelen istekleri kabul edip işleyecek ve işlemi bitince sonucu verecek işçiler başlatmak yada thread lar ile dağıtmak istiyorum hangisiz sizce uygunsa yapmak istediğim bu.

sizce gelen her bir istek için işçi başlatmak mı uygun thread larla çalışmak mı

sonuçta kullanıcı gelecek domain.com/uyeler dediğinde ben uyeler sayfasını ekrana basıcam tabi bu üyeler sayfasında mysql'den veri çekme ve tasarım olacak. Sonuçta domain.com/uyeler yazdığında bu bir istek dir ve istekler IP:9000 portu üzerinden gelecek ve işlenecek.

Not:
listenLoop(); Fonksiyonu üzerinden httpRequest(); fonksiyonu başlatılıp işçilere ve threadlarla dağıtılması herşeyi tek sınıf üzerinde toplamak istiyorum dağılmadan.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 16, 2013

Önce anladığımı yazayım: foreach döngüsü bir üye işlev içinde duruyor. O üye işlevi çağırabilmek için öncelikle bir http nesnesi olması gerekir:

   // Derlemeden yazıyorum:
   auto h = new http();
   h.listenLoop()

listenLoop içinden httpRequests'in üç port için üç işçi üzerinde üç kere çağırıyorsun. httpRequests listenLoop ile aynı nesne üzerinde mi çağrılmalı? Yani, bütün işçiler örneğin, buffer ve listenPort üyelerini paylaşacaklar mı? Bence öyle olmamalı.

Dolayısıyla, http neyi temsil ediyor? Eğer tek portun sorumlusu bir sunucuyu temsil ediyorsa üç tane farklı http nesnesi olmalı.

Ek olarak, parallel ile spawn'ın bir arada kullanılmasının yararı görülmüyor. Benim daha önce gösterdiğim yalnızca parallel kullansan zaten aynı anda işleyen görevlerin oluyor. Eğer o işine yaramıyorsa onun yerine spawn'ı kullanmalısın. O da olmuyorsa Thread vs. gibi alt düzey olanaklara geçebilirsin. (parallel'in örneğini yukarıda göstermiştim. spawn'ın örneği de Ceviz'deki mesajda var.)

Onları bir yana bırakırsak şimdi derleme hatasına geçiyorum. &httpRequests tek başına bir işlev göstergesi olamaz. Bunun nedeni, onun bir üye işlev olmasıdır. Üye işlevler ise ancak elimizde bir nesne olduğunda çağrılabilirler. spawn'a httpRequests'i versek spawn "bu üye işlevi hangi nesne ile çağıracağımı bilemiyorum" der.

Onun için nesne ile üye işlevi birbirine bağlayan bir ara işlev gerekir. Araya bir de shared konusu giriyor. D'de veriler normalde paylaşılamazlar (shared değillerdir). Dolayısıyla spawn'a bir http verebilmek için öncelikle onu shared yapmak gerekiyor. Sonra işlev içinde shared'ini cast ile kaldırabiliyoruz:

void işçi(shared(http) hShared, ushort p)
{
   auto h = cast(http)hShared;
   h.httpRequests(p);
}
// ...
           auto tid = spawn(&işçi, cast(shared)this, port);

Ama dediğim gibi bu kod ya gereğinden fazlasını yapmaya çalışıyor ya da ben problemi tam olarak anlamıyorum.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 16, 2013

Teşekkür ederim acehreli,

Şimdi işçiden gelen cevaptan kastım şuydu şimdi bir istek kabul edildi gelen isteğin görevini üstlenen bir işçimiz var gelen istek(de) blogumuzda herhangi bir konunun detay sayfası böylecek gelen bilgiler neticesinde database üzerinden veriyi çekip sonra tasarımı render edip ekrana basıcak böylece işçi sonlanacaktır.

nasıl bir yapı oluşturmaya çalışıyorum diye düşünüyor olursanız D dili ile bir web projesi büyük bir portal trafiğin yoğun olduğu ve isteklerin yoğun olduğu hal böyle iken.

Sürekli gelen istekler ve girilen her sayfada gelen istek doğrultusunda Database ile iletişim ve html dosyası ile html çıktısı üretme işlemleri olacak her sayfada.

Sunucunun şişmemesi bu yaptığımız socket sınıfı verimli ve performans lı çalışmasını sağlamak istiyorum.

Hal böyle iken bu şekilde bir yapıyı ele alırsak nasıl bir yolda gitmemi önerirsiniz bu sınıf üzerinde uygulamamı istediğiniz veya önerileriniz neler olabilir.

ayrıca tek sınıf olmasından kastım socket işlemleri ve threadları başlatan birtek bu sınıf olacak sonra gelen datayı çıkan datayı farklı sınıflarla işlicem göndericem birbiri ile iletişim halinde olan bir sınıf olacak.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

« First   ‹ Prev
1 2