nLeft = sizeof(package1);
else
nLeft = sizeof(package2);
idx = 0;
while(nLeft > 0)
{
if (TypeSender < 3)
ret = recv(sockInfo[nClient].sClient, ((char *)&pack1)+idx, nLeft, 0);
else
ret = recv(sockInfo[nClient].sClient, ((char *)&pack2)+idx, nLeft, 0);
if ((ret == SOCKET_ERROR)||(ret == 0))
{
bError = 1;
break;
}
nLeft -= ret;
idx += ret;
}//while
//запись полученных данных в файл
if (!bError)
if (TypeSender < 3)
{
EnterCriticalSection (&csFile);
if (pack1.time >= lastTimeGroup1)
{
lastTimeGroup1 = pack1.time;
fwrite((void *)&pack1,sizeof(package1) ,1,f1);
fflush(f1);
}
LeaveCriticalSection (&csFile);
}
else //TypeSender > 3
{
EnterCriticalSection (&csFile);
if (pack2.time >= lastTimeGroup2)
{
lastTimeGroup2 = pack2.time;
fwrite((void *)&pack2,sizeof(package2) ,1,f2);
fflush(f2);
}
LeaveCriticalSection (&csFile);
}
}//if УВМ
//работа с рабочей станцией
if ((req.typeRequest == 2) && (!bError))
{
//сохранение времени последнего обращения
EnterCriticalSection (&cs);
sockInfo[nClient].time = time(NULL);
LeaveCriticalSection (&cs);
//приём диапазона и типа УВМ
nLeft = sizeof (requestRange);
idx = 0;
while(nLeft > 0)
{
ret = recv(sockInfo[nClient].sClient, ((char *)&reqRange)+idx, nLeft, 0);
if ((ret == SOCKET_ERROR)||(ret == 0))
{
bError = 1;
break;
}
nLeft -= ret;
idx += ret;
}//while
//поиск кол-ва файлов удовлетворяющих диапазону времени
packServ.typeRequest = 3; //данные от сервера
packServ.typeSender = 6; //сервер
packServ.lengthPack = sizeof (packageServer);
packServ.AmountPacks = 0;
EnterCriticalSection (&csFile);
if (reqRange.iTypeUVM == 1)
{
curPos = ftell(f1);
fseek(f1, 0, SEEK_END);
endPos = ftell(f1);
fseek(f1, 0, SEEK_SET);
nStructs = endPos / (sizeof(package1));
iFound = 0;
for (i = 0; i<nStructs; i++)
{
fread((void *)&pack1, sizeof(package1), 1, f1);
if ((pack1.time >=reqRange.tBegin) && ( pack1.time <= reqRange.tEnd))
{
packServ.AmountPacks++;
if (iFound == 0)
{
iFound = 1;
startPos = ftell(f1) - sizeof(package1);
}
}
}//for
fseek(f1, curPos, SEEK_SET);
}
else
{
curPos = ftell(f2);
fseek(f2, 0, SEEK_END);
endPos = ftell(f2);
fseek(f2, 0, SEEK_SET);
nStructs = endPos / (sizeof(package2));
iFound = 0;
for (i = 0; i<nStructs; i++)
{
fread((void *)&pack2, sizeof(package2), 1, f2);
if ((pack2.time >=reqRange.tBegin) && ( pack2.time <= reqRange.tEnd))
{
packServ.AmountPacks++;
if (iFound == 0)
{
iFound = 1;
startPos = ftell(f2) - sizeof(package2);
}
}
}//for
fseek(f2, curPos, SEEK_SET);
}
LeaveCriticalSection (&csFile);
//отсылка количества найденных структур
nLeft = packServ.lengthPack;
idx = 0;
while(nLeft > 0)
{
ret = send(sockInfo[nClient].sClient, ((char *) &packServ)+idx, nLeft, 0);
if (ret == SOCKET_ERROR)
{
bError = 1;
break;
}
nLeft -= ret;
idx += ret;
}
//считывание структур из файлов
if ((iFound != 0)&&(!bError))
{
EnterCriticalSection (&csFile);
if (reqRange.iTypeUVM == 1)
{
pack1Array = new package1[packServ.AmountPacks];
curPos = ftell(f1);
fseek(f1, startPos, SEEK_SET);
for (i = 0; i<packServ.AmountPacks; i++)
fread((void *)&pack1Array[i], sizeof(package1), 1, f1);
fseek(f1, curPos, SEEK_SET);
}
else
{
pack2Array = new package2[packServ.AmountPacks];
curPos = ftell(f2);
fseek(f2, startPos, SEEK_SET);
for (i = 0; i<packServ.AmountPacks; i++)
fread((void *)&pack2Array[i], sizeof(package2), 1, f2);
fseek(f2, curPos, SEEK_SET);
}
LeaveCriticalSection (&csFile);
//отсылка структур
for (i = 0; i<packServ.AmountPacks; i++)
{
if (reqRange.iTypeUVM == 1)
nLeft = sizeof(package1);
else
nLeft = sizeof(package2);
idx = 0;
while(nLeft > 0)
{
if (reqRange.iTypeUVM == 1)
ret = send(sockInfo[nClient].sClient, ((char *) &pack1Array[i])+idx, nLeft, 0);
else
ret = send(sockInfo[nClient].sClient, ((char *) &pack2Array[i])+idx, nLeft, 0);
if (ret == SOCKET_ERROR)
{
bError = 1;
break;
}
nLeft -= ret;
idx += ret;
}//while
if (bError == 1)
{
idx = 5;
break;
}
}//for
if (reqRange.iTypeUVM == 1)
delete[] pack1Array;
else
delete[] pack2Array;
}//if iFound
}//if PC
}//while (!bError)
//удаление записи о скруктуре текущего сокете
if (!bAlowCloseClient[nClient])
{
EnterCriticalSection (&cs);
DeleteSockInfo (nClient, 0);
LeaveCriticalSection (&cs);
}
return 0;
}//ClientThread
//---------------------------------------------------------------------------
unsigned __stdcall AcceptThread(LPVOID lpParam)
{
SOCKET sockAccept;
UINT iThreadId;
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;
} // AcceptThread()
//---------------------------------------------------------------------------
unsigned __stdcall ControlThread(LPVOID lpParam)
{
int i;
DWORD dwWaitState;
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;
} // ControlThread()
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
struct sockaddr_in server;
UINT iThreadId;
AnsiString sAddress, sPort;
char * cAddress, * cPort;
unsigned int lenAdr, lenPort, iPort;
Form1->Button1->Enabled = FALSE;
//создание или открытие файлов
hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
if ((f1=fopen("group1.txt","a+b"))==NULL)
{
Form1->Button1->Enabled = TRUE;
return;
}
fseek (f1, 0, SEEK_END);
if ((f2=fopen("group2.txt","a+b"))==NULL)
{
fclose(f1);
Form1->Button1->Enabled = TRUE;
return;
}
fseek (f2, 0, SEEK_END);
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
fclose(f1);
fclose(f2);
Form1->Button1->Enabled = TRUE;
return;
}
//создание необходимых событий, секций
hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
InitializeCriticalSection (&cs);
InitializeCriticalSection (&csFile);
//создание сокета
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sListen == INVALID_SOCKET)
{
CloseHandle (hEvent);
fclose(f1);
fclose(f2);
DeleteCriticalSection (&cs);
DeleteCriticalSection (&csFile);
Form1->Button1->Enabled = TRUE;
return;
}
// преобразование адреса
sAddress = Form1->Edit2->Text;
cAddress = sAddress.c_str();
lenAdr = sAddress.Length();
cAddress[lenAdr] = '\0';
//преобразование порта
sPort = Form1->Edit3->Text;
cPort = sPort.c_str();
lenPort = sPort.Length();
cPort[lenPort] = '\0';
iPort = atoi(cPort);
server.sin_family = AF_INET;
server.sin_port = htons(iPort);
server.sin_addr.s_addr = inet_addr(cAddress);
if (server.sin_addr.s_addr == INADDR_NONE)
{
CloseHandle (hEvent);
shutdown(sListen, SD_BOTH);
closesocket(sListen);
fclose(f1);
fclose(f2);
DeleteCriticalSection (&cs);
DeleteCriticalSection (&csFile);
Form1->Button1->Enabled = TRUE;
return;
}
if (bind(sListen, (SOCKADDR*) &server, sizeof(server)) == SOCKET_ERROR)
{
CloseHandle (hEvent);
shutdown(sListen, SD_BOTH);
closesocket(sListen);
fclose(f1);
fclose(f2);
DeleteCriticalSection (&cs);
DeleteCriticalSection (&csFile);
Form1->Button1->Enabled = TRUE;
return;
}
if (listen(sListen, 8) == SOCKET_ERROR)
{
CloseHandle (hEvent);
shutdown(sListen, SD_BOTH);
closesocket(sListen);
fclose(f1);
fclose(f2);
DeleteCriticalSection (&cs);
DeleteCriticalSection (&csFile);
Form1->Button1->Enabled = TRUE;
return;
}
//создание потока accept
hThreadAccept = (HANDLE)_beginthreadex(NULL, 0, AcceptThread, (LPVOID)sListen, 0,
&iThreadId);
if (hThreadAccept == NULL)
{
CloseHandle (hEvent);
shutdown(sListen, SD_BOTH);
closesocket(sListen);
fclose(f1);
fclose(f2);
DeleteCriticalSection (&cs);
DeleteCriticalSection (&csFile);
Form1->Button1->Enabled = TRUE;
return;
}
//создание потока отслеживания времени последнего обращени клиентов
hThreadControl = (HANDLE)_beginthreadex(NULL, 0, ControlThread, (LPVOID)sListen, 0,
&iThreadId);
if (hThreadControl == NULL)
{
return;
}
bServWorking = TRUE;
return;
}
//---------------------------------------------------------------------------
void DeleteSockInfo(int num, uc bWaitThread)
{
int i;
bAlowCloseClient[num] = 1;
shutdown(sockInfo[num].sClient, SD_BOTH);
closesocket(sockInfo[num].sClient);
if (bWaitThread)
WaitForSingleObject(sockInfo[num].hClientThread, INFINITE);
CloseHandle (sockInfo[num].hClientThread);
bAlowCloseClient[num] = 0;
for (i = num; i<(iNumClients-1); i++)
sockInfo[i] = sockInfo[i+1];
iNumClients--;
}
//---------------------------------------------------------------------------
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<iNumClients; 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();
}
Додаток В. Вихідний текст робочої станції
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Client.h"
#include <time.h>
#include <winsock2.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
typedef unsigned char uc;
typedef unsigned short int ui;
#pragma pack (push)
#pragma pack (1)
typedef struct
{
time_t time;
uc speed1;
uc speed2;
ui temperature1;
ui temperature2;
ui temperature3;
ui weight1;
ui weight2;
ui weight3;
uc length1;
uc length2;
} package1;
typedef struct
{
time_t time;
uc speed1;
uc speed2;
uc speed3;
ui temperature1;
ui temperature2;
ui weight1;
ui weight2;
ui weight3;
ui weight4;
uc length;
} package2;
typedef struct
{
uc typeRequest; //0 - запрос на синхронизацию
//1 - данные от УВМ
//2 - запрос от клиента
//3 - данные от севера
uc typeSender; //1..4 номер УВМ
//5 клиент
//6 сервер
uc lengthPack;
} request;
typedef struct
{
uc typeRequest;
uc typeSender;
uc lengthPack;
ui iTypeUVM;
time_t tBegin;
time_t tEnd;
} requestRange;
typedef struct
{
uc typeRequest;
uc typeSender;
uc lengthPack;
unsigned long AmountPacks;
} packageServer;
#pragma pack (pop)
SOCKET sClient;
WSADATA wsd;
//---------------------------------------------------------------------------
void CloseClientSocket()
{
Form1->Button2->Enabled = FALSE;
Form1->Button3->Enabled = FALSE;
shutdown(sClient, SD_BOTH);
closesocket(sClient);
Form1->Button1->Enabled = TRUE;
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
StringGrid1->RowCount = 2;
StringGrid1->Rows[1]->Clear();
StringGrid1->Cells[0][0] = "№";
StringGrid1->Cells[1][0] = "Год";
StringGrid1->Cells[2][0] = "Месяц";
StringGrid1->Cells[3][0] = "День месяца";
StringGrid1->Cells[4][0] = "Часы";
StringGrid1->Cells[5][0] = "Минуты";
StringGrid1->Cells[6][0] = "Секунды";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
struct sockaddr_in server;
AnsiString sAddress, sPort;
char * cAddress, * cPort;
unsigned int lenAdr, lenPort, iPort;
int nLeft, idx, ret;
request req;
time_t UpdateTime;
Form1->Button1->Enabled = FALSE;
// преобразование адреса
sAddress = Form1->Edit1->Text;
cAddress = sAddress.c_str();
lenAdr = sAddress.Length();
cAddress[lenAdr] = '\0';
//преобразование порта
sPort = Form1->Edit2->Text;
cPort = sPort.c_str();
lenPort = sPort.Length();
cPort[lenPort] = '\0';
iPort = atoi(cPort);
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{