C# - Programok közötti kommunikáció TCP/IP-n keresztül

forráskód letöltése
Ha egy TCP/IP hálózat két tetszőleges pontján lévő számítógépen futó alkalmazások között szükség lenne arra, hogy azok kommunikáljanak egymással, akkor ennek módját a mellékelt példából megismerhetjük. A két programnak persze nem feltétlenül kell különböző gépeken lenniük, működtethető úgy is, hogy e két program egy gépen fut.
A mellékelt példa kipróbálásához fordítsuk le mind a két alkalmazást, futtassuk a szervert, kattintsuk a Start gombra, majd csak ezek után próbáljunk kapcsolódni a kliensen keresztül a szerverhez.
A két program közül kezdjük most azzal, amelyet szerver alkalmazásnak nevezünk ki és azt a feladatot szánjuk neki, hogy figyelje az 5000-es portot és ha megtörténik a kliens oldali kapcsolat felvétel, akkor küldje el a kliensnek az aktuális dátumot és időt sztringként. Mellékelt példában ezt a programot a TCPServer könyvtárban találjuk.
Ha figyelnünk kell egy portot programból, akkor ehhez a TcpListener osztályt használhatjuk fel.
Ennek az osztálynak a konstruktorában adhatjuk át, hogy melyik legyen ez a port.
    private void button1_Click(object sender, System.EventArgs e)
    {
      TcpListener tl = new TcpListener(5000);
A port figyeltetését az osztály Start függvényének hívásával kezdeményezhetjük.
      tl.Start();
Indítás után, ha meghívjuk az AcceptSocket függvényt, akkor ezzel a programunk futása felfüggesztésre kerül, amíg nem érkezik kapcsolatfelvétel az adott porton keresztül. Ezért célszerűbb ilyen esetben egy külön szálon futtatni a TCP port figyelését és kiszolgálást, hogy alkalmazásunkat a felhasználó ettől függetlenül is használhassa.
Amikor megtörtént a kapcsolatfelvétel, akkor létrejön egy Socket osztály példánya, melyet visszatérési értékként kapunk meg. A későbbiek folyamán ezt használhatjuk a klienssel történő kommunikáció során.
      Socket s = tl.AcceptSocket();      
Amikor megtörtént a kapcsolatfelvétel, akkor ezen a ponton fut tovább a programunk. Itt letároljuk egy sztringbe az aktuális dátumot és időt.
      string str = cDateTime.Now.ToString();
Mivel a TCP/IP-n keresztül bájtokat tudunk elküldeni, így az imént létrehozott sztringünkből célszerű egy olyan tömböt létrehoznunk, mely bájtokat tartalmaz. Ehhez az Encoding osztály statikus ASCII property-jén keresztül elérhetünk egy ASCIIEncoding osztályt, melynek van egy GetBytes függvénye, amelynek paraméterként átadva egy karakter tömböt átalakítja azt ASCII kódolással egy bájtokat tartalmazó tömbbé és ezt visszatérési értékként szolgáltatja. Paraméterként úgy tudunk a sztring típusunkból egy karaktertömböt átadni, hogy meghívjuk a sztring ToCharArray függvényét.
      Byte[] b = Encoding.ASCII.GetBytes(str.ToCharArray());
Most, hogy a sztringből létrehoztunk egy bájt tömböt, már csak meg kell hívnunk a Socket osztály Send függvényét, mellyel képesek vagyunk adatot küldeni a kliens felé. A Send függvény első paraméterében kell átadnunk a bájtokból álló tömböt. Második paraméterében pedig a tömbben lévő bájtok számát kell megadnunk.
      s.Send(b, b.Length, SocketFlags.None);
Az időpont átadása után le is állítjuk az 5000-es port figyelését a Stop függvény hívásával.
      tl.Stop();
    }
Nézzük most a kliens program elkészítésének módját, melyet a TCPClient könyvtárban találunk. Kliens oldalon a TcpClient osztály segíti munkánkat. Ezt használva képesek vagyunk egyszerűen kapcsolódni egy szerverhez az adott porton keresztül.
    private void button1_Click(object sender, System.EventArgs e)
    {
      TcpClient tc = new TcpClient();
      Byte[] buf = new Byte[50];
      try
      {
Kapcsolódáshoz most meg kell adnunk a távoli gép host nevét valamint második paraméterként a port számát. Amennyiben ugyanazon a gépen futtatjuk a szervert és a klienst is, úgy használhatjuk host névnél a localhost szót.
        tc.Connect(textBox1.Text, 5000);
A kapcsolat felvétel után adatok olvasásához a portról a TcpClient osztály GetStream függvénye használható. Ez egy NetworkStream osztályt ad vissza.
        NetworkStream s = tc.GetStream();
Ebből a stream-ből a Read függvény fogja szolgáltatni a kiolvasott adatot. Ehhez szükségünk lesz egy bájtokat tartalmazó tömbre, majd szintén az Encoding ASCII property-jén keresztül elérhető ASCIIEncoding osztályra. Ennek GetString függvénye fogja átalakítani sztringgé a kapott adatokat.
        s.Read(buf, 0, buf.Length);
        label1.Text = Encoding.ASCII.GetString(buf);
Az adatok olvasása után már csak le kell zárnunk a kapcsolatot a Close függvény meghívásával.
        tc.Close();
      }
      catch (Exception ex)
      {
        label1.Text = ex.Message;
      }
    }