Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
6
Добавлен:
01.05.2014
Размер:
5.68 Кб
Скачать
//
//  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;
}
Соседние файлы в папке Lab1
  • #
    01.05.201426 б6ClientA.bat
  • #
    01.05.201427 б6ClientB.bat
  • #
    01.05.20145.68 Кб6Lab1.cpp
  • #
    01.05.20144.34 Кб6Lab1.dsp
  • #
    01.05.2014533 б6Lab1.dsw
  • #
    01.05.2014239.93 Кб6Lab1.ilk
  • #
    01.05.201450.18 Кб6Lab1.ncb
  • #
    01.05.201448.64 Кб6Lab1.opt