Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
92.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
100.76 Кб
Скачать

Функция приема блока

Данная функция начинает свою работу только если для приема есть нужное количество данных.

unsigned long lSize;

ioctlsocket(s,FIONREAD,&lSize);

if (lSize==0) return;

Далее происходит прием сообщение, выделение его составляющих, проверка его номера для отброса неактуальных сообщений, увеличение счетчика сообщений, вывод символьного имени и отправка аудиоданных в буфер для последующего воспроизведения.

//приём данных

int cadr=sizeof(from);

recvfrom(s,RecvBuffer,sizeof(Sound),0,(struct sockaddr*)&from,&cadr);

//указатель на буфер с принятыми данными

Sound* pointSound;

pointSound=(Sound*) RecvBuffer;

//анализ номера пакета

//если нумерация нарушается, то пакет не воспроизводится

if (pointSound->Number>prevNumber)

{

//вывод числа принятых пакетов и имени отправителя

/*AnsiString st=pointSound->Name;

Form1->lReceive->Caption="От "+st+" принято пакетов: "+IntToStr(i);

i++;*/

String^ a= gcnew String(pointSound->Name,0,strlen(pointSound->Name));

textBox_file_name->Text=a;

numericUpDown_reseive->Value++;

//отправка данных в буфер для накопления

In(pointSound->SoundData);

};

return;

Функция воспроизведения блока

В данной функции происходит сначала чтение семпла из буфера.

//взять блок данных из начала очереди

memcpy(PlayBuf,QUEUE[(fst+1)%SIZE_OF_BUF],SIZE_OF_SOUND);

fst=(fst+1)%SIZE_OF_BUF;

Далее его подготовка к воспроизведению, т.е. создание структуры данных понятной аудиоустройству.

//подготовка буфера для воспроизведения

pwhPlay.lpData=PlayBuf;

pwhPlay.dwBufferLength=SIZE_OF_SOUND;

pwhPlay.dwFlags=0;

//подготовка блока аудиоданных для воспроизведения

mres=waveOutPrepareHeader(hwo,&pwhPlay,sizeof(pwhPlay));

if (mres!=0) textBox_error->Text=L"Error: OutPrepareHeader";

И Далее отправка блока на аудиоустройство

//отправка блока аудиоданных заданному устройству вывода

mres=waveOutWrite(hwo,&pwhPlay,sizeof(pwhPlay));

if (mres!=0) textBox_error->Text=L"Error: waveOutWrite";

Подключение необходимых библиотек

Для работы программы необходимо подключить 2 основные библиотеки – это библиотека работы с сокетами и библиотека работы со звуком.

Помимо подключения заголовочных файлов

#include <Winsock2.h>

#include <MMSystem.h>

Приложение

Блок-схемы

Инициализация сокета

Инициализация звука

Прием одного пакета

Передача одного пакета

SDL-диаграммы

Текст программы

// kur.cpp: главный файл проекта.

#include "stdafx.h"

#include "Form1.h"

using namespace kur;

[STAThreadAttribute]

int main(array<System::String ^> ^args)

{

// Включение визуальных эффектов Windows XP до создания каких-либо элементов управления

Application::EnableVisualStyles();

Application::SetCompatibleTextRenderingDefault(false);

// Создание главного окна и его запуск

Application::Run(gcnew Form1());

return 0;

}

// Form1.h

#pragma once

//подключение необходимых библиотек

#include <Winsock2.h>

#include <stdio.h>

#include <string.h>

#include <MMSystem.h>

const int SIZE_OF_SOUND=192*50;

//структура с описанием формата пакета

struct Sound

{

char Name[10]; //имя отправителя

int Number; //номер кадра

char SoundData[SIZE_OF_SOUND]; //аудиоданные

};

//---------------------------------------------------------------------------

//необходимые переменные и константы

int num = 0;

//размер области аудиоданных пакета

//параметры циклического буфера для принятых аудиоданных

int fst; //указатель на первый элемент буфера

int lst; //указатель на следующий за последним элемент буфера

const int SIZE_OF_BUF=14; //максимальное число элементов буфера

char QUEUE[SIZE_OF_BUF][SIZE_OF_SOUND]; //буфер

//буфер для воспроизведения

char PlayBuf[SIZE_OF_SOUND];

bool EnableReceive=false; //индикатор разрешения приёма трансляции

bool StreamOpen=false; //индикатор создания потока

bool Timer2Enable=false; //индикатор запуска таймера на воспроизведение

char WaveBuf[SIZE_OF_SOUND]; //буфер для считанных из файла данных

HANDLE Soc_id; //дескриптор потока

DWORD S_id; //идентификатор потока

WAVEHDR pwhPlay; //структура, описывающая буфер на проигрывание звука

HWAVEOUT hwo; //идентификатор аудиоустройства

WAVEFORMATEX CurrentFormatFile; //структура с описанием формата звуковых данных

MMRESULT mres; //переменная для хранения результата выполнения функции

HMMIO hmmio; //идентификатор файла

//из класса Tsoc

int i, j; //число отправленных/принятых пакетов

int prevNumber; //номер предыдущего принятого пакета

SOCKET s; //идентификатор сокета

SOCKADDR_IN to; //структура с описанием адреса получателя

SOCKADDR_IN from; //структура с описанием адреса отправителя

char RecvBuffer[SIZE_OF_SOUND+14]; //буфер для принятого пакета

Sound sSound; //объект класса Sound

//TSoc(); //конструктор

bool Create(); //функция создания и настройки сокета

void Receive(); //функция приёма пакетов

void Send(char* SendVoiceBuf); //функция отправки пакетов

//---

//функция записи принятых аудиоданных в циклический буфер

void In(char* SoundBuff);

//---------------------------------------------------------------------------

namespace kur {

using namespace System;

using namespace System::ComponentModel;

using namespace System::Collections;

using namespace System::Windows::Forms;

using namespace System::Data;

using namespace System::Drawing;

public ref class Form1 : public System::Windows::Forms::Form

{

public:

Form1(void)

{

InitializeComponent();

//

//TODO: добавьте код конструктора

//

}

protected:

/// <summary>

/// Освободить все используемые ресурсы.

/// </summary>

~Form1()

{

if (components)

{

delete components;

}

}

private: System::Windows::Forms::Button^ button_start_send;

private: System::Windows::Forms::Button^ button_end_send;

private: System::Windows::Forms::Button^ button_start_reseive;

private: System::Windows::Forms::Button^ button_end__reseive;

private: System::Windows::Forms::TextBox^ textBox_error;

private: System::Windows::Forms::Timer^ timer_send;

private: System::Windows::Forms::Timer^ timer_reseive;

private: System::Windows::Forms::Timer^ timer_play;

private: System::Windows::Forms::NumericUpDown^ numericUpDown_send;

private: System::Windows::Forms::NumericUpDown^ numericUpDown_reseive;

private: System::Windows::Forms::NumericUpDown^ numericUpDown_timer;

private: System::Windows::Forms::TextBox^ textBox_file_name;

private: System::Windows::Forms::TextBox^ textBox_IP;

private: System::ComponentModel::IContainer^ components;

protected:

protected:

protected:

private:

/// <summary>

/// Требуется переменная конструктора.

/// </summary>

#pragma region Windows Form Designer generated code

/// <summary>

/// Обязательный метод для поддержки конструктора - не изменяйте

/// содержимое данного метода при помощи редактора кода.

/// </summary>

void InitializeComponent(void)

{

this->components = (gcnew System::ComponentModel::Container());

this->button_start_send = (gcnew System::Windows::Forms::Button());

this->button_end_send = (gcnew System::Windows::Forms::Button());

this->button_start_reseive = (gcnew System::Windows::Forms::Button());

this->button_end__reseive = (gcnew System::Windows::Forms::Button());

this->textBox_error = (gcnew System::Windows::Forms::TextBox());

this->timer_send = (gcnew System::Windows::Forms::Timer(this->components));

this->timer_reseive = (gcnew System::Windows::Forms::Timer(this->components));

this->timer_play = (gcnew System::Windows::Forms::Timer(this->components));

this->numericUpDown_send = (gcnew System::Windows::Forms::NumericUpDown());

this->numericUpDown_reseive = (gcnew System::Windows::Forms::NumericUpDown());

this->numericUpDown_timer = (gcnew System::Windows::Forms::NumericUpDown());

this->textBox_file_name = (gcnew System::Windows::Forms::TextBox());

this->textBox_IP = (gcnew System::Windows::Forms::TextBox());

(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->numericUpDown_send))->BeginInit();

(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->numericUpDown_reseive))->BeginInit();

(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->numericUpDown_timer))->BeginInit();

this->SuspendLayout();

//

// button_start_send

//

this->button_start_send->Location = System::Drawing::Point(12, 179);

this->button_start_send->Name = L"button_start_send";

this->button_start_send->Size = System::Drawing::Size(128, 29);

this->button_start_send->TabIndex = 0;

this->button_start_send->Text = L"Начать отправку";

this->button_start_send->UseVisualStyleBackColor = true;

this->button_start_send->Click += gcnew System::EventHandler(this, &Form1::button1_Click);

//

// button_end_send

//

this->button_end_send->Location = System::Drawing::Point(12, 214);

this->button_end_send->Name = L"button_end_send";

this->button_end_send->Size = System::Drawing::Size(128, 29);

this->button_end_send->TabIndex = 1;

this->button_end_send->Text = L"Закончить отправку";

this->button_end_send->UseVisualStyleBackColor = true;

this->button_end_send->Click += gcnew System::EventHandler(this, &Form1::button_end_send_Click);

//

// button_start_reseive

//

this->button_start_reseive->Location = System::Drawing::Point(274, 179);

this->button_start_reseive->Name = L"button_start_reseive";

this->button_start_reseive->Size = System::Drawing::Size(128, 29);

this->button_start_reseive->TabIndex = 2;

this->button_start_reseive->Text = L"Начать прием";

this->button_start_reseive->UseVisualStyleBackColor = true;

this->button_start_reseive->Click += gcnew System::EventHandler(this, &Form1::button_start_reseive_Click);

//

// button_end__reseive

//

this->button_end__reseive->Location = System::Drawing::Point(274, 214);

this->button_end__reseive->Name = L"button_end__reseive";

this->button_end__reseive->Size = System::Drawing::Size(128, 29);

this->button_end__reseive->TabIndex = 3;

this->button_end__reseive->Text = L"Закончит прием";

this->button_end__reseive->UseVisualStyleBackColor = true;

this->button_end__reseive->Click += gcnew System::EventHandler(this, &Form1::button_end__reseive_Click);

//

// textBox_error

//

this->textBox_error->Location = System::Drawing::Point(12, 278);

this->textBox_error->Name = L"textBox_error";

this->textBox_error->Size = System::Drawing::Size(390, 20);

this->textBox_error->TabIndex = 4;

//

// timer_send

//

this->timer_send->Interval = 1270;

this->timer_send->Tick += gcnew System::EventHandler(this, &Form1::timer_send_Tick);

//

// timer_reseive

//

this->timer_reseive->Interval = 1270;

this->timer_reseive->Tick += gcnew System::EventHandler(this, &Form1::timer_reseive_Tick);

//

// timer_play

//

this->timer_play->Interval = 1270;

this->timer_play->Tick += gcnew System::EventHandler(this, &Form1::timer_play_Tick);

//

// numericUpDown_send

//

this->numericUpDown_send->Location = System::Drawing::Point(12, 140);

this->numericUpDown_send->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) {10000, 0, 0, 0});

this->numericUpDown_send->Name = L"numericUpDown_send";

this->numericUpDown_send->Size = System::Drawing::Size(120, 20);

this->numericUpDown_send->TabIndex = 5;

//

// numericUpDown_reseive

//

this->numericUpDown_reseive->Location = System::Drawing::Point(282, 140);

this->numericUpDown_reseive->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) {10000, 0, 0, 0});

this->numericUpDown_reseive->Name = L"numericUpDown_reseive";

this->numericUpDown_reseive->Size = System::Drawing::Size(120, 20);

this->numericUpDown_reseive->TabIndex = 6;

//

// numericUpDown_timer

//

this->numericUpDown_timer->Location = System::Drawing::Point(140, 12);

this->numericUpDown_timer->Maximum = System::Decimal(gcnew cli::array< System::Int32 >(4) {10000, 0, 0, 0});

this->numericUpDown_timer->Name = L"numericUpDown_timer";

this->numericUpDown_timer->Size = System::Drawing::Size(120, 20);

this->numericUpDown_timer->TabIndex = 7;

this->numericUpDown_timer->Value = System::Decimal(gcnew cli::array< System::Int32 >(4) {1270, 0, 0, 0});

this->numericUpDown_timer->ValueChanged += gcnew System::EventHandler(this, &Form1::numericUpDown_timer_ValueChanged);

//

// textBox_file_name

//

this->textBox_file_name->Location = System::Drawing::Point(198, 85);

this->textBox_file_name->Name = L"textBox_file_name";

this->textBox_file_name->Size = System::Drawing::Size(209, 20);

this->textBox_file_name->TabIndex = 8;

//

// textBox_IP

//

this->textBox_IP->Location = System::Drawing::Point(26, 76);

this->textBox_IP->Name = L"textBox_IP";

this->textBox_IP->Size = System::Drawing::Size(100, 20);

this->textBox_IP->TabIndex = 9;

this->textBox_IP->Text = L"127.0.0.1";

//

// Form1

//

this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);

this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;

this->ClientSize = System::Drawing::Size(419, 310);

this->Controls->Add(this->textBox_IP);

this->Controls->Add(this->textBox_file_name);

this->Controls->Add(this->numericUpDown_timer);

this->Controls->Add(this->numericUpDown_reseive);

this->Controls->Add(this->numericUpDown_send);

this->Controls->Add(this->textBox_error);

this->Controls->Add(this->button_end__reseive);

this->Controls->Add(this->button_start_reseive);

this->Controls->Add(this->button_end_send);

this->Controls->Add(this->button_start_send);

this->Name = L"Form1";

this->Text = L"Form1";

this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);

(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->numericUpDown_send))->EndInit();

(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->numericUpDown_reseive))->EndInit();

(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->numericUpDown_timer))->EndInit();

this->ResumeLayout(false);

this->PerformLayout();

}

#pragma endregion

// мои функции

//функция записи принятых аудиоданных в циклический буфер

void In(char* Buf)

{

//запись в буфер

memcpy(QUEUE[lst],Buf,SIZE_OF_SOUND);

lst=(lst+1)%SIZE_OF_BUF;

//разрешить срабатывание таймера на воспроизведение принятых данных

//если он ещё не запущен

if (timer_play->Enabled==false)

{

//Form1->Timer2->Enabled=true;

timer_play->Enabled=true;

};

}

//---------------------------------------------------------------------------

//функция создания и настройки сокета

bool Create()

{

//инициализация сокета

WSADATA wsadata;

WORD wVersionRequested;

wVersionRequested = MAKEWORD(2,0);

if (WSAStartup(wVersionRequested,&wsadata)==SOCKET_ERROR)

{

// MessageBox(0,"Error: WSAStartup",0,MB_OK);

textBox_error->Text=L"Error: WSAStartup";

return false;

};

//создание сокета и присвоение идентификатора

s=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

if(s==INVALID_SOCKET)

{

// MessageBox(0,"Error: Create socket",0,MB_OK);

textBox_error->Text=L"Error: Create socket";

return false;

};

//создание структуры адреса отправителя

from.sin_addr.S_un.S_addr=ADDR_ANY;

from.sin_family=PF_INET;

from.sin_port=5000;

//подключение сокета к коммуникационной среде

int errSer=bind(s,(LPSOCKADDR)&from,sizeof(from));

if(errSer!=0)

{

//MessageBox(0,"Error: Bind", 0, MB_OK);

textBox_error->Text=L"Error: Bind";

closesocket(s); //закрытие сокета

return false;

};

return true;

}

//---------------------------------------------------------------------------

//функция формирования и передачи пакетов

void Send(char* SendVoiceBuf)

{

//заполнение заголовка пакета

//имя отправителя берётся из поля "От кого"

memcpy(sSound.Name,"telefon",10);

//номер пакета

sSound.Number=num++;

//заполнение поля данных

memcpy(sSound.SoundData,SendVoiceBuf,SIZE_OF_SOUND);

//формирование структуры с IP-адресом получателя

::to.sin_family=PF_INET;

//::to.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

String^ strinput2=textBox_IP->Text;

char c[20];

for(int j=0;j<strinput2->Length;j++)

c[j]=strinput2[j];

c[strinput2->Length]='\0';

to.sin_addr.S_un.S_addr=inet_addr(c);

::to.sin_port=5000;

//отправка пакета

int err=sendto(s,(char*)(&sSound),sizeof(Sound),0,(struct sockaddr*)&to,sizeof(to));

if (err==SOCKET_ERROR)

//MessageBox(0,"Error: Send sound",0,MB_OK);

textBox_error->Text=L"Error: Send sound";

//число переданных пакетов

else

{

//Form1->lSend->Caption="Послано пакетов: "+IntToStr(j);

//j++;

numericUpDown_send->Value++;

};

}

//---------------------------------------------------------------------------

//функция приёма пакетов

void Receive()

{

//определение наличия пришедших данных

unsigned long lSize;

ioctlsocket(s,FIONREAD,&lSize);

if (lSize==0) return;

//приём данных

int cadr=sizeof(from);

recvfrom(s,RecvBuffer,sizeof(Sound),0,(struct sockaddr*)&from,&cadr);

//указатель на буфер с принятыми данными

Sound* pointSound;

pointSound=(Sound*) RecvBuffer;

//анализ номера пакета

//если нумерация нарушается, то пакет не воспроизводится

if (pointSound->Number>prevNumber)

{

//вывод числа принятых пакетов и имени отправителя

/*AnsiString st=pointSound->Name;

Form1->lReceive->Caption="От "+st+" принято пакетов: "+IntToStr(i);

i++;*/

String^ a= gcnew String(pointSound->Name,0,strlen(pointSound->Name));

textBox_file_name->Text=a;

numericUpDown_reseive->Value++;

//отправка данных в буфер для накопления

In(pointSound->SoundData);

};

return;

}

//---------------------------------------------------------------------------

//конец функций

private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {

//вызов функции создания и настройки сокета

Create();

//if (Create()) btSend->Enabled=true;

//else return;

//инициализация формата звуковых данных

CurrentFormatFile.wFormatTag=WAVE_FORMAT_PCM;

CurrentFormatFile.nChannels=1;

CurrentFormatFile.nSamplesPerSec=8000;

CurrentFormatFile.nAvgBytesPerSec=8000;

CurrentFormatFile.nBlockAlign=1;

CurrentFormatFile.wBitsPerSample=8;

//открытие устройства воспроизведения

UINT uDeviceID=WAVE_MAPPER;

mres=waveOutOpen(&hwo,uDeviceID,&CurrentFormatFile,0,0,0);

if (mres!=0)

//MessageBox(0,"Error: WaveOutOpen",0,MB_OK);

textBox_error->Text=L"Error: WaveOutOpen";

//else btReceive->Enabled=true;

//---------------------------------------------------------------------------

}

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {

//открытие файла для чтения

hmmio=mmioOpen(L"telephon.wav",0,MMIO_READ);

if (hmmio==0)

{

//MessageBox(0,"Error: mmioOpen",0,MB_OK);

textBox_error->Text=L"Error: mmioOpen";

//btSend->Enabled=false;

return;

};

/*

btSend->Enabled=false; //деактивация кнопки "Начать передачу"

btStopSend->Enabled=true; //активация кнопки "Остановить"

From->Enabled=false; //запрещение редктирования поля "От кого"

To->Enabled=false; //запрещение редктирования поля "Кому"

*/

//разрешить срабатывание таймера на отправку пакетов

timer_send->Enabled=true;

}

private: System::Void button_end_send_Click(System::Object^ sender, System::EventArgs^ e) {

timer_send->Enabled=false; //запретить срабатывание таймера на отправку пакетов

}

private: System::Void timer_send_Tick(System::Object^ sender, System::EventArgs^ e) {

//прочитать данные из открытого блока

mmioRead(hmmio,WaveBuf,SIZE_OF_SOUND);

//вызов функции отправки пакета

Send(WaveBuf);

}

private: System::Void button_start_reseive_Click(System::Object^ sender, System::EventArgs^ e) {

timer_reseive->Enabled=true;

}

private: System::Void button_end__reseive_Click(System::Object^ sender, System::EventArgs^ e) {

timer_reseive->Enabled=false;

timer_play->Enabled=false;

}

private: System::Void timer_reseive_Tick(System::Object^ sender, System::EventArgs^ e) {

Receive();

}

private: System::Void timer_play_Tick(System::Object^ sender, System::EventArgs^ e) {

//взять блок данных из начала очереди

memcpy(PlayBuf,QUEUE[(fst+1)%SIZE_OF_BUF],SIZE_OF_SOUND);

fst=(fst+1)%SIZE_OF_BUF;

//подготовка буфера для воспроизведения

pwhPlay.lpData=PlayBuf;

pwhPlay.dwBufferLength=SIZE_OF_SOUND;

pwhPlay.dwFlags=0;

//подготовка блока аудиоданных для воспроизведения

mres=waveOutPrepareHeader(hwo,&pwhPlay,sizeof(pwhPlay));

if (mres!=0)

//MessageBox(0,"Error: OutPrepareHeader",0,MB_OK);

textBox_error->Text=L"Error: OutPrepareHeader";

//отправка блока аудиоданных заданному устройству вывода

mres=waveOutWrite(hwo,&pwhPlay,sizeof(pwhPlay));

if (mres!=0)

//MessageBox(0,"Error: waveOutWrite",0,MB_OK);

textBox_error->Text=L"Error: waveOutWrite";

}

private: System::Void numericUpDown_timer_ValueChanged(System::Object^ sender, System::EventArgs^ e) {

timer_play->Interval=numericUpDown_timer->Value.ToInt32(numericUpDown_timer->Value);

timer_send->Interval=numericUpDown_timer->Value.ToInt32(numericUpDown_timer->Value);

timer_reseive->Interval=numericUpDown_timer->Value.ToInt32(numericUpDown_timer->Value);

}

};

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]