C# tcp_server uygulaması

Başlatan yamak, 19 Ocak 2012, 23:28:54

yamak

C# da tcp_server uygulaması yapmaya çalışıyorum. Messenger tarzı bişey olacak. Client lar için bir program yazılacak sonra. Sonra clientlar birbirleriyle haberleşecek.Bir client diğerine bir mesaj göndermek istediğinde ilk olarak yolladığı mesaj server a gidecek server da yönlendirmeyi yapacak. Şimdi benim sorum şöyle. Server tarafındaki programda her bağlanan client için yeni bir thread mı oluşturmam gerekiyo. Örnek verecek olursam:
void tcp_client()
{
...
...
..
}
gibi bir fonksiyonun var bu fonksiyon da client larda gelen mesajlar okunup gerekli kişeye yönlendirme yapılıyo. Şimdi ben böyle bi fonksiyonu herbir kullanıcı için yeni bir thread oluşturup her kullanıcıdan gelen verileri paralel mi okumam gerekiyo. Ya da bu işin raconu böyle mi? (Eğer böyle ise bunu nasıl yapacam. Herbir kullanıcı için ayrı bir fonksiyon mu yazmam gerekiyo?) Ya da atıyorum her 5 client için ayrı bir thread mı oluşturmam gerekiyo. Bu konuda tecrübesi, bilgisi olan arkadaşlar  yardımcı olabilirler mi?

aeki

aslında yazılım gelistirdiginiz otamla ilgili bir bilgim yok  ama,bircok kullanıcılı mesajlasma sistemleri sunucudaki veritanına bakıp bana bir posta varmı diye bakıyor.okuduysa okundu alanını degistiriyor.genel mantık bu.devamlı sunucuya istekde bulunuyorlar.ben bunu yüksek seviyede yaptım sizn bulundugunuz ortamda nasıl yapılır tam bilemiyecem ama belki fikir verir

RcALTIN

#2
Alıntı yapılan: yamak - 19 Ocak 2012, 23:28:54
C# da tcp_server uygulaması yapmaya çalışıyorum. Messenger tarzı bişey olacak. Client lar için bir program yazılacak sonra. Sonra clientlar birbirleriyle haberleşecek.Bir client diğerine bir mesaj göndermek istediğinde ilk olarak yolladığı mesaj server a gidecek server da yönlendirmeyi yapacak. Şimdi benim sorum şöyle. Server tarafındaki programda her bağlanan client için yeni bir thread mı oluşturmam gerekiyo. Örnek verecek olursam:
void tcp_client()
{
...
...
..
}
gibi bir fonksiyonun var bu fonksiyon da client larda gelen mesajlar okunup gerekli kişeye yönlendirme yapılıyo. Şimdi ben böyle bi fonksiyonu herbir kullanıcı için yeni bir thread oluşturup her kullanıcıdan gelen verileri paralel mi okumam gerekiyo. Ya da bu işin raconu böyle mi? (Eğer böyle ise bunu nasıl yapacam. Herbir kullanıcı için ayrı bir fonksiyon mu yazmam gerekiyo?) Ya da atıyorum her 5 client için ayrı bir thread mı oluşturmam gerekiyo. Bu konuda tecrübesi, bilgisi olan arkadaşlar  yardımcı olabilirler mi?

farklı yöntemi var mı bilmiyorum ancak thread kullanılarak yapılabilir. bir tane fonksiyon kullanacaksınız, her client bağlandığında da aynı fonksiyonu kullanan yeni bir kanal örneklendirip başlatacaksınız.

biraz kod ile ifade etmek gerekirse :
    public class TcpSinifi
    {
        static readonly object lockObject = new object();
        Thread thTcpSrv, thTcpCli;
        TcpListener ts;
        
        //constructor 
        public TcpSinifi(IPAddress ip, int port)
        {
            ts = new TcpListener(ip, port);

            thTcpSrv = new Thread(new ThreadStart(TcpServer));
            thTcpSrv.IsBackground = true;
            thTcpSrv.Start();
        }

        private void TcpServer()
        {
            ts.Start();

            //tcp server ana döngüsü
            while (true)
            {
                TcpClient cli = ts.AcceptTcpClient(); //birisi bağlanana kadar bekle ve bağlantıyı kabul et
                thTcpCli = new Thread(new ParameterizedThreadStart(TcpClient)); //yeni kanal oluştur
                thTcpCli.IsBackground = true;
                thTcpCli.Start(cli); //bağlananı parametre olarak gönder ve kanalı başlat
            }
        }

        //bağlanan her client için bu fonksiyon yeni bir kanal olarak başlıyor, parametreye TcpClient nesnesi aktarılıyor
        private void TcpClient(object p)
        {
            TcpClient cli = (TcpClient)p;

            Timer timerCallBack = new Timer(new TimerCallback(TcpClientCallBack), cli, 0, 1000);

            Socket sock = cli.Client;
            string ip = ((IPEndPoint)sock.RemoteEndPoint).Address.ToString();
            string port = ((IPEndPoint)sock.RemoteEndPoint).Port.ToString();

            cli.ReceiveTimeout = 5000;
            //cli.SendTimeout = 55000;

            Console.WriteLine("#İstemci bağlandı(" + ip + ")#");
            
            NetworkStream ns = cli.GetStream();

            Random r = new Random();
            while (cli.Connected)
            {
                try
                {
                    //tamponda alınabilir veri varsa oku
                    if (ns.DataAvailable) 
                    {
                        byte[] buffer = new byte[1024];
                        int bCount = ns.Read(buffer, 0, buffer.Length); //gelen veri buffer dizisine doldu , bCount değişkeni ne kadar byte geldiğini tutuyor
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Hata : " + ex.Message);
                }
            }
            timerCallBack.Dispose();
            Console.WriteLine("#İstemci ayrıldı(" + ip + ")#");
        }

        //yukarıda tanımlanan timer, belirli aralıklarla zaman bilgisi göndermek için bu fonksiyonu kullanıyor
        //parametreyle gelen TcpClient nesnesine, periyodik olarak tarih-zaman bilgisi gönderiliyor
        private void TcpClientCallBack(object p)
        {
            TcpClient cli = (TcpClient)p;
            NetworkStream ns = cli.GetStream();

            WriteToClient(new UTF8Encoding().GetBytes(DateTime.Now.ToString()), ns);
        }

        //çok kanallı çalışıldığından, lock mekanizması kullanabilmek için yazmayı bu metodla yapıyorum
        private void WriteToClient(byte[] buffer, NetworkStream stream)
        {
            lock (lockObject)
            {
                try
                {
                    stream.Write(buffer, 0, buffer.Length);
                    stream.Flush();
                }
                catch (Exception ex)
                {

                }
            }
        }
}


bu kod parçası geliştirmekte olduğum bir projemde bir class'a ait, bayağı kırpıp/yeniden düzenledim ama kalıntılar kalmış olabilir. timer kısmını pediyodik işleri nasıl yapabileceğini anlayabilmeniz için silmedim...

düzeltme: önemli bir fonksiyonu eklememişim
KİMSEYİ ENGELLEDİĞİM YOK, ÖZEL İLETİ DEVRE DIŞI !

RcALTIN

bu forumda başka üyelerle de defalarca karşılaştığım çok büyük bir sıkıntı var. insanlar yardım istiyor, birilerince yardım ediliyor fakat nedense hiç bir geri dönüş yapılmadan konu ölüyor... sonra, yardım eden kişi kendi mesaj geçmişini incelerken durum gözüne batıyor ve geri dönüş yapmaya değmeyecek kadar anlamsız bir şeyler mi yazdığından yoksa adam yerine konulmadığından mı bir geri dönüş olmamasını sorgulamaya başlıyor. neden böyle? bir örneğe karşı "şu yönden eksiği var" veya "evet bu işimi gördü tamamdır" demek çok mu zor anlayamıyorum ben.
KİMSEYİ ENGELLEDİĞİM YOK, ÖZEL İLETİ DEVRE DIŞI !

yamak

Arakadaşım haklısın geri dönüş yapmam gerekirdi. Fakat şu an memlektteyim ve evde internet yok telefondan girebiliyorum ancak. Cevabınız için teşekkür ederim.

ogunduru

TCP Server konusunda en doğru çözüm ThreadSpool nesnesi kullanımı ile mümkündür.
ThreadSpool anahtar kelimesi ile arama yaparak Microsoft kaynaklarında önemli bilgilere ve örneklere ulaşabilirsiniz.
Matematik Mühendisi bir hobi elektronikçi