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

          socket.Send (Encoding.ASCII.GetBytes (nick + "Moderator must log off, Sorry"));

          break;

        }

        data = nick + data;

        msg = Encoding.ASCII.GetBytes (data);

        nBytes = // Отправьте сообщение

      }

      Console.WriteLine("\n\nLeaving");

      socket.Shutdown(SocketShutdown.Both);

      socket.Close();

    }

    catch (Exception ex) { Console.WriteLine(ex.Message); }

    Console.ReadKey(true);

  }

}

Новый разъем (или соединение) создается в недрах метода Accept класса Socket, который, как вы помните, блокирует серверное приложение до тех пор, пока не подключится клиент, который и образует новое соединение. Далее запускается цикл обмена сообщениями, прерывающийся сигналом завершения сессии.

В качестве этого сигнала мы выбрали символ '@'. Ввод этого символа одним из адресатов (как видно из рисунков) означает, что он хочет закончить разговор. Другой абонент может (а в нашем сценарии должен) воспринять этот символ, как сигнал к окончанию сессии. Отладьте серверное приложение, оно должно компилироваться без ошибок, а при запуске ждать клиента.

Теперь перейдем к разработке клиентского приложения. Оно также должно создать сетевой разъем и подключиться (метод Connect) к серверу, зная номер порта на котором тот работает. О номере порта клиент и сервер должны договориться заранее. Затем клиент входит в псевдобесконечный цикл типа Send-Receive, который прерывается, когда придет сигнал к окончанию сессии. Мы уже выбрали его в серверном приложении, и им является символ '@'. Ниже приведен каркас клиентского проекта, вы должны доработать его код.

class ChatClient

{

  private static string nick;

   // Вставьте метод GetNick()

  private static void Main()

  {

    GetNick();

    try

    {

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

      IPHostEntry host = Dns.GetHostEntry(имя сервера);

      IPEndPoint point = new IPEndPoint (// Задайте 2 параметра (IPAdress и порт)

      // Подключите разъем к точке point

      Console.WriteLine("Connected to {0}\n", socket.RemoteEndPoint.ToString());

      nick = Dns.GetHostName() + "." + nick + ": ";

      while (true)

      {

        Console.Write(": ");

        string data = // Пользователь вводит текст сообщения

        data = nick + data;

        byte[] msg = Encoding.ASCII.GetBytes (data);

        int nBytes = // Отправьте сообщение

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

          break;

        msg = // Создайте буфер на 128 байт

        nBytes = socket.Receive(msg);

        if (nBytes <= 0)

          throw new Exception (string.Format ("Received: {0} bytes", nBytes));

        data = // Преобразуйте msg в строку текста

        Console.WriteLine (// Выведите строку отрезав адрес, но оставив nick

      }

      Console.WriteLine("\n\nLeaving");

      socket.Shutdown (SocketShutdown.Both);

      socket.Close();

    }

    catch (Exception ex)

    {

      Console.WriteLine(ex.Message);

    }

    Console.ReadKey(true);

  }

}

После отладки синтаксиса клиентского приложения, запустите сервер, затем клиента и скорректируйте работу всей системы. Признаюсь, что я потратил на это довольно много времени, так как не понимал, что после подключения клиента, разъем серверного приложения должен полностью измениться. Мы заменяем первоначальный объект на тот, что возвращает метод Accept. Внимательный читатель, наверное поймет (или почувсвует), что такое решение вряд-ли сработает, если модератор будет работать с произвольным числом клиентов.

Реализуем сценарий: один сервер—много клиентов

Попробуем усложнить сценарий и организовать связь между сервером и произвольным количеством клиентов. При этом сервер командует парадом, он по очереди обслучивает всех клиентов, но клиенты не знают друг друга. Только сервер видит всех клиентов, а последние даже не подозревают о существовании друг друга. Существующий вариант собеседования двух абонентов не удастся преобразовать в разговор трех и более абонентов сети, используя лишь один сетевой разъем и простые, косметические добавки к коду.