Запустите пример на выполнение проанализируйте его вывод, а затем замените IP-адрес испытуемого узла. Вместо сетевого имени компьютера (Dns.GetHostName()) вставьте имя заглушки ("localhost") и сравните результаты. Убедитесь. что кроме IP-адреса, изменяется номер порта, хранящийся в свойстве LocalEndPoint.
Пояснения. Ссылка на SocketAddress добывается с помощью метода Serialize класса IPEndPoint. Строковое представление (ToString()) объекта SocketAddress производит вывод, логика которого становится ясной только после того, как выведен имеющийся в этом классе специальный буфер.
Класс SocketAddress имеет индексатор, который дает доступ к отдельным байтам своего буфера. Мы используем его для выбора первого байта (AddressFamily) и видим, что он равен константе AF_INET, которую мы использовали ранее в приложении WinSockClient. Ниже выведен весь буфер и мы видим, что его первые 2 байта содержат AddressFamily (они выведены выше в виде строки InterNetwork), третий и четвертый байты хранят номер порта, далее следует IP-адрес. Число 16 в строковом представлении означают размер буфера.
Для более близкого знакомства с классом Socket добавьте к существующему решению два новых проекта типа Visual C# Console Application. Один (с именем SocketServer) будет выполнять роль сервера услуг, а второй (с именем SocketClient) будет пользоваться этими услугами.
Услуга сервера состоит в выдаче полезных советов (Tip of the day). Такой сценарий можно использовать в разных ситуациях: выдача текущего прогноза погоды, биржевых котировок акций и т. д. Заметьте, что связь носит односторонний характер. Сервер не интересуется, получил-ли клиент его сообщение, или нет, он не ждет от него подтверждения. Единственной его функцией является реакция на каждое новое соединение и выдача каждому новому клиенту случайно выбранного совета.
class SocketServer
{
public static void Main()
{
string[] tips =
{
"Socket class methods simply marshal data\r\n" +
"into their native Win32 counterparts.",
"Socket supports two basic modes\r\n" +
"synchronous and asynchronous.",
"In synchronous mode, Send and Receive\r\n" +
"wait until the operation completes",
"In asynchronous mode, BeginSend and\r\n" +
"BeginReceive return immediately.",
"Applications can use TCP and UDP services with\r\n" +
"the TcpClient, TcpListener, and UdpClient classes.",
"Classes: TcpListener, TcpClient and UdpClient\r\n" +
"use the synchronous methods of the Socket class",
"TcpListener, TcpClient and UdpClientto provide\r\n" +
"simple access to network services without\r\n" +
"the overhead of maintaining state",
};
Random r = new Random (DateTime.Now.Millisecond);
Socket socket = null;
try
{
int port = 27015;
TcpListener listener = new TcpListener (IPAddress.Any, port); // Listen on port 27015
listener.Start();
Console.WriteLine("Waiting for clients to connect to port: {0}\n" +
"Press Ctrl+c to Quit...", port);
while (true)
{
socket = listener.AcceptSocket(); // Приложение замораживается, если очередь запросов пуста
IPEndPoint
local = listener.LocalEndpoint as IPEndPoint,
remote = socket.RemoteEndPoint as IPEndPoint;
Console.WriteLine("\nServing client: {0} on port: {1}",
remote.ToString(), local.Port.ToString());
int id = r.Next (tips.Length);
byte[] msg = Encoding.ASCII.GetBytes (tips[id].ToCharArray());
int bytes = socket.Send (msg, msg.Length, 0);
Console.WriteLine("\nSent {0} bytes: \n-->{1}", bytes, tips[id]);
}
}
catch (SocketException ex)
{
Console.WriteLine((ex.ErrorCode == 10048 ?
"Another server is listening on this port." : ex.Message));
}
finally
{
if (socket != null)
{
socket.Shutdown (SocketShutdown.Send);
socket.Close();
}
}
}
}
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.