Сетевое программирование в .NET, страница 26

}

}

Однопроходовый алгоритм клиентского приложения настолько прост, что не нуждается в комментарии. Отметим лишь, что класс TcpClient реализует лишь самые простые функции сетевого разъема (Socket). Если вам нужно реализовать более сложное поведение, то его следует заменить на класс Socket.

¨  Постройте оба проекта и запустите сервер из окна файлового менеджера (вне студии),

¨  Запустите клиента таким же образом (из окна файлового менеджера) и убедитесь, что он получил совет дня от сервера, а сервер сообщил, что он обработал клиента,

¨  Не закрывая окно первого клиента, повторите запуск еще одного клиента и наблюдайте за сообщениями как клиента, так и сервера.

¨  Замените имя сервера на реальное (если вы его знаете), не "localhost", перекомпилируйте клиентское приложение и вновь проверьте его работу. Сервер при этом можно не останавливать.

¨  Проверьте возможность использовать другой номер порта.

Создаем приложение типа Chat

Удалите из существующего решения два последних проекта (файлы останутся невредимыми) и добавьте два новых проекта типа Visual C# Console Application. Один (с именем ChatServer) будет выполнять роль сервера, а второй (с именем ChatClient)—клиента. В сценарии типа Chat оба приложения выполняют роль как клиента, так и сервера, и тем не менее одно из них должно быть модератором сессии (это калька с английского: председатель заседания). Именно его надо запустить в первую очередь, в нем надо создать сетевой разъем и начать прослушивание сети. При появлении клиента модератор создает новый, второй разъем (при этом можно просто заменить ссылку), по которому и будет происходить обмен. Следующие рисунки иллюстрируют сказанное.

             

Левое окно принадлежит серверному проекту, в нем вы видите, что прослушивание сети происходит с помощью разъема, начальный конец которого LocalEndPoint = 169.254.13.32:27015 (удаленный конец соединения отсутствует). После подключения клиента с именем Red разъем меняется, его концевым узлом соединения становится RemoteEndPoint=169.254.13.32:1068, а начальный конец не изменяется. Номер порта (1068) для клиентского приложения выбран системой автоматически. В следующий раз он может быть другим. Рассмотрим код серверного приложения. Некоторые его фрагменты вы должны написать самостоятельно.

class ChatServer

{

  private static string nick; // Nickname пользователя

  private static int port;      // Номер порта локальной машины

  public static void GetNick()

  {

    // Запросите строку текста (nickname) и обрежте ее, если она длиннее 15 символов

    nick = hostName + "." + nick + ": ";  // Образуем сложный nick

  }

  private static void Main()

  {

    port = 27015;

    hostName = Dns.GetHostName();

    GetNick();

    Chat();

  }

  private static void Chat()

  {

    try

    {

      Socket socket = // Создайте Socket

      IPHostEntry host = Dns.GetHostEntry (hostName);

      IPEndPoint point = new IPEndPoint (// Задайте параметры);

      // Привяжите разъем socket к начальному концу point и заставьте его слушать сеть

      Console.WriteLine("\nMy address: {0}\nWaiting for a client to connect...", point);

      socket = // Ждите, когда клиент подключится

      string client = ((IPEndPoint) socket.RemoteEndPoint).ToString();

      Console.WriteLine("I am connected to {0}\n", client);

      while (true)

      {

        byte[] msg = new byte[128];

        int nBytes = // Получите сообщение из разъема и поместите его в msg

        string

          data = Encoding.ASCII.GetString (msg, 0, nBytes),

          user = data.Substring (0, data.IndexOf(':') + 1);

        if (// В сообщении есть текст ": @")

          Console.WriteLine (user + " said good-bye");

        Console.Write (data.Substring (data.IndexOf('.') + 1) + "\n: ");

        data = // Запросите у пользователя строку с ответным текстом

        if (Ответ начинается с "@")

        {