Sieci komputerowe — ćwiczenia 5
Temat zajęć: Programowanie gniazd — C#.
Literatura:
- Dokumentacja gniazd w C#
- R. Stevens, "Biblia TCP/IP" (tom 1 - Protokoły i tom 2 - Implementacje)
- Dokumenty RFC wersja on-line
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 pobierzusing 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 pobierzusing 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.
Begin main navigation