Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабораторная работа 12 / Lab1 / Lab1 / Lab1
.cpp//
// Lab1.cpp
//
#include "stdafx.h"
#include <wtypes.h>
#include <stdlib.h>
#define PACKET_NUM ((DWORD)100) //число пакетов
//#define DATA_SIZE ((DWORD)0x10000) //размер данных
#define MAX_DATA_SIZE ((int)256*1024) //граница размера данных
int data_size=0; //размер данных
#define QUEUE_SIZE ((DWORD)5) //размер очереди
#define CLIENT_TIMEOUT ((DWORD)50) //интервал
#define TIME_LIMIT ((DWORD)3000) //время ожидания
//#define SERV_TIME ((DWORD)100) //время обслуживания
int serv_time=0; //время обслуживания
char *SERVER_NAME; // имя сервера
unsigned short SERVER_PORT; // порт сервера
bool SERVER_ROLE=false; // роль
unsigned g_success=0; // число успешно обработанных запросов
DWORD proc_time=0;
DWORD start_time=0;
// функция: PrintError
// назначение: вывод на экран ошибки WinSock
int PrintError(const char *msg=0)
{
printf("Fatal error in %s, WSAError=%d\n",msg,WSAGetLastError());
ExitThread(-1);
return -1;
}
// функция: PrintUsage
// назначение: вывод на экран информации о параметрах
// командной строки
void PrintUsage()
{
printf("Program usage:\n");
printf("\tServer role: lab1 -S port proc_time data_size\n");
printf("\tClient role: lab1 -C server_name port data_size\n");
printf("Example:");
printf("\n\tlab1 -S 3000 100 64");
printf("\n\tlab1 -C MyServer 3000 64\n");
ExitProcess(0);
}
// функция: clparse
// назначение: разбор параметров командной строки
void clparse(int c, char** v)
{
if(c==5) if(!strcmp(v[1],"-S"))
{ //запуск программы как сервера
SERVER_PORT=atoi(v[2]), SERVER_ROLE=true;
serv_time=atoi(v[3]); data_size=atoi(v[4])*1024;
printf("Started as server, port=%d\n",SERVER_PORT);
printf("Process time: %i. Data size: %i\n",
serv_time,data_size);
return;
}
if(c==5) if(!strcmp(v[1],"-C"))
{ //запуск программы как клиента
SERVER_PORT=atoi(v[3]), SERVER_NAME=v[2];
data_size=atoi(v[4])*1024;
printf("Started as client, server=%s, port=%d\n",
SERVER_NAME,SERVER_PORT);
printf("Data size: %i\n",data_size);
return;
}
PrintUsage();
}
// функция: resaddr
// назначение: определение адреса хоста
void resaddr(sockaddr_in *addr)
{
hostent *he;
ZeroMemory(addr,sizeof(sockaddr_in));
// запрос адреса хоста по его имени
!(he=gethostbyname(SERVER_NAME)) && PrintError("gethostbyname");
CopyMemory(&addr->sin_addr, he->h_addr, sizeof(sockaddr_in));
addr->sin_family=AF_INET, addr->sin_port=htons(SERVER_PORT);
printf("host=%s, IP=%s\n",SERVER_NAME, inet_ntoa(addr->sin_addr));
}
// функция: server
// назначение: реализация сервера
void server()
{
char hostname[BUFSIZ];
sockaddr_in addr;
SOCKET sock;
int c=0; //счётчик клиентов
// получение имени компьютера, на котором запущена программа
gethostname(hostname,BUFSIZ) && PrintError("gethostname");
SERVER_NAME = new char[strlen(hostname)+1];
strcpy(SERVER_NAME,hostname);
resaddr(&addr);
// открытие серверного сокета
SOCKET_ERROR==(sock=socket(AF_INET,SOCK_STREAM,0))
&& PrintError("socket");
// привязка сокета к локальному адресу
SOCKET_ERROR==bind(sock,(sockaddr*)&addr,sizeof(addr))
&& PrintError("bind");
// включение прослушивания сети
SOCKET_ERROR==listen(sock,QUEUE_SIZE)
&& PrintError("listen");
for(;;)
{
char buf[MAX_DATA_SIZE];
sockaddr_in addr;
int sz=sizeof(addr);
// создание соединения с клиентом, приславшим запрос
SOCKET s=accept(sock,(sockaddr*)&addr,&sz);
printf("accepted=%d\n",c++);
// приём данных запроса от клиента
recv(s,buf,data_size,0);
// задержка на обработку информации
proc_time-=GetCurrentTime();
Sleep(serv_time);
proc_time+=GetCurrentTime();
// посылка клиенту результатов обработки запроса
send(s,buf,data_size,0);
DWORD total_time=GetCurrentTime()-start_time;
printf("Total time: %i, Process time: %i. ",
total_time,proc_time);
printf("Utilization: %i%%.\n",proc_time*100/total_time);
}
}
// функция: client
// назначение: реализация клиента
DWORD WINAPI client(void *)
{
SOCKET sock;
sockaddr_in addr;
char buf[MAX_DATA_SIZE];
static int i=0;
DWORD id=GetCurrentThreadId();
resaddr(&addr);
printf("thread_id=%04X\n",i++);
// создание клиентского сокета
SOCKET_ERROR==(sock=socket(AF_INET,SOCK_STREAM,0))
&& PrintError("socket");
// соединение с сервером
connect(sock,(sockaddr*)&addr,sizeof(sockaddr_in))
&& PrintError("connect");
*((DWORD*)buf)=id;
// посылка данных запроса серверу
send(sock,buf,data_size,0) || PrintError("send");
// принятие результатов обработки запроса
recv(sock,buf,data_size,0) || PrintError("recv");
*((DWORD*)buf)==id
&& printf("thread %04X success\n",*((DWORD*)buf)),g_success++;
// закрытие клиентского сокета (соответствующий сокет
// на сервере закрывается автоматически)
closesocket(sock);
return 0;
}
// функция: main
// назначение: точка входа
int main(int argc, char*argv[])
{
WSADATA wsad;
// разбор командной строки
clparse(argc,argv);
// инициализация библиотеки WinSock
if(WSAStartup(MAKEWORD(2,0),&wsad)) PrintError("WSAStartup");
start_time=GetCurrentTime();
// если программа запущена как сервер
if(SERVER_ROLE) server();
// иначе создать необходимое число клиентских потоков
else{
for(int i=0; i<PACKET_NUM; i++)
CreateThread(0,0,client,0,0,0), Sleep(CLIENT_TIMEOUT);
proc_time=serv_time*PACKET_NUM;
}
DWORD total_time=GetCurrentTime()-start_time;
// ожидание окончания обработки
Sleep(TIME_LIMIT);
// вывод статистики
printf("Sent %d, received %d.\n",
PACKET_NUM,g_success,((float)g_success*100)/PACKET_NUM);
scanf("%s",0);
return 0;
}