Sieci komputerowe — ćwiczenia 5


Temat zajęć: Programowanie gniazd — C#.

Literatura:

Uwaga:
Poniższe programy zostały przetestowane na platformie mono (monodevelop), powinny jednak działać bez problemu w Visual Studio NET.


 Przykład 1

Przykładowy program serwera na platformie NET.

Plikc5s.cs pobierz
using System;
using System.Threading;
using System.Text;
using System.Net;
using System.Net.Sockets;

public class Server {
    // Przekazuje stan
    internal class StateObject {
        internal byte[] sBuffer;
        internal Socket sSocket;
        internal StateObject(int size, Socket sock){
            sBuffer = new byte[size];
            sSocket = sock;
        }
    }
    static void Main(){
        IPEndPoint ipEndpoint =
          new IPEndPoint(IPAddress.Any, 1800);

        Socket listenSocket =
          new Socket(AddressFamily.InterNetwork,
                     SocketType.Stream,
                     ProtocolType.Tcp);

        listenSocket.Bind(ipEndpoint);
        listenSocket.Listen(1);

        // Zamiast blokowac podaje metode do wywolania w przypadku
        // polaczenia
        IAsyncResult asyncAccept = listenSocket.BeginAccept(
          new AsyncCallback(Server.acceptCallback),
          listenSocket);

        Console.Write("Trwa laczenie.");
        if (writeDot(asyncAccept) == true){
            Thread.Sleep(3000);
        }
    }

    public static void acceptCallback(IAsyncResult asyncAccept){
        Socket listenSocket = (Socket)asyncAccept.AsyncState;
        Socket serverSocket =
          listenSocket.EndAccept(asyncAccept);

        if (serverSocket.Connected == false){
            Console.WriteLine(".serwer nie polaczony.");
            return;
        }
        else Console.WriteLine(".serwer polaczony.");

        listenSocket.Close();

        StateObject stateObject =
          new StateObject(16, serverSocket);

        // Przekazujemy StateObject, bo potrzeba zarowno gniazda,
        // jak i bufora
        IAsyncResult asyncReceive =
          serverSocket.BeginReceive(
            stateObject.sBuffer,
            0,
            stateObject.sBuffer.Length,
            SocketFlags.None,
            new AsyncCallback(receiveCallback),
            stateObject);

        Console.Write("Odbieranie danych.");
        writeDot(asyncReceive);
    }

    public static void receiveCallback(IAsyncResult asyncReceive){
        StateObject stateObject =
          (StateObject)asyncReceive.AsyncState;
        int bytesReceived =
          stateObject.sSocket.EndReceive(asyncReceive);

        Console.WriteLine(
          ".Otrzymano {0} bajtow: {1}",
          bytesReceived.ToString(),
          Encoding.ASCII.GetString(stateObject.sBuffer));

        byte[] sendBuffer =
          Encoding.ASCII.GetBytes("Goodbye");
        IAsyncResult asyncSend =
          stateObject.sSocket.BeginSend(
            sendBuffer,
            0,
            sendBuffer.Length,
            SocketFlags.None,
            new AsyncCallback(sendCallback),
            stateObject.sSocket);

        Console.Write("Wysylanie odpowiedzi.");
        writeDot(asyncSend);
    }

    public static void sendCallback(IAsyncResult asyncSend){
        Socket serverSocket = (Socket)asyncSend.AsyncState;
        int bytesSent = serverSocket.EndSend(asyncSend);
        Console.WriteLine(
          ".Wyslano {0} bajtow.{1}{1}Zamykanie gniazd.",
          bytesSent.ToString(),
          Environment.NewLine);

        serverSocket.Shutdown(SocketShutdown.Both);
        serverSocket.Close();
    }

    internal static bool writeDot(IAsyncResult ar){
        int i = 0;
        while (ar.IsCompleted == false){
            if (i++ > 40){
                Console.WriteLine("Przekroczony czas oczekiwania.");
                return false;
            }
            Console.Write(".");
            Thread.Sleep(500);
        }
        return true;
    }
}

 Przykład2

Przykladowy kod klienta w C#.

Plik c5c.cs pobierz
using System;
using System.Threading;
using System.Text;
using System.Net;
using System.Net.Sockets;

public class Client {

    class StateObject {
        internal byte[] sBuffer;
        internal Socket sSocket;
        internal StateObject(int size, Socket sock) {
            sBuffer = new byte[size];
            sSocket = sock;
        }
    }

    static void Main(string[] argHostName) {
        if (argHostName.Length > 0) {
            IPAddress ipAddress =
                //Dns.Resolve(argHostName[0]).AddressList[0]; (przestarzałe)
              Dns.GetHostEntry(argHostName[0]).AddressList[0];

            IPEndPoint ipEndpoint =
              new IPEndPoint(ipAddress, 1800);

            Socket clientSocket = new Socket(
              AddressFamily.InterNetwork,
              SocketType.Stream,
              ProtocolType.Tcp);

            IAsyncResult asyncConnect = clientSocket.BeginConnect(
              ipEndpoint,
              new AsyncCallback(connectCallback),
              clientSocket);

            Console.Write("Lacze sie.");
            if (writeDot(asyncConnect) == true) {
                Thread.Sleep(3000);
            }
        }
    }

    public static void connectCallback(IAsyncResult asyncConnect) {
        Socket clientSocket =
          (Socket)asyncConnect.AsyncState;
        clientSocket.EndConnect(asyncConnect);

        if (clientSocket.Connected == false) {
            Console.WriteLine(".klient nie polaczony.");
            return;
        }
        else Console.WriteLine(".klient polaczony.");

        byte[] sendBuffer = Encoding.ASCII.GetBytes("Hello");
        IAsyncResult asyncSend = clientSocket.BeginSend(
          sendBuffer,
          0,
          sendBuffer.Length,
          SocketFlags.None,
          new AsyncCallback(sendCallback),
          clientSocket);

        Console.Write("Wysylanie danych.");
        writeDot(asyncSend);
    }

    public static void sendCallback(IAsyncResult asyncSend) {
        Socket clientSocket = (Socket)asyncSend.AsyncState;
        int bytesSent = clientSocket.EndSend(asyncSend);
        Console.WriteLine(
          ".Wyslano {0} bajtow.",
          bytesSent.ToString());

        StateObject stateObject =
          new StateObject(16, clientSocket);

        IAsyncResult asyncReceive =
          clientSocket.BeginReceive(
            stateObject.sBuffer,
            0,
            stateObject.sBuffer.Length,
            SocketFlags.None,
            new AsyncCallback(receiveCallback),
            stateObject);

        Console.Write("Odbieranie odpowiedzi serwera.");
        writeDot(asyncReceive);
    }

    public static void receiveCallback(IAsyncResult asyncReceive) {
        StateObject stateObject =
         (StateObject)asyncReceive.AsyncState;

        int bytesReceived =
          stateObject.sSocket.EndReceive(asyncReceive);

        Console.WriteLine(
          ".Otrzymano {0} bajtow: {1}{2}{2}Zamykanie polaczenia.",
          bytesReceived.ToString(),
          Encoding.ASCII.GetString(stateObject.sBuffer),
          Environment.NewLine);

        stateObject.sSocket.Shutdown(SocketShutdown.Both);
        stateObject.sSocket.Close();
    }

    internal static bool writeDot(IAsyncResult ar) {
        int i = 0;
        while (ar.IsCompleted == false) {
            if (i++ > 20) {
                Console.WriteLine("Przekroczono czas polaczenia z serwerem.");
                return false;
            }
            Console.Write(".");
            Thread.Sleep(100);
        }
        return true;
    }
}

Zadanie 1

Napisać program realizujący to samo zadanie, wykorzystujący protokół UDP.

Zadanie 2

Rozszerzyć działanie programów podanych w przykładach o możliwość wysyłania wielu wiadomości.