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.