Основная часть
Постановка задачи
Целью данной курсовой работы является закрепление и углубление теоретических знаний в области современных операционных систем, приобретение практических навыков разработки клиент-серверных приложений, использующих стандартные механизмы межпроцессного взаимодействия.
Краткие теоретические основы разрабатываемой темы
«Клиент — сервер» (англ. client–server) — вычислительная или сетевая архитектура, в которой задания или сетевая нагрузка распределены между поставщиками услуг, называемыми серверами, и заказчиками услуг, называемыми клиентами. Фактически клиент и сервер — это программное обеспечение. Обычно эти программы расположены на разных вычислительных машинах и взаимодействуют между собой через вычислительную сеть посредством сетевых протоколов, но они могут быть расположены также и на одной машине. Программы-серверы ожидают от клиентских программ запросы и предоставляют им свои ресурсы в виде данных (например, загрузка файлов посредством HTTP, FTP, BitTorrent, потоковое мультимедиа или работа с базами данных) или в виде сервисных функций (например, работа с электронной почтой, общение посредством систем мгновенного обмена сообщениями или просмотр web-страниц во всемирной паутине). Поскольку одна программа-сервер может выполнять запросы от множества программ-клиентов, её размещают на специально выделенной вычислительной машине, настроенной особым образом, как правило, совместно с другими программами-серверами, поэтому производительность этой машины должна быть высокой. Из-за особой роли такой машины в сети, специфики её оборудования и программного обеспечения, её также называют сервером, а машины, выполняющие клиентские программы, соответственно, клиентами.
Преимущества
Отсутствие дублирования кода программы-сервера программами-клиентами.
Так как все вычисления выполняются на сервере, то требования к компьютерам, на которых установлен клиент, снижаются.
Все данные хранятся на сервере, который, как правило, защищён гораздо лучше большинства клиентов. На сервере проще организовать контроль полномочий, чтобы разрешать доступ к данным только клиентам с соответствующими правами доступа.
Недостатки
Неработоспособность сервера может сделать неработоспособной всю вычислительную сеть. Неработоспособным сервером следует считать сервер, производительности которого не хватает на обслуживание всех клиентов, а также сервер, находящийся на ремонте, профилактике и т. п.
Поддержка работы данной системы требует отдельного специалиста — системного администратора.
Высокая стоимость оборудования.
Разработка и описание алгоритма работы приложения
Сервера 1 и 2 запускаются на портах 27015 и 27016 соответственно и ожидают входящее соединение. После установления соединения передают данные клиенту.
Клиент соединяется с сервером и после получения данных разрывает соединение.
Описание структуры программы
В серверной части приложения определена функция, отвечающая за передачу данных клиенту. Используются функции send, connect, recv и другие.
В клиентской части также определена функция, отвечающая за отправку запроса на сервер и вывод полученного ответа.
Руководство пользователя
Прежде всего необходимо запустить оба сервера иначе данные не будут получены клиентом, для этого в приложениях серверов имеются соответствующие кнопки. Далее запустив клиент можно с помощью соответствующих кнопок получить данные от серверов.
Результаты применения программы
Рисунок 1 - Первый сервер
Рисунок 2 - Второй сервер
Рисунок 3 – Клиент
Заключение
В результате данной курсовой работы были закреплены и углублены теоретических знаний в области современных операционных систем, приобретены практические навыки разработки клиент-серверных приложений, использующих стандартный механизм межпроцессного взаимодействия - сокет.
Список использованных источников
Э.Таненбаум. Современные операционные системы. 3-изд. – СПб.: Питер, 2011
http://ru.wikipedia.org/wiki/Клиент-сервер
http://msdn.microsoft.com
Приложение А
первый сервер #undef UNICODE #include <stdlib.h> #include <stdio.h> #include <iostream> #pragma comment(lib, "user32.lib") using namespace std; // Need to link with Ws2_32.lib #pragma comment (lib, "Ws2_32.lib") // #pragma comment (lib, "Mswsock.lib") #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27015" #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <winternl.h> #include <cstdio> #pragma comment (lib, "User32.lib") char recvbuf[200]; int main () { setlocale(LC_ALL, "rus"); TCHAR compname[256]; DWORD compname_len = 256; GetComputerName((TCHAR*)compname, &compname_len); TCHAR username[256]; DWORD username_len = 256; GetUserName((TCHAR*)username, &username_len); char str1[80]; sprintf(str1,"Имя компьютера: %s\nИмя пользователя: %s\n\n",compname,username); cout«str1; char str2[80]; NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW); OSVERSIONINFOEXW osInfo; *(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion"); if (NULL != RtlGetVersion) { osInfo.dwOSVersionInfoSize = sizeof(osInfo); RtlGetVersion(&osInfo); sprintf(str2,"Версия ОС: %d\n",osInfo.dwMajorVersion); cout « str2«endl; } sprintf(recvbuf,"%s%s\n",str1,str2); for(;;) { WSADATA wsaData; int iResult; SOCKET ListenSocket = INVALID_SOCKET; SOCKET ClientSocket = INVALID_SOCKET; char recvbuf1[200]; int recvbuflen1 = sizeof(recvbuf1); struct addrinfo *result = NULL; struct addrinfo hints; char str[100]; int iSendResult; int recvbuflen = sizeof(recvbuf); // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { sprintf(str,"WSAStartup failed with error: %d\r\n", iResult); cout«str; return 1; } ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; // Resolve the server address and port iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); if ( iResult != 0 ) { sprintf(str,"getaddrinfo failed with error: %d\r\n", iResult); cout«str; WSACleanup(); return 1; } // Create a SOCKET for connecting to server ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { sprintf(str,"socket failed with error: %ld\r\n", WSAGetLastError()); cout«str; freeaddrinfo(result); WSACleanup(); return 1; } // Setup the TCP listening socket iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { sprintf(str,"bind failed with error: %d\r\n", WSAGetLastError()); cout«str; freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return 1; } freeaddrinfo(result); iResult = listen(ListenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { sprintf(str,"listen failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ListenSocket); WSACleanup(); return 1; } // Accept a client socket ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { sprintf(str,"accept failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ListenSocket); WSACleanup(); return 1; } // No longer need server socket closesocket(ListenSocket); // Receive until the peer shuts down the connection do { iResult = recv(ClientSocket, recvbuf1, recvbuflen1, 0); if (iResult > 0) { sprintf(str,"Bytes received: %d\r\n", iResult); cout«str; // Echo the buffer back to the sender iSendResult = send( ClientSocket, recvbuf, recvbuflen, 0 ); if (iSendResult == SOCKET_ERROR) { sprintf(str,"send failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ClientSocket); WSACleanup();
return 1; } sprintf(str,"Bytes sent: %d\r\n", iSendResult); cout«str; } else if (iResult == 0){ sprintf(str,"Connection closing...\r\n"); cout«str; } else { sprintf(str,"recv failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ClientSocket); WSACleanup(); return 1; } } while (iResult > 0); // shutdown the connection since we're done iResult = shutdown(ClientSocket, SD_SEND); if (iResult == SOCKET_ERROR) { sprintf(str,"shutdown failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ClientSocket); WSACleanup(); return 1; } // cleanup closesocket(ClientSocket); WSACleanup(); cout«"\n"; } return 0; }
второй сервер #undef UNICODE #include <stdlib.h> #include <stdio.h> #include <iostream> #pragma comment(lib, "user32.lib") using namespace std; // Need to link with Ws2_32.lib #pragma comment (lib, "Ws2_32.lib") // #pragma comment (lib, "Mswsock.lib") #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27016" #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <winternl.h> #include <cstdio> #pragma comment (lib, "User32.lib") char recvbuf[200]; int main () { setlocale(LC_ALL, "rus"); MEMORYSTATUSEX statex; statex.dwLength = sizeof (statex); GlobalMemoryStatusEx (&statex); char str1[80]; sprintf(str1,"Процент используемой физической памяти : %d%\nПроцент используемой виртуальной памяти: %d%\n",statex.dwMemoryLoad,((statex.ullTotalVirtual-statex.ullAvailVirtual)/(statex.ullTotalVirtual/100))); cout«str1«endl; sprintf(recvbuf,"%s\n",str1); for(;;) { WSADATA wsaData; int iResult; SOCKET ListenSocket = INVALID_SOCKET; SOCKET ClientSocket = INVALID_SOCKET; char recvbuf1[200]; int recvbuflen1 = sizeof(recvbuf1); struct addrinfo *result = NULL; struct addrinfo hints; char str[100]; int iSendResult; int recvbuflen = sizeof(recvbuf); // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { sprintf(str,"WSAStartup failed with error: %d\r\n", iResult); cout«str; return 1; } ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; // Resolve the server address and port iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); if ( iResult != 0 ) { sprintf(str,"getaddrinfo failed with error: %d\r\n", iResult); cout«str; WSACleanup(); return 1; } // Create a SOCKET for connecting to server ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (ListenSocket == INVALID_SOCKET) { sprintf(str,"socket failed with error: %ld\r\n", WSAGetLastError()); cout«str; freeaddrinfo(result); WSACleanup(); return 1; } // Setup the TCP listening socket iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { sprintf(str,"bind failed with error: %d\r\n", WSAGetLastError()); cout«str; freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return 1; } freeaddrinfo(result); iResult = listen(ListenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { sprintf(str,"listen failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ListenSocket); WSACleanup(); return 1; } // Accept a client socket ClientSocket = accept(ListenSocket, NULL, NULL); if (ClientSocket == INVALID_SOCKET) { sprintf(str,"accept failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ListenSocket); WSACleanup(); return 1; } // No longer need server socket closesocket(ListenSocket); // Receive until the peer shuts down the connection do { iResult = recv(ClientSocket, recvbuf1, recvbuflen1, 0); if (iResult > 0) { sprintf(str,"Bytes received: %d\r\n", iResult); cout«str; // Echo the buffer back to the sender iSendResult = send( ClientSocket, recvbuf, recvbuflen, 0 ); if (iSendResult == SOCKET_ERROR) { sprintf(str,"send failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ClientSocket); WSACleanup(); return 1; } sprintf(str,"Bytes sent: %d\r\n", iSendResult); cout«str; } else if (iResult == 0){ sprintf(str,"Connection closing...\r\n"); cout«str; } else { sprintf(str,"recv failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ClientSocket); WSACleanup(); return 1; }
// shutdown the connection since we're done iResult = shutdown(ClientSocket, SD_SEND); if (iResult == SOCKET_ERROR) { sprintf(str,"shutdown failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ClientSocket); WSACleanup(); return 1; } // cleanup closesocket(ClientSocket); WSACleanup(); cout«"\n"; } return 0; }
клиент #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <stdlib.h> #include <stdio.h> #include <iostream> using namespace std; #pragma comment (lib, "Ws2_32.lib") #pragma comment (lib, "Mswsock.lib") #pragma comment (lib, "AdvApi32.lib") #define DEFAULT_BUFLEN 512 #define DEFAULT_PORT "27015" #define DEFAULT_PORT1 "27016" int main () { setlocale(LC_ALL, "rus"); int a=-1; while (a != 0) { cout «"Выберите нужный пункт:\n"« "1) Получение информации с первого сервера" « endl « "2) Получение информации со второго сервера" « endl « "0) Выход" « endl ; cout « "Введите номер пункта: "; cin » a; switch (a) { case 0: { break; } case 1 : { WSADATA wsaData; SOCKET ConnectSocket = INVALID_SOCKET; struct addrinfo *result = NULL, *ptr = NULL, hints; char *sendbuf = "this is a test"; char recvbuf[DEFAULT_BUFLEN]; int iResult; int recvbuflen = DEFAULT_BUFLEN; char str[100]; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { sprintf(str,"WSAStartup failed with error: %d\r\n", iResult); cout«str; system ("pause"); return 1; } ZeroMemory( &hints, sizeof(hints) ); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; // Resolve the server address and port iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result); if ( iResult != 0 ) { sprintf(str,"getaddrinfo failed with error: %d\r\n", iResult); cout«str; WSACleanup(); system ("pause"); return 1; } // Attempt to connect to an address until one succeeds for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { // Create a SOCKET for connecting to server ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { sprintf(str,"socket failed with error: %ld\r\n", WSAGetLastError()); cout«str; WSACleanup(); system ("pause"); return 1; } // Connect to server. iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; continue; } break; } freeaddrinfo(result); if (ConnectSocket == INVALID_SOCKET) { sprintf(str,"Unable to connect to server!\r\n"); cout«str; WSACleanup(); system ("pause"); return 1; } // Send an initial buffer iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 ); if (iResult == SOCKET_ERROR) { sprintf(str,"send failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ConnectSocket); WSACleanup(); system ("pause"); return 1; } sprintf(str,"Bytes Sent: %ld\r\n", iResult); cout«str; // shutdown the connection since no more data will be sent iResult = shutdown(ConnectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { sprintf(str,"shutdown failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ConnectSocket); WSACleanup(); system ("pause"); return 1; } // Receive until the peer closes the connection do { iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); if ( iResult > 0 ){ sprintf(str,"Bytes received: %d\r\n", iResult); cout«str; cout«recvbuf; } else if ( iResult == 0 ) { sprintf(str,"Connection closed\r\n"); cout«str; } else { sprintf(str,"recv failed with error: %d\r\n", WSAGetLastError()); cout«str; } } while( iResult > 0 ); // cleanup closesocket(ConnectSocket); WSACleanup(); system ("pause");
break; } case 2 : { WSADATA wsaData; SOCKET ConnectSocket = INVALID_SOCKET; struct addrinfo *result = NULL, *ptr = NULL, hints; char *sendbuf = "this is a test"; char recvbuf[DEFAULT_BUFLEN]; int iResult; int recvbuflen = DEFAULT_BUFLEN; char str[100]; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { sprintf(str,"WSAStartup failed with error: %d\r\n", iResult); cout«str; system ("pause"); return 1; } ZeroMemory( &hints, sizeof(hints) ); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; // Resolve the server address and port iResult = getaddrinfo("localhost", DEFAULT_PORT1, &hints, &result); if ( iResult != 0 ) { sprintf(str,"getaddrinfo failed with error: %d\r\n", iResult); cout«str; WSACleanup(); system ("pause"); return 1; } // Attempt to connect to an address until one succeeds for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { // Create a SOCKET for connecting to server ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (ConnectSocket == INVALID_SOCKET) { sprintf(str,"socket failed with error: %ld\r\n", WSAGetLastError()); cout«str; WSACleanup(); system ("pause"); return 1; } // Connect to server. iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; continue; } break; } freeaddrinfo(result); if (ConnectSocket == INVALID_SOCKET) { sprintf(str,"Unable to connect to server!\r\n"); cout«str; WSACleanup(); system ("pause"); return 1; } // Send an initial buffer iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 ); if (iResult == SOCKET_ERROR) { sprintf(str,"send failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ConnectSocket); WSACleanup(); system ("pause"); return 1; } sprintf(str,"Bytes Sent: %ld\r\n", iResult); cout«str; // shutdown the connection since no more data will be sent iResult = shutdown(ConnectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { sprintf(str,"shutdown failed with error: %d\r\n", WSAGetLastError()); cout«str; closesocket(ConnectSocket); WSACleanup(); system ("pause"); return 1; } // Receive until the peer closes the connection do { iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); if ( iResult > 0 ){ sprintf(str,"Bytes received: %d\r\n", iResult); cout«str; cout«recvbuf; } else if ( iResult == 0 ) { sprintf(str,"Connection closed\r\n"); cout«str; } else { sprintf(str,"recv failed with error: %d\r\n", WSAGetLastError()); cout«str; } } while( iResult > 0 ); // cleanup closesocket(ConnectSocket); WSACleanup(); system ("pause"); break; } } } return 0; }