Пишем локальный чат на C#

ПРИМЕЧАНИЕ - http://xnim.ru/blog?id=28 здесь - более подробное объяснение темы - как создать локальный чат на C#
http://xnim.ru/blog?id=29 здесь - более объяснение темы - как реализовать передачу файлов на C#


Последнее время на форумах часто встречаю записи, типа: "Как создать чат в локальной сети?", "Как отправить сообщение с одного ПК на другой посредством C#?".
Поэтому решил немного осветить данный вопрос и написать небольшую статью на тему: "Создаем чат в локальной сети". Сразу оговорюсь - если у принимающей стороны нет прокси\\роутеров и т.п., то отправлять сообщение получиться и им (при условии, что и там и там работает программа)
Поэтому начнем.
Мы будем создавать приложение, которое позволит как принимать, так и отправлять сообщения - т.е. в одной программе совмещаем клиент и сервер.
Итак, создаем новое приложение, кидаем на форму кнопку "отправить", текстовое поле для IP адреса (Я назвал свое IPConnect), второе текстовое поле для написания сообщения(ChatMessage) и текстовое поле для отображения диалога(ChatBox).
Для начала, думаю есть смысл описать работу приложения как "сервер" - для приема сообщений. Сообщения необходимо постоянно "прослушивать", поэтому работать функция будет в отдельном потоке.
Для начала в класс формы добавим переменные -
  1. //Прослушивает подключения от TCP-клиентов сети
  2. TcpListener TCPMesLis;
  3. //Интерфейс сокетов
  4. Socket MSocket;
  5. //Обеспечивает базовый поток данных для доступа к сети
  6. NetworkStream MNetStrm;

This code was highlighted with code.xnim.ru


Теперь реализуем метод, который будем запускать в отдельном потоке. Его задачей будет прослушивание определенного порта (в своем случае я выбрал 7000) и обработкой входящего сообщения.
Каким будет порядок действий?
Определим его следующим образом:

  1. Начинаем прослушку порта

  2. В цикле:

  3. Принимаем запрос на подключение

  4. Связываем NetworkStream с Socket

  5. Считываем сообщение из NetworkStream

  6. Сохраняем сообщение в текстовое окно



В виде кода это выглядит следующим образом:
  1. void MessageServer()
  2.    {
  3.     TCPMesLis = new TcpListener(7000);// открываем порт
  4.     TCPMesLis.Start();// начинаем сканирование
  5.         
  6.    while (true)
  7.     {
  8.      try
  9.       {
  10.        MSocket = TCPMesLis.AcceptSocket();//Принимаем запрос на подключение
  11.        MNetStrm = new NetworkStream(MSocket);//связываем
  12.       
  13.        byte[ ] buffer = new byte[ 1024];//считываем
  14.        MNetStrm.Read(buffer, 0 , 1024 );
  15.        MemoryStream ms = new MemoryStream(buffer);
  16.       
  17.       
  18.        tempRichText.LoadFile(ms, RichTextBoxStreamType.RichText);//сохраняем в текстовое поле (временное )
  19.        //Его можно объявить и сразу проинициализировать в переменных класса, как RichTextBox tempRichText = new RichTextBox();
  20.        tempRichText.Text += ''\
    ''
    ;//Добавляем перевод строки
  21.        ChatBox.Text += tempRichText.Text;//Выводим сообщение
  22.        /* еще один способ получить информацию.
  23.        * В этом случае необходимо учесть, что к текстовой информации может
  24.        * добавляться информация о стиле тексте, шрифте и т.д.*/
  25.        for (int i = 0 ; i < buffer.Length; i++)
  26.         ChatBox.Text += (char)buffer[i];
  27.      }
  28.          catch (Exception) { }//сюда можно внести обработку исключений.
  29.     }
  30.    }

This code was highlighted with code.xnim.ru


Серверная часть готова. Ее вызвать можно, к примеру следующим образом:
Thread MThrd = new Thread(new System.Threading.ThreadStart(MessageServer));
    MThrd.Start();//запускае поток на исполнение.

This code was highlighted with code.xnim.ru


Переходим к клиентской части -
Клиентская часть предполагает -

  1. С помощью TCPClient подключаемся к заданному в IPConnect IP-адресу и выбранному ранее порту 7000

  2. Перевести сообщение в поток и отправить с помощью NetworkStream

  3. Закрыть подключение



Описывается, равно как и реализуется это достаточно просто -
  1. private void Send_Click(object sender, EventArgs e)
  2.    {
  3.     try
  4.      {
  5.        //Предоставляет клиентские подключения для сетевых служб протокола TCP.
  6.      TcpClient Client;
  7.      Client = new TcpClient(IPConnect.Text, 7000 );//открыли подключение
  8.      NetworkStream ClientMNetworkS = Client.GetStream();//получили поток (для записи)
  9.      MemoryStream ClientMemoryS = new MemoryStream();
  10.      ChatBox.Text += "\
    Вы:"
    + ChatMessage.Text;//скопировали в чат-окно свое сообщение
  11.      //сюда можно добавить сопроводительную информацию (с какого IP было отправлено, либо с какой учетной записи и т.д.)
  12.      //подобные изменения проводятся с ChatMessage
  13.      ChatMessage.SaveFile(ClientMemoryS, RichTextBoxStreamType.RichText);//сохранили информацию в MemoryStream
  14.      ClientMNetworkS.Write(ClientMemoryS.ToArray(), 0 , ClientMemoryS.ToArray().Length);//записали
  15.      //закрываем потоки, подключения
  16.      ClientMNetworkS.Close();
  17.      Client.Close();
  18.      //отправленное сообщение очищаем
  19.      ChatMessage.Clear();
  20.     }
  21.     catch (Exception ex)
  22.     {//если порт не прослушивается на сервере (не было ответа), либо произошла стороння ситуация - уведомим ошибкой
  23.      MessageBox.Show(ex.Message);
  24.     }
  25.    }

This code was highlighted with code.xnim.ru


Основной функционал чата на этом реализован.
Остается добавить создание адресной книги, внести поддержку передачи файлов, сделать передачу информации удобней (отправка при нажати Enter и подобные плюшки), сопроводить текст сообщения "сопроводительной информацией" и получится добротный чат-клиент ;-)
Надеюсь, данная статья помогла вам обрести "азы" в написании подобного рода приложения. Эта программа,к примеру, использует "выдержки кода" из данной статьи.


P.S. В программе используются следующие пространства имен (добавленные вручную)
using System.Net.Sockets;
using
System.IO;
using
System.Threading;
using
System.Text;
using
System.Net;

This code was highlighted with code.xnim.ru
2012-08-12