48888 (Розробка програмного забезпечення системи збору даних про хід та параметри технологічного процесу), страница 2

2016-07-30СтудИзба

Описание файла

Документ из архива "Розробка програмного забезпечення системи збору даних про хід та параметри технологічного процесу", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "курсовые/домашние работы", в предмете "информатика, программирование" в общих файлах.

Онлайн просмотр документа "48888"

Текст 2 страницы из документа "48888"

sUvm = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (!(connect(sUvm, (struct sockaddr *)&server,

sizeof(server)) == SOCKET_ERROR))

{

bConnect = 0;

bTimeSync = 1;

}

}//if

Одразу після підключення КОМ надішле запит на синхронізацію часу.

if ((!bConnect) && (bTimeSync))

{

nLeft = req.lengthPack;

idx = 0;

while(nLeft > 0)

{

ret = send(sUvm, ((char *)&req) + idx, nLeft, 0);

if (ret == SOCKET_ERROR)

{

bConnect = 1;

break;

}

nLeft -= ret;

idx += ret;

}

}//if

Та встновить цей час у системі.

if ((!bConnect) && (bTimeSync))

{

nLeft = 4;

idx = 0;

while(nLeft > 0)

{

ret = recv(sUvm, ((char *)&lastUpdateTime)+idx, nLeft, 0);

if ((ret == SOCKET_ERROR)||(ret == 0))

{

bConnect = 1;

break;

}

nLeft -= ret;

idx += ret;

}

bTimeSync = 0;

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

//stime(&lastUpdateTime);

}//if

Також буде посилатися запит на синхронізацію через 10 хвилин від часу останнього запиту.

if (!bConnect)

{

if ((time (NULL) - lastUpdateTime) > 600)

bTimeSync = 1;

}//if

КОМ відсилають дані датчиків по контрольних точках. Тому час відправки КОМ однієї групи буде однаковим, навіть якщо один з них був запущеним пізніше, але в рамках однієї контрольної точки часу.

if (!bConnect)

{

curTime = time(NULL);

if (lastSendTime == curTime)

timeToSleep = period * 1000;

else

timeToSleep = (period-(curTime % period))*1000;

WaitForSingleObject(hEvent, timeToSleep);

}

Після «прокинення» програмне забезпечення відішле поточний час та дані.

if (!bConnect)

{

if (iUVM < 3)

{

//считывание времени и установка параметров

curTime = time(NULL);

pack1.time = curTime;

nLeft = sizeof(pack1);

}

else

{

//считывание датчиков

//считывание времени и установка параметров

curTime = time(NULL);

pack2.time = curTime;

nLeft = sizeof(pack2);

}

lastSendTime = time(NULL);

idx = 0;

while(nLeft > 0)

{

ret = send(sUvm, pPack+idx, nLeft, 0);

if (ret == SOCKET_ERROR)

{

bConnect = 1;

break;

}

nLeft -= ret;

idx += ret;

}

}//if

Програма буде працювати так постійно, доки користувач не закриє форму програми. Ця подія перехопиться і цикл завершиться, також закриються сокети та поток програми.

7. Програмне забезпечення серверу

Інтерейс серверу зображено на рисунку 6.1.

Рисунок 6. 1 – Інтерфейс серверу

Спочатку користувач вводит адрес серверу, а потім запускає його. Після цього кнопка стане неактивованою.

Сервер також використовую блокуючи сокети. Це приводить до того, що необхідно створювати нові потоки для кожної блокуючої функції. Це з одного боку спрощує роботу з самими сонетами, але ускладнює задачу взаємодії потоків, коли вони використовують одні й ті ж змінні, коли один потік закриваює інший. Велика кількість потоків прискорює роботу серверу на багатопроцесорних системах, але загальмовує її на одно процесорних, бо операційній системі необхідно перемикатися між задачами.

Сервер має постійним потік прийому сокетів та контролю таймаутій. Також програма створює новий потік для кожного клієнта.

Алгоритм прийому клієнтів має наступний вигляд:

while (1)

{

sockAccept = accept(sListen, NULL, NULL);

if ((sockAccept == INVALID_SOCKET) && (WSAGetLastError() == WSAENOTSOCK))

break;

EnterCriticalSection (&cs);

if ((sockAccept != INVALID_SOCKET) && (iNumClients < MAX_CLIENT ))

{

sockInfo[iNumClients].sClient = sockAccept;

sockInfo[iNumClients].typeSender = 0;

sockInfo[iNumClients].time = time(NULL);

sockInfo[iNumClients].hClientThread =(HANDLE) _beginthreadex(NULL, 0,

ClientThread, (LPVOID)iNumClients, 0, &iThreadId);

sockInfo[iNumClients].time = time(NULL);

iNumClients ++ ;

LeaveCriticalSection (&cs);

}

else

{

LeaveCriticalSection (&cs);

shutdown(sockAccept, SD_BOTH);

closesocket(sockAccept);

}

}

return 0;

Алгоритм контролю часу клієнтів працює в залежності від типу клієнта. Якщо це КОМ, то timeout дорівнює 1 хвилині, інакше це 10 хвилин.

while (1)

{

dwWaitState = WaitForSingleObject(hEvent, timeToSleep);

if (dwWaitState == WAIT_OBJECT_0)

break;

EnterCriticalSection (&cs);

for (i = 0; i< iNumClients; i++)

{

if ((sockInfo[i].typeSender == 5) || (sockInfo[i].typeSender == 0))

{

if ((time(NULL) - sockInfo[i].time)>600)

{

DeleteSockInfo(i , 1);

}

}

else

{

if ((time(NULL) - sockInfo[i].time)>60)

{

DeleteSockInfo(i , 1);

}

}

}//for

LeaveCriticalSection (&cs);

}//while

return 0;

Треба зазначити, що сокети клієнтів можуть закриватися при таймауті, при закритті серверу. Тому є спеціальний масив char bAlowCloseClient[MAX_CLIENT] , який указує потоку клієнта, що не потрібно видаляти сокет, бо це буде зроблено іншим модулем програми. В іншому разі, якщо виникла звичайна помилка, то потік клієнта самостійно закриє цей сокет.

Модуль обробки клієнта приймає запити та відповідно отриманих даних виконує дії. Сервер приймає запит req у якому знаходиться тип запиту, ідентифікатор клієнту та довина запросу.

nLeft = sizeof(request);

idx = 0;

while(nLeft > 0)

{

ret = recv(sockInfo[nClient].sClient, ((char *) &req)+idx, nLeft, 0);

if ((ret == SOCKET_ERROR)||(ret == 0))

{

bError = 1;

break;

}

nLeft -= ret;

idx += ret;

}

Необхідно звернути увагу на те, як повідомлення закриття програми обробляється у сервері. Це важливо, бо необхідно зарити усі потоки, та видалити усі динамічні змінні.

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)

{

int i;

if (!bServWorking)

return;

// Закрытие потока Control и события ожидания

SetEvent (hEvent);

WaitForSingleObject(hThreadControl, INFINITE);

CloseHandle (hThreadControl);

CloseHandle (hEvent);

//закрытие сокета сервера и потока Accept

shutdown(sListen, SD_BOTH);

closesocket(sListen);

WaitForSingleObject(hThreadAccept, INFINITE);

CloseHandle (hThreadAccept);

//закрытие сокетов клиентов -> закрытие потоков

EnterCriticalSection (&cs);

for (i = 0; i

{

bAlowCloseClient[i] = 1;

shutdown(sockInfo[i].sClient, SD_BOTH);

closesocket(sockInfo[i].sClient);

WaitForSingleObject(sockInfo[i].hClientThread, INFINITE);

CloseHandle (sockInfo[i].hClientThread);

}

LeaveCriticalSection (&cs);

fclose(f1);

fclose(f2);

DeleteCriticalSection (&cs);

DeleteCriticalSection (&csFile);

WSACleanup();

}

8. Програмне забезпечення робочих станцій

Інтерфейс робочої станції зображено на рисунку 7. 1.

Рисунок 7. 1 – Інтерфейс робочої станції

Спочатку користувач повинен ввести адресу та порт серверу та натиснути відповідну кнопку. При помилці з’явиться відповідне повідомлення та процедуру необхідно буде повторити. Також користувач сам може відсоєдинитись від сервера, натиснувши кнопку. Якщо помилка не з’явилась, то програма ще й синхронізує клієнта з сервером. Процес синхронізації такий ж самий як і в КОМ.

if (connect(sClient, (struct sockaddr *)&server,

sizeof(server)) == SOCKET_ERROR)

{

Application->MessageBoxA("Неудалось подключится к серверу", "Error!", MB_OK);

Form1->Button1->Enabled = TRUE;

return;

}

req.typeRequest = 0; //запрос на синхронизацию

req.typeSender = 5; //идентификатор рабочей станции

req.lengthPack = sizeof(request);

//отправка запроса на синхронизацию времени

nLeft = req.lengthPack;

idx = 0;

while(nLeft > 0)

{

ret = send(sClient, ((char *)&req) + idx, nLeft, 0);

if (ret == SOCKET_ERROR)

{

Application->MessageBoxA("Ошибка отправки запроса на синхронизацию", "Error!", MB_OK);

CloseClientSocket();

return;

}

nLeft -= ret;

idx += ret;

}

//приём времени сервера и установка его в системе

nLeft = sizeof(time_t);

idx = 0;

while(nLeft > 0)

{

ret = recv(sClient, ((char *)&UpdateTime)+idx, nLeft, 0);

if ((ret == SOCKET_ERROR)||(ret == 0))

{

Application->MessageBoxA("Ошибка приёма времени", "Error!", MB_OK);

CloseClientSocket();

return;

}

nLeft -= ret;

idx += ret;

}

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

stime(&UpdateTime);

Далі програма очікує введення даних: типу КОМ, початкового та кінцевого часів. Після введення необхідно натиснути кнопку відправки запиту. Спочатку програма преобразує час. Якщо виникне якась помилка з часом, то з’явиться відповідне повідомлення.

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

tmBegin.tm_sec = Form1->ComboBox3->ItemIndex;

tmBegin.tm_min = Form1->ComboBox2->ItemIndex;

tmBegin.tm_hour = Form1->ComboBox6->ItemIndex;

tmBegin.tm_mday = Form1->ComboBox8->ItemIndex+1;

tmBegin.tm_mon = Form1->ComboBox10->ItemIndex;

tmBegin.tm_year = Form1->ComboBox12->ItemIndex+70;

tmBegin.tm_isdst = 0;

time_tBegin = mktime(&tmBegin);

if (time_tBegin == -1)

{

Application->MessageBoxA("Ошибка преобразования начального времени", "Error!", MB_OK);

Form1->Button3->Enabled = TRUE;

return;

}

tmEnd.tm_sec = Form1->ComboBox5->ItemIndex;

tmEnd.tm_min = Form1->ComboBox4->ItemIndex;

tmEnd.tm_hour = Form1->ComboBox7->ItemIndex;

tmEnd.tm_mday = Form1->ComboBox9->ItemIndex+1;

tmEnd.tm_mon = Form1->ComboBox11->ItemIndex;

tmEnd.tm_year = Form1->ComboBox13->ItemIndex+70;

tmEnd.tm_isdst = 0;

time_tEnd = mktime(&tmEnd);

if (time_tBegin == -1)

{

Application->MessageBoxA("Ошибка преобразования конечного времени", "Error!", MB_OK);

Form1->Button3->Enabled = TRUE;

return;

}

if (time_tEnd < time_tBegin)

{

Application->MessageBoxA("Конечное время меньше начального", "Error!", MB_OK);

Form1->Button3->Enabled = TRUE;

return;

}

Далі програма відправить запит та надасть отримані дані або повідомить про відсутність даних у цьому діапазоні.

reqRange.typeRequest = 2;

reqRange.typeSender = 5;

reqRange.lengthPack = sizeof (requestRange);

reqRange.iTypeUVM = iTypeUVM;

reqRange.tBegin = time_tBegin;

reqRange.tEnd = time_tEnd;

nLeft = reqRange.lengthPack;

idx = 0;

while(nLeft > 0)

{

ret = send(sClient, ((char *)&reqRange) + idx, nLeft, 0);

if (ret == SOCKET_ERROR)

{

Application->MessageBoxA("Ошибка отправки запроса на приём данных", "Error!", MB_OK);

CloseClientSocket();

return;

}

nLeft -= ret;

idx += ret;

}

nLeft = sizeof(packageServer);

idx = 0;

while(nLeft > 0)

{

ret = recv(sClient, ((char *)&packServ)+idx, nLeft, 0);

if ((ret == SOCKET_ERROR)||(ret == 0))

{

Application->MessageBoxA("Ошибка приёма количества данных", "Error!", MB_OK);

CloseClientSocket();

return;

}

nLeft -= ret;

idx += ret;

}

if (packServ.AmountPacks == 0)

{

Application->MessageBoxA("Нет данных в заданном диапазоне времени", "Error!", MB_OK);

Form1->Button3->Enabled = TRUE;

return;

}

StringGrid1->RowCount = packServ.AmountPacks+1;

for (i = 0; i

{

if (iTypeUVM == 1)

nLeft = sizeof(package1);

else

nLeft = sizeof(package2);

idx = 0;

while(nLeft > 0)

{

if (iTypeUVM == 1)

ret = recv(sClient, ((char *)&pack1)+idx, nLeft, 0);

else

ret = recv(sClient, ((char *)&pack2)+idx, nLeft, 0);

if ((ret == SOCKET_ERROR)||(ret == 0))

{

Application->MessageBoxA("Ошибка приёма структуры данных", "Error!", MB_OK);

CloseClientSocket();

return;

}

nLeft -= ret;

idx += ret;

}//while

Додаток А. Вихідний текст КОМ

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

#include

Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5137
Авторов
на СтудИзбе
440
Средний доход
с одного платного файла
Обучение Подробнее