Поиск на сайте
Главная Журнал Форум Wiki DRKB Страны мира

Голосовой чат в C#

В статье описывается пример элементарного голосового чата. Звук берётся с микрофона при помощи DirectSound и передаётся UDP-пакетами. Перед тем как передать, данные сжимаются войскодером G711. Протокол общения между приёмником и передатчиком выглядит следующим образом:

|             Приглашение                | 
| --------------------------------> |
|               OK                  |
| <-------------------------------- |
|                                   |
| --------------------------------> |
|            поток Аудио            |
| <-------------------------------- |
|              Досвидание           | 
| --------------------------------> |
A                                   B

Структура, содержаща управляющие команды:

enum Command
{
    Invite, //Сделать вызов.

    Bye,    //Закончить вызов.

    Busy,   //Пользователь занят.

    OK,     //Ответ на приглашение. Значение OK указывает, 

            //что вызов принят.

    Null,   //пустой пакет.

}

Когда пользователь делает вызов другого собеседника, приложение посылает команду Invite и ждёт ответа OK. Как только получен ответ OK, начинается приём/передача аудио захваченного с микрофона. Если противоположная сторона отвергает вызов, то отправляется ответ Busy. Для прекращения чата достаточно отправить сообщение Bye. Данный пример приложения ассинхронно принимает/передаёт команды на 1450 порту и синхронно принимает/передаёт звуковые данные 1550 порту. Другими словами, приложение ожидает данных на двух портах: один для управляющих сообщений, а другой для аудио-потока. При запуске, автоматически запускается прослушивание командных сообщений на 1450 порту:

//использование UDP сокетов

clientSocket = new Socket(AddressFamily.InterNetwork, 
    SocketType.Dgram, 
    ProtocolType.Udp);
EndPoint ourEP = new IPEndPoint(IPAddress.Any, 1450);
 
//Ассинхронное прослушивание управляющих сообщений (Invite, Bye и т.д.) на 1450 порту

clientSocket.Bind(ourEP);
 
//Получение данных разрешается с любого IP-адреса.

EndPoint remoteEP = (EndPoint)(new IPEndPoint(IPAddress.Any, 0));
byteData = new byte[1024];
 
//Ассинхронный приём данных.

clientSocket.BeginReceiveFrom(byteData,
    0, byteData.Length,
    SocketFlags.None,
    ref remoteEP,
    new AsyncCallback(OnReceive),
    null);

После получения сообщения, происходит его обработка. За это отвечает обработчик OnReceive (см. исходник). Для приёма/передачи звука с микрофона запускаются два потока, чтобы можно было синхронно посылать/принимать данные и при этом не блокировать пользовательский интерфейс:

private void InitializeCall()
{
    try
    {
        //Запускаем прослушивание на 1550 порту.

        udpClient = new UdpClient(1550);
        Thread senderThread = new Thread(new ThreadStart(Send));
        Thread receiverThread = new Thread(new ThreadStart(Receive));
        bIsCallActive = true;
 
        //Запускаем принимающий и передающий потоки.

        receiverThread.Start();
        senderThread.Start();
        btnCall.Enabled = false;
        btnEndCall.Enabled = true;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, 
            "VoiceChat-InitializeCall ()", MessageBoxButtons.OK, 
        MessageBoxIcon.Error);
    }
}

Методы Send и Receive можно посмотреть в прилагаемом ниже исходнике; разобраться с ними не составит труда.

Скачать исходник - 21 кб




Основные разделы сайта


 

Реклама клининговая компания Эко-сервис.