Исходный текст
|
Описание
|
char szBuf[512];
|
Буфер для обменов информацией
|
DWORD cbWritten;
|
Количество байтов, записанных в буфер
|
static HWND hwndEdit;
|
Дескриптор поля редактирования
|
TCHAR mess[2048];
|
Буфер формирования сообщений на экран
|
TCHAR* m_mess = mess;
|
Ссылка на буфер
|
#define SERV_PORT 5000
|
Значение номера порта сокета
|
#define WSA_NETEVENT (WM_USER+1)
|
Значение кода сообщения о сетевом событии
|
WSADATA wsaData;
|
сведения о конкретной реализации интерфейса Windows Sockets
|
WORD wVersionRequested = MAKEWORD(
1, 1 );
|
Номер требуемой версии Windows Sockets
|
int err=0;
|
Код ошибки
|
SOCKET cln_socket=INVALID_SOCKET;
|
Сокет
сервера
|
static PHOSTENT phe;
|
Дескриптор компьютера, на котором запущена программа-сервер
|
SOCKADDR_IN dest_sin;
|
Адрес
сервера
|
char szHostName[128] =
"localhost";
|
имя хоста
|
.3.3.2Процедура соединения с сервером
Схема алгоритма представлена на рисунке 1.5. Процедурой выполняются
следующие функции:
¾ создание структуры данных для сокета и получения дескриптора
сокета;
¾ определение адреса хоста;
¾ задание типа и значения адреса и номера порта для сокета;
¾ установка соединения с сервером;
¾ установка режима асинхронного взаимодействия с сокетом.
В процедуре создается потоковый сокет и задается структура для хранения
адресных данных (блоки 1-5, рисунок 1.5.
С помощью функции gethostbyname по известному имени компьютера в сети
определяется его сетевой адрес. Для отладки программ удобно размещать и
серверную, и клиентскую программы на одном локальном компьютере. В этом случае
задается имя “localhost”. Если серверная и клиентские программы размещаются на
разных компьютерах сети, то в качестве имени хоста можно задать сразу IP адрес
компьютера-хоста. Эти действия реализованы блоками 6 - 9 на рисунке 1.5 .
Для сокета определяется Интернет семейство адресов. Номер порта выбран из
области свободно используемых значений и равен 5000. С помощью функции htons
порядок байтов этого значения преобразуется в сетевой порядок байтов - первым
идет старший байт. Адрес хоста копируется в структуру данных сокета. Эти
действия реализуются блоками 10-11 на рисунке 1.5 .
Соединение сокета с сервером реализуются блоками 12-15 на рисунке 1.5 .
Установка режима асинхронного взаимодействия с сокетом реализуются блоками
16-21 на рисунке 1.5 .
Рисунок 1.5 - Схема алгоритма процедуры соединения с сервером
1.3.3.3Процедура посылки информации серверу
Схема алгоритма представлена на рисунке 1.6. С помощью системной функции
SendMessage определяется длина блока информации для сервера и выполняется
пересылка этого блока в буфер. С помощью функции send выполняется пересылка
информации серверу и в зависимости от результата выполнения функции выводится
сообщение на экран. Эти действия реализуются блоками 1-8 на рисунке 1.6.
Рисунок 1.6 - Схема алгоритма процедуры посылки информации серверу
.3.3.4«Оконная» процедура программы-клиента
Схема алгоритма представлена на рисунке 1.7. В схеме алгоритма отражены
только действия, связанные с сокетами.
При создании окна приложения-клиента создается также поле ввода,
редактирования и отображения текста, подключается библиотека работы с сокетами
и о результате подключения выводится сообщение. Эти действия реализованы
блоками 3 - 7 на рисунке 1.7.
Организована обработка сообщений WSA_NETEVENT - о сетевом событии от
сокета. Анализируется принятый код события. Если это код чтения данных, то
вызывается функция recv приема информации из сокета в буфер. Если это код
завершения работы сервера, то выводится сообщение на экран. Эти действия
реализованы блоками 10 - 14 на рисунке 1.7.
При обработке сообщения WM_DESTROY о закрытии окна приложения-клиента
является то, что предварительно надо отключиться от библиотеки работы с
сокетами. Эти действия реализованы блоками 15 - 17 на рисунке 1.7. При
получении сообщения WM_COMMAND о поступлении команды выполняется ее
декодирование и организовывается переключатель для выбора процедуры обработки в
зависимости от кода команды. Эти действия реализованы блоками 18 - 22 на рисунке
1.7.
Рисунок 1.7 - Схема алгоритма «оконной» процедуры программы-клиента
1.4 Результаты применения программы
Разработка и отладка программы выполнялась в среде Microsoft Visual
Studio. Разработано одно приложение-сервер и два приложения клиента, которые
подтвердили свою работоспособность. Копии экранов работающих приложений
приведены на рисунке 1.8.
Рисунок 1.8 - Копии экранов серверного и клиентских приложений
ВЫВОДЫ
В ходе выполнения курсовой роботы получены положительные результаты.
Разработано и отлажено 3 приложения. Приложение - сервер выполняет такие
функции:
¾ создание сокетов;
¾ получение информации от приложений - клиентов;
¾ вывод на экран полученных результатов.
Приложение - клиент 1 выполняет такие функции:
¾ открытие сокета;
¾ установка соединения с сервером;
¾ подготовка и передача такой системной информации:) системные
цвета 2-х элементов окна приложения;) код раскладки клавиатуры.
Приложение - клиент 1 выполняет такие функции:
¾ открытие сокета;
¾ установка соединения с сервером;
¾ подготовка и передача такой системной
информации:)идентификатор текущего процесса;)дескриптор текущего процесса.
ПЕРЕЧЕНЬ
ССЫЛОК
1. http://www.rsdn.ru/article/baseserv/mt.xml
. http://vunivere.ru/work11218
3. Методические указания к курсовой работе по дисциплине
"Системное программное обеспечение" (для студентов дневной и заочной
формы обучения, обучающихся по направлению 6.050102 «Компьютерная инженерия» /
Сост.: Брежнев А.М. - Северодонецк: 2013. - 71 с.
. http://frolov-lib.ru/books/bsp/v23/ch5_3.html
. http://gendocs.ru/v31765/?cc=32
. http://life-prog.ru/view_linux.php?id=23
ПРИЛОЖЕНИЯ
Приложение А
Распечатка программы сервера
1. // Сервер.cpp: определяет точку входа для приложения.
. //
. #include "stdafx.h"
. #include "Сервер.h"
. #include <windows.h>
. #include <windowsx.h>
. #include <winsock.h>
. #include <commctrl.h>
. #include <stdlib.h>
. #include <stdio.h>
. char szBuf[512];
. DWORD cbWritten;
. static HWND hwndEdit;
. TCHAR mess[2048];
. TCHAR* m_mess = mess;
. #define SERV_PORT 5000// Порт сервера
. #define WSA_ACCEPT (WM_USER+0)
. #define WSA_NETEVENT (WM_USER+1)
. #define MAX_LOADSTRING 100
. WSADATA wsaData; //сведения о конкр. реализации интерфейса
Windows Sockets
. WORD wVersionRequested = MAKEWORD(1, 1); //Номер
требуемой версии Windows Sockets
. int err=0;
. SOCKET srv_socket=INVALID_SOCKET; // Сокет сервера
. int ClientNum = -1;// Номер последнего клиента
. SOCKET sock[2];// Сокеты клиентов
. SOCKADDR_IN sockaddr[2];// Адреса клиентов
. // Глобальные переменные:
. HINSTANCE hInst;// текущий экземпляр
. TCHAR szTitle[MAX_LOADSTRING]; // Текст строки
заголовка
. TCHAR szWindowClass[MAX_LOADSTRING];// имя класса
главного окна
. HWND hWindow;
. // Отправить объявления функций, включенных в этот
модуль кода:
. ATOMMyRegisterClass(HINSTANCE hInstance);
. BOOLInitInstance(HINSTANCE, int);
. LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);
. INT_PTR CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);
. int APIENTRY _tWinMain(HINSTANCE hInstance,
. HINSTANCE hPrevInstance,
. LPTSTR lpCmdLine,
. int nCmdShow)
. {
. UNREFERENCED_PARAMETER(hPrevInstance);
. UNREFERENCED_PARAMETER(lpCmdLine);
. // TODO: разместите код здесь.
. MSG msg;
. HACCEL hAccelTable;
. // Инициализация глобальных строк
. LoadString(hInstance, IDS_APP_TITLE, szTitle,
MAX_LOADSTRING);
. LoadString(hInstance, IDC_MY, szWindowClass,
MAX_LOADSTRING);
. MyRegisterClass(hInstance);
. // Выполнить инициализацию приложения:
. if (!InitInstance (hInstance, nCmdShow))
. {
. return FALSE;
. }
. hAccelTable = LoadAccelerators(hInstance,
MAKEINTRESOURCE(IDC_MY));
. // Цикл основного сообщения:
. while (GetMessage(&msg, NULL, 0, 0))
. {
. if (!TranslateAccelerator(msg.hwnd, hAccelTable,
&msg))
. {
. TranslateMessage(&msg);
. DispatchMessage(&msg);
. }
. }
. return (int) msg.wParam;
. }
. //
. // ФУНКЦИЯ: MyRegisterClass()
. //
. // НАЗНАЧЕНИЕ: регистрирует класс окна.
. //
. // КОММЕНТАРИИ:
. //
. // Эта функция и ее использование необходимы только
в случае, если нужно, чтобы данный код
. // был совместим с системами Win32, не имеющими
функции RegisterClassEx'
. // которая была добавлена в Windows 95. Вызов этой
функции важен для того,
. // чтобы приложение получило
"качественные" мелкие значки и установило связь
. // с ними.
. //
. ATOM MyRegisterClass(HINSTANCE hInstance)
. {
. WNDCLASSEX wcex;
. wcex.cbSize = sizeof(WNDCLASSEX);
. wcex.style= CS_HREDRAW | CS_VREDRAW;
. wcex.lpfnWndProc= WndProc;
. wcex.cbClsExtra= 0;
. wcex.cbWndExtra= 0;
. wcex.hInstance= hInstance;
. wcex.hIcon= LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_MY));
. wcex.hCursor= LoadCursor(NULL, IDC_ARROW);
. wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
. wcex.lpszMenuName= MAKEINTRESOURCE(IDC_MY);
. wcex.lpszClassName= szWindowClass;
. return RegisterClassEx(&wcex);
. }
. //
. // ФУНКЦИЯ: InitInstance(HINSTANCE, int)
. //
. // НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и
создает главное окно.
. //
. // КОММЕНТАРИИ:
. //
. В данной функции дескриптор экземпляра сохраняется в
глобальной переменной, а также
. // создается и выводится на экран главное окно
программы.
. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
. {
. HWND hWnd;
. hInst = hInstance; // Сохранить дескриптор
экземпляра в глобальной переменной
. hWnd = CreateWindow(szWindowClass, szTitle,
WS_OVERLAPPEDWINDOW,
. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL,
hInstance, NULL);
. if (!hWnd)
. {
. return FALSE;
. }
. hWindow=hWnd;
. ShowWindow(hWnd, nCmdShow);
. UpdateWindow(hWnd);
. return TRUE;
. }
. void ServerStart( HWND hWnd )
. {
. if(srv_socket != INVALID_SOCKET )
. {
. MessageBox( hWnd, "Socket уже есть",
"Info", MB_OK | MB_ICONINFORMATION );
. return;
. }
. // создаем сокет сервера для работы с потоком данных
. srv_socket = socket( AF_INET, SOCK_STREAM, 0 );
. if( srv_socket == INVALID_SOCKET )
. {
. MessageBox( hWnd, "Ошибка создания
сокета!!!", "Error", MB_OK | MB_ICONERROR );
. return;
. }
. // Устанавливаем адрес IP и номер порта
. SOCKADDR_IN srv_address;
. srv_address.sin_family = AF_INET;
. srv_address.sin_port = htons( SERV_PORT );
. srv_address.sin_addr.s_addr = INADDR_ANY; // исп.
адрес по умолчанию (т.е. любой)
. // Связываем адрес IP с сокетом
. if(SOCKET_ERROR ==bind(srv_socket,(LPSOCKADDR)
&srv_address, sizeof(srv_address) ) )
. {
. closesocket( srv_socket );
. MessageBox( hWnd, "Ошибка связывания с
портом", "Error", MB_OK | MB_ICONSTOP );
. return;
. }
. // ожидаем установки связи
. if( listen( srv_socket, 4 ) == SOCKET_ERROR )
. {
. closesocket( srv_socket );
. MessageBox( hWnd, "Ошибка ожидания установки
связи","Error", MB_OK );
. return;
. }
. // при попытке соединения главное окно получит
сообщение WSA_ACCEPT
. int rc = WSAAsyncSelect( srv_socket, hWnd,
WSA_ACCEPT, FD_ACCEPT );
. if( rc )
. {
. closesocket( srv_socket );
. MessageBox( hWnd, "WSAAsyncSelect
error","Error", MB_OK );
. return;
. }
. // Выводим сообщение о запуске сервера
. SendMessage( hwndEdit, WM_SETTEXT, 0, ( LPARAM )
"Сервер запущен" );
. }
. void ServerStop( HWND hWnd )
. {
. // отменяем приход сообщений в главную функцию окна
при возникновении
. // любых событий, связанных с системой Windows
Sockets
. WSAAsyncSelect( srv_socket, hWnd, 0, 0 );
. if( srv_socket != INVALID_SOCKET ) // если сокет был
создан, закрываем его
. {
. closesocket( srv_socket );
. srv_socket = INVALID_SOCKET;
. }
. // выводим сообщение об останове сервера
. SendMessage( hwndEdit, WM_SETTEXT, 0, (LPARAM)
"Сервер остановлен" );
. }
. BOOL AcceptClient(int j)// присоединить клиента
. {
. int sockaddr_len = sizeof( sockaddr[j] );
. sock[j]=accept(
srv_socket,(LPSOCKADDR)&sockaddr[j],(int FAR*)&sockaddr_len );
. if( sock[j] != INVALID_SOCKET )
. if(!WSAAsyncSelect( sock[j],hWindow,WSA_NETEVENT,
FD_READ | FD_CLOSE ))
. return TRUE;
. closesocket( sock[j] );
. return FALSE;
. }
. void DisconnectClient(int j)// отключить клиента
. {
. WSAAsyncSelect( sock[j], hWindow, 0, 0 );
. closesocket(sock[j]);
. }
. void WndProc_OnWSAAccept( HWND hWnd, LPARAM lParam )
. {
. // при ошибке отменяем поступление сообщений в
главное окно приложения
. if( WSAGETSELECTERROR( lParam ) ){
. MessageBox( hWnd, "accept error",
"Error", MB_OK );
. WSAAsyncSelect( srv_socket, hWnd, 0, 0 );
. return;
. }
. if( ClientNum == 1){
. MessageBox( hWnd,"число клиентов
>2\r\n", "Соединение недопустимо!", MB_OK );
. return;
. }
. ClientNum++;
. if(!AcceptClient(ClientNum) ){
. MessageBox( hWnd, "Ошибка соед с
клиентом", "Error", MB_OK );
. return;
. }
. // добавляем клиента
. sprintf(szBuf, "Добавлен клиент %i\r\nАдрес:
IP=%s Port=%u\r\n \0", ClientNum+1,
. inet_ntoa(sockaddr[ClientNum].sin_addr),
htons(sockaddr[ClientNum].sin_port));
. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)szBuf);
. }
. void WndProc_OnWSANetEvent( HWND hWnd, WPARAM
wParam, LPARAM lParam )
. {
. char szTemp[256], szMess[256];
. int Number;
. // узнаем от какого клиента пришло сообщение, =>
Number
. if( sock[0]==(SOCKET) wParam ) Number=0;
. else if( sock[1]==(SOCKET) wParam ) Number=1;
. // если на сокете выполняется передача данных,
принимаем и отображаем их
. if( WSAGETSELECTEVENT( lParam ) == FD_READ )
. {
. int rc = recv( (SOCKET) wParam, szTemp, 256, 0 );
. if(rc){
. szTemp[rc]='\0';
. sprintf( m_mess, "%s \r\n Данные от Клиента
%i:\r\n%s", m_mess, Number+1,szTemp );
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)m_mess);
. }
. }
. // если соединение завершено, выводим сообщение об
этом
. if( WSAGETSELECTEVENT( lParam ) == FD_CLOSE )
. {
. WSAAsyncSelect( sock[Number], hWindow, 0, 0 );
. closesocket(sock[Number]);
. sprintf( szTemp, "Клиент %i завершил
работу", Number+1 );
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)szTemp);
. }
. }
. void SendToClient(int j)
. {
. if(j>ClientNum) return;
. cbWritten = SendMessage(hwndEdit,WM_GETTEXTLENGTH,0,0);
. SendMessage(hwndEdit, WM_GETTEXT, (WPARAM)
cbWritten, (LPARAM) szBuf);
. szBuf[cbWritten]='\0';
. if( send(sock[j],szBuf,lstrlen(szBuf),0) !=
SOCKET_ERROR)
. {
. sprintf(szBuf, "Данные отосланы клиенту %d\r\n
%s",j+1,szBuf);
. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)szBuf);
. }
. else
. SendMessage(hwndEdit,WM_SETTEXT, 0,
(LPARAM)"Ошибка отправки сообщения \r\n");
. }
. void ClientOff(HWND hWnd, int j)
. {
. if(j>ClientNum) return;
. sprintf( szBuf, "Отключить Клиента %i?",
j+1 );
. if( IDYES == MessageBox( hWnd, szBuf,
"Question", MB_YESNO | MB_ICONQUESTION ) )
. DisconnectClient(j);
. ClientNum--;
. }
. //
. // ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
. //
. // НАЗНАЧЕНИЕ: обрабатывает сообщения в главном
окне.
. //
. // WM_COMMAND- обработка меню приложения
. // WM_PAINT-Закрасить главное окно
. // WM_DESTROY - ввести сообщение о выходе и
вернуться.
. //
. //
. LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
. {
. int wmId, wmEvent;
. PAINTSTRUCT ps;
. HDC hdc;
. switch (message)
. {
. case WM_CREATE:
. hwndEdit = CreateWindow( // Создаем доч.окно для
вывода данных от процессов
. TEXT("EDIT"), NULL,
. WS_CHILD | WS_VISIBLE | WS_VSCROLL |
. ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
. 0, 0, 400, 200, hWnd, NULL, hInst, NULL);
. err = WSAStartup( wVersionRequested, &wsaData );
. if( err ){
. MessageBox( hWnd, "WSAStartup
Error","ERROR", MB_OK | MB_ICONSTOP );
. return FALSE;
. }
. sprintf(m_mess, "Используется %s \r\nСтатус:
%s\r\n",
. wsaData.szDescription, wsaData.szSystemStatus);
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)m_mess);
. break;
. case WM_COMMAND:
. wmId = LOWORD(wParam);
. wmEvent = HIWORD(wParam);
. // Разобрать выбор в меню:
. switch (wmId)
. {
. case ID_32771:
. ServerStart( hWnd );
. break;
. case ID_32772:
. ServerStop( hWnd );
. break;
. case ID_32773:
. SendToClient(0);
. break;
. case ID_32774:
. SendToClient(1);
. break;
. case ID_32775:
. ClientOff(hWnd, 0);
. break;
. case ID_32776:
. ClientOff(hWnd, 1);
. break;
. case IDM_ABOUT:
. DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX),
hWnd, About);
. break;
. case IDM_EXIT:
. DestroyWindow(hWnd);
. break;
. default:
. return DefWindowProc(hWnd, message, wParam, lParam);
. }
. break;
. case WM_PAINT:
. hdc = BeginPaint(hWnd, &ps);
. // TODO: добавьте любой код отрисовки...
. EndPaint(hWnd, &ps);
. break;
. case WM_DESTROY:
. WSACleanup( );
. PostQuitMessage(0);
. break;
. case WSA_ACCEPT:
. WndProc_OnWSAAccept( hWnd, lParam );
. break;
. case WSA_NETEVENT:
. WndProc_OnWSANetEvent( hWnd, wParam, lParam );
. break;
. default:
. return DefWindowProc(hWnd, message, wParam, lParam);
. }
. return 0;
. }
. // Обработчик сообщений для окна "О
программе".
. INT_PTR CALLBACK About(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
. {
. UNREFERENCED_PARAMETER(lParam);
. switch (message)
. {
. case WM_INITDIALOG:
. return (INT_PTR)TRUE;
. case WM_COMMAND:
. if (LOWORD(wParam) == IDOK || LOWORD(wParam) ==
IDCANCEL)
. {
. EndDialog(hDlg, LOWORD(wParam));
. return (INT_PTR)TRUE;
. }
. break;
. }
. return (INT_PTR)FALSE;
. }
.
Приложение Б
Распечатка программы клиента 1
. // Клиент1.cpp: определяет точку входа для
приложения.
. //
. #include "stdafx.h"
. #include "Клиент1.h"
. #include <winsock.h>
. #include <process.h>
. #include <stdio.h>
. #include <windows.h>
. #include <tchar.h>
. #include <string.h>
. #include <iostream>
. char szBuf[512];
. DWORD cbWritten;
. int flag = 0;
. static HWND hwndEdit;
. TCHAR mess[2048];
. TCHAR* m_mess = mess;
. int wmId, wmEvent;
. PAINTSTRUCT ps;
. HDC hdc;
. HWND hwnd;
. RECT rt;
. #define SERV_PORT 5000// Порт сервера
. #define WSA_NETEVENT (WM_USER+1)
. WSADATA wsaData; //сведения о конкретной реализации
интерфейса Windows Sockets
. WORD wVersionRequested = MAKEWORD( 1, 1 ); //Номер
требуемой версии Windows Sockets
. int err=0;
. SOCKET cln_socket=INVALID_SOCKET; // Сокет сервера
. static PHOSTENT phe;
. SOCKADDR_IN dest_sin; // Адрес сервера
. char szHostName[128] = "localhost"; //имя
хоста
. #define MAX_LOADSTRING 100
. // Глобальные переменные:
. HINSTANCE hInst;// текущий экземпляр
. TCHAR szTitle[MAX_LOADSTRING];// Текст строки
заголовка
. TCHAR szWindowClass[MAX_LOADSTRING];// имя класса
главного окна
. // Отправить объявления функций, включенных в этот
модуль кода:
. ATOMMyRegisterClass(HINSTANCE hInstance);
. BOOLInitInstance(HINSTANCE, int);
. LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);
. INT_PTR CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);
. int APIENTRY _tWinMain(HINSTANCE hInstance,
. HINSTANCE hPrevInstance,
. LPTSTR lpCmdLine,
. int nCmdShow)
. {
. UNREFERENCED_PARAMETER(hPrevInstance);
. UNREFERENCED_PARAMETER(lpCmdLine);
. // TODO: разместите код здесь.
. MSG msg;
. HACCEL hAccelTable;
. // Инициализация глобальных строк
. LoadString(hInstance, IDS_APP_TITLE, szTitle,
MAX_LOADSTRING);
. LoadString(hInstance, IDC_MY1, szWindowClass,
MAX_LOADSTRING);
. MyRegisterClass(hInstance);
. // Выполнить инициализацию приложения:
. if (!InitInstance (hInstance, nCmdShow))
. {
. return FALSE;
. }
. hAccelTable = LoadAccelerators(hInstance,
MAKEINTRESOURCE(IDC_MY1));
. // Цикл основного сообщения:
. while (GetMessage(&msg, NULL, 0, 0))
. {
. if (!TranslateAccelerator(msg.hwnd, hAccelTable,
&msg))
. {
. TranslateMessage(&msg);
. DispatchMessage(&msg);
. }
. }
. return (int) msg.wParam;
. }
. //
. // ФУНКЦИЯ: MyRegisterClass()
. //
. //
. // КОММЕНТАРИИ:
. //
. // Эта функция и ее использование необходимы только
в случае, если нужно, чтобы данный код
. // был совместим с системами Win32, не имеющими
функции RegisterClassEx'
. // которая была добавлена в Windows 95. Вызов этой
функции важен для того,
. // чтобы приложение получило
"качественные" мелкие значки и установило связь
. // с ними.
. //
. ATOM MyRegisterClass(HINSTANCE hInstance)
. {
. WNDCLASSEX wcex;
. wcex.cbSize = sizeof(WNDCLASSEX);
. wcex.style= CS_HREDRAW | CS_VREDRAW;
. wcex.lpfnWndProc= WndProc;
. wcex.cbClsExtra= 0;
. wcex.cbWndExtra= 0;
. wcex.hInstance= hInstance;
. wcex.hIcon= LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_MY1));
. wcex.hCursor= LoadCursor(NULL, IDC_ARROW);
. wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
. wcex.lpszMenuName= MAKEINTRESOURCE(IDC_MY1);
. wcex.lpszClassName= szWindowClass;
. wcex.hIconSm= LoadIcon(wcex.hInstance,
MAKEINTRESOURCE(IDI_SMALL));
. return RegisterClassEx(&wcex);
. }
. //
. // ФУНКЦИЯ: InitInstance(HINSTANCE, int)
. //
. // НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и
создает главное окно.
. //
. // КОММЕНТАРИИ:
. //
. //В данной функции дескриптор экземпляра сохраняется
в глобальной переменной, а также
. // создается и выводится на экран главное окно
программы.
. //
. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
. {
. HWND hWnd;
. hInst = hInstance; // Сохранить дескриптор
экземпляра в глобальной переменной
.
. hWnd = CreateWindow(szWindowClass, szTitle,
WS_OVERLAPPEDWINDOW,
. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL,
hInstance, NULL);
.
. if (!hWnd)
. {
. return FALSE;
. }
.
. ShowWindow(hWnd, nCmdShow);
. UpdateWindow(hWnd);
.
. return TRUE;
. }
. void Task1()
. {
. HKL layot = GetKeyboardLayout(0);
. DWORD wn = GetSysColor(COLOR_WINDOW);
. DWORD frame = GetSysColor(COLOR_WINDOWFRAME);
. char str[256];
. sprintf(str, "Код раскладки клавиатуры:
%d\r\n",layot );
. strcat_s(szBuf, str);
. sprintf(str, "Цвет фона окна: %d\r\n",wn
);
. strcat_s(szBuf, str);
. sprintf(str, "Цвет фона рамки:
%d\r\n",frame);
. strcat_s(szBuf, str);
. }
. BOOL SetConnection( HWND hWnd )
. {
. cln_socket = socket( AF_INET, SOCK_STREAM, 0 ); //
создаем сокет
. if ( cln_socket == INVALID_SOCKET )
. {
. MessageBox( hWnd, "Socket error",
"Error", MB_OK | MB_ICONSTOP );
. return FALSE;
. }
. phe = gethostbyname( szHostName ); // Определяем
адрес узла
. if( phe == NULL )
. {
. closesocket( cln_socket );
. MessageBox( hWnd, "Адрес хоста не
определен", "Error", MB_OK | MB_ICONSTOP );
. return FALSE;
. }
. dest_sin.sin_family = AF_INET;// Задаем тип адреса
. dest_sin.sin_port = htons( SERV_PORT );//
Устанавливаем номер порта
. memcpy( (char FAR*) &(dest_sin.sin_addr),
phe->h_addr, phe->h_length );// Копируем адрес узла
. // Устанавливаем соединение
. if( connect( cln_socket, (PSOCKADDR) &dest_sin,
sizeof(dest_sin) ) == SOCKET_ERROR )
. {
. closesocket( cln_socket );
. MessageBox( hWnd, "Ошибка соединения",
"Error", MB_OK | MB_ICONSTOP );
. return FALSE;
. }
. // при попытке соединения главное окно получит
сообщение WSA_ACCEPT
. if( WSAAsyncSelect( cln_socket, hWnd, WSA_NETEVENT,
FD_READ | FD_CLOSE ) )
. {
. MessageBox( hWnd, "WSAAsyncSelect error",
"Error", MB_OK );
. return FALSE;
. }
. // Выводим сообщение об установке соединения с узлом
. SendMessage( hwndEdit, WM_SETTEXT, 0, ( LPARAM )
"Связь установлена!" );
. return TRUE;
. }
.
. void SendMsg( HWND hWnd )
. {
. cbWritten =
SendMessage(hwndEdit,WM_GETTEXTLENGTH,0,0);
. SendMessage(hwndEdit, WM_GETTEXT, (WPARAM)
cbWritten, (LPARAM) szBuf);
. if( send(cln_socket,szBuf,lstrlen(szBuf),0) !=
SOCKET_ERROR)
. {
. sprintf(m_mess, "\r\n Данные отосланы серверу
\r\n %s",szBuf);
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)m_mess);
. }
. else
. {
. sprintf(m_mess, "%s \r\n Ошибка отправки
сообщения \r\n ",m_mess);
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)m_mess);
. }
. }
. // ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
. //
. // НАЗНАЧЕНИЕ: обрабатывает сообщения в главном
окне.
. //
. // WM_COMMAND- обработка меню приложения
. // WM_PAINT-Закрасить главное окно
. // WM_DESTROY - ввести сообщение о выходе и
вернуться.
. LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
. {
. int wmId, wmEvent;
. PAINTSTRUCT ps;
. HDC hdc;
. switch (message)
. {
. case WM_CREATE:
. hwndEdit = CreateWindow( // Создаем доч.окно для
вывода данных от процессов
. TEXT("EDIT"), NULL,
. WS_CHILD | WS_VISIBLE | WS_VSCROLL |
. ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
. 0, 0, 400, 200, hWnd, NULL, hInst, NULL);
. err = WSAStartup( wVersionRequested, &wsaData );
. if( err ){
. MessageBox( hWnd, "WSAStartup
Error","ERROR", MB_OK | MB_ICONSTOP );
. return FALSE;
. }
. sprintf(m_mess, "Используется %s \r\nСтатус:
%s\r\n ",
. wsaData.szDescription, wsaData.szSystemStatus);
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)m_mess);
. break;
. case WM_COMMAND:
. wmId = LOWORD(wParam);
. wmEvent = HIWORD(wParam);
. // Разобрать выбор в меню:
. switch (wmId)
. {
. case ID_32771:
. SetConnection( hWnd );
. break;
. case ID_32772:
. Task1();
. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)szBuf);
. break;
. case ID_32773:
. SendMsg( hWnd );
. break;
. case WSA_NETEVENT:
. // если на сокете выполняется передача данных,
принимаем и отображаем их
. if( WSAGETSELECTEVENT( lParam ) == FD_READ )
. {
. int rc = recv( cln_socket, szBuf, sizeof(szBuf), 0
);
. if( rc )
. {
. szBuf[rc]='\0';
. sprintf(m_mess, "%s \r\n Данные от сервера:
%s\r\n ",m_mess ,szBuf);
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)m_mess);
. }
. }
. // если соединение завершено, выводим сообщение об
этом
. if( WSAGETSELECTEVENT( lParam ) == FD_CLOSE )
. MessageBox( hWnd, "Сервер закрыт",
"Server", MB_OK );
. break;
. case IDM_ABOUT:
. DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX),
hWnd, About);
. break;
. case IDM_EXIT:
. DestroyWindow(hWnd);
. break;
. default:
. return DefWindowProc(hWnd, message, wParam, lParam);
. }
. break;
. case WM_PAINT:
. hdc = BeginPaint(hWnd, &ps);
. // TODO: добавьте любой код отрисовки...
. EndPaint(hWnd, &ps);
. break;
. case WM_DESTROY:
. PostQuitMessage(0);
. break;
. default:
. return DefWindowProc(hWnd, message, wParam, lParam);
. }
. return 0;
. }
. // Обработчик сообщений для окна "О
программе".
. INT_PTR CALLBACK About(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
. {
. UNREFERENCED_PARAMETER(lParam);
. switch (message)
. {
. case WM_INITDIALOG:
. return (INT_PTR)TRUE;
. case WM_COMMAND:
. if (LOWORD(wParam) == IDOK || LOWORD(wParam) ==
IDCANCEL)
. {
. EndDialog(hDlg, LOWORD(wParam));
. return (INT_PTR)TRUE;
. }
. break;
. }
. return (INT_PTR)FALSE;
. }
Приложение В
Распечатка программы клиента 2
. // Клиент2.cpp: определяет точку входа для
приложения.
. //
. #include "stdafx.h"
. #include "Клиент2.h"
. #include <winsock.h>
. #include <process.h>
. #include <stdio.h>
. #include <windows.h>
. #include <tchar.h>
. #include <string.h>
. #include <iostream>
. char szBuf[512];
. DWORD cbWritten;
. int flag = 0;
. static HWND hwndEdit;
. TCHAR mess[2048];
. TCHAR* m_mess = mess;
. #define SERV_PORT 5000// Порт сервера
. #define WSA_NETEVENT (WM_USER+1)
. WSADATA wsaData; //сведения о конкретной реализации
интерфейса Windows Sockets
. WORD wVersionRequested = MAKEWORD( 1, 1 ); //Номер
требуемой версии Windows Sockets
. int err=0;
. SOCKET cln_socket=INVALID_SOCKET; // Сокет сервера
. static PHOSTENT phe;
. SOCKADDR_IN dest_sin; // Адрес сервера
. char szHostName[128] = "localhost"; //имя
хоста
. #define MAX_LOADSTRING 100
. // Глобальные переменные:
. HINSTANCE hInst;// текущий экземпляр
. TCHAR szTitle[MAX_LOADSTRING];// Текст строки
заголовка
. TCHAR szWindowClass[MAX_LOADSTRING];// имя класса
главного окна
. // Отправить объявления функций, включенных в этот
модуль кода:
. ATOMMyRegisterClass(HINSTANCE hInstance);
. BOOLInitInstance(HINSTANCE, int);
. LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);
. INT_PTR CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);
.
. int APIENTRY _tWinMain(HINSTANCE hInstance,
. HINSTANCE hPrevInstance,
. LPTSTR lpCmdLine,
. int nCmdShow)
. {
. UNREFERENCED_PARAMETER(hPrevInstance);
. UNREFERENCED_PARAMETER(lpCmdLine);
. // TODO: разместите код здесь.
. MSG msg;
. HACCEL hAccelTable;
. // Инициализация глобальных строк
. LoadString(hInstance, IDS_APP_TITLE, szTitle,
MAX_LOADSTRING);
. LoadString(hInstance, IDC_MY2, szWindowClass,
MAX_LOADSTRING);
. MyRegisterClass(hInstance);
. // Выполнить инициализацию приложения:
. if (!InitInstance (hInstance, nCmdShow))
. {
. return FALSE;
. }
. hAccelTable = LoadAccelerators(hInstance,
MAKEINTRESOURCE(IDC_MY2));
. // Цикл основного сообщения:
. while (GetMessage(&msg, NULL, 0, 0))
. {
. if (!TranslateAccelerator(msg.hwnd, hAccelTable,
&msg))
. {
. TranslateMessage(&msg);
. DispatchMessage(&msg);
. }
. }
. return (int) msg.wParam;
. }
. // ФУНКЦИЯ: MyRegisterClass()
. //
. // НАЗНАЧЕНИЕ: регистрирует класс окна.
. //
. // КОММЕНТАРИИ:
. //
. // Эта функция и ее использование необходимы только
в случае, если нужно, чтобы данный код
. // был совместим с системами Win32, не имеющими
функции RegisterClassEx'
. // которая была добавлена в Windows 95. Вызов этой
функции важен для того,
. // чтобы приложение получило
"качественные" мелкие значки и установило связь
. // с ними.
. //
. ATOM MyRegisterClass(HINSTANCE hInstance)
. {
. WNDCLASSEX wcex;
. wcex.cbSize = sizeof(WNDCLASSEX);
. wcex.style= CS_HREDRAW | CS_VREDRAW;
. wcex.lpfnWndProc= WndProc;
. wcex.cbClsExtra= 0;
. wcex.cbWndExtra= 0;
. wcex.hInstance= hInstance;
. wcex.hIcon= LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_MY2));
. wcex.hCursor= LoadCursor(NULL, IDC_ARROW);
. wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
. wcex.lpszMenuName= MAKEINTRESOURCE(IDC_MY2);
. wcex.lpszClassName= szWindowClass;
. wcex.hIconSm= LoadIcon(wcex.hInstance,
MAKEINTRESOURCE(IDI_SMALL));
. return RegisterClassEx(&wcex);
. }
. // ФУНКЦИЯ: InitInstance(HINSTANCE, int)
. //
. // НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и
создает главное окно.
. //
. // КОММЕНТАРИИ:
. //
. // В данной функции дескриптор экземпляра
сохраняется в глобальной переменной, а также
. // создается и выводится на экран главное окно
программы.
. //
. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
. {
. HWND hWnd;
. hInst = hInstance; // Сохранить дескриптор
экземпляра в глобальной переменной
. hWnd = CreateWindow(szWindowClass, szTitle,
WS_OVERLAPPEDWINDOW,
. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance,
NULL);
. if (!hWnd)
. {
. return FALSE;
. }
. ShowWindow(hWnd, nCmdShow);
. UpdateWindow(hWnd);
. return TRUE;
. }
. BOOL SetConnection( HWND hWnd )
. {
. cln_socket = socket( AF_INET, SOCK_STREAM, 0 ); //
создаем сокет
. if ( cln_socket == INVALID_SOCKET )
. {
. MessageBox( hWnd, "Socket error",
"Error", MB_OK | MB_ICONSTOP );
. return FALSE;
. }
. if( phe == NULL )
. {
. closesocket( cln_socket );
. MessageBox( hWnd, "Адрес хоста не
определен", "Error", MB_OK | MB_ICONSTOP );
. return FALSE;
. }
. dest_sin.sin_family = AF_INET;// Задаем тип адреса
. dest_sin.sin_port = htons( SERV_PORT );//
Устанавливаем номер порта
. memcpy( (char FAR*) &(dest_sin.sin_addr), phe->h_addr,
phe->h_length );// Копируем адрес узла
. // Устанавливаем соединение
. if( connect( cln_socket, (PSOCKADDR) &dest_sin,
sizeof(dest_sin) ) == SOCKET_ERROR )
. {
. closesocket( cln_socket );
. MessageBox( hWnd, "Ошибка соединения",
"Error", MB_OK | MB_ICONSTOP );
. return FALSE;
. }
. // при попытке соединения главное окно получит
сообщение WSA_ACCEPT
. if( WSAAsyncSelect( cln_socket, hWnd, WSA_NETEVENT,
FD_READ | FD_CLOSE ) )
. {
. MessageBox( hWnd, "WSAAsyncSelect error",
"Error", MB_OK );
. return FALSE;
. }
. // Выводим сообщение об установке соединения с узлом
. SendMessage( hwndEdit, WM_SETTEXT, 0, ( LPARAM )
"Связь установлена!" );
. return TRUE;
. }
. void SendMsg( HWND hWnd )
. {
. cbWritten =
SendMessage(hwndEdit,WM_GETTEXTLENGTH,0,0);
. SendMessage(hwndEdit, WM_GETTEXT, (WPARAM)
cbWritten, (LPARAM) szBuf);
. if( send(cln_socket,szBuf,lstrlen(szBuf),0) !=
SOCKET_ERROR)
. {
. sprintf(m_mess, "\r\n Данные отосланы серверу
\r\n %s",szBuf);
. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)m_mess);
. }
. else
. {
. sprintf(m_mess, "%s \r\n Ошибка отправки
сообщения \r\n ",m_mess);
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)m_mess);
. }
. }
. void Task1()
. {
. DWORD id = GetCurrentProcessId();
. HANDLE ds = GetCurrentProcess();
. char str[256];
. sprintf(str, "Идентификатор текущего процесса:
%d\r\n",id );
. strcat_s(szBuf, str);
. sprintf(str, "Дескриптор текущего процесса:
%d\r\n",ds );
. strcat_s(szBuf, str);
. }
. // ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
. //
. // НАЗНАЧЕНИЕ: обрабатывает сообщения в главном
окне.
. //
. // WM_COMMAND- обработка меню приложения
. // WM_PAINT-Закрасить главное окно
. // WM_DESTROY - ввести сообщение о выходе и
вернуться.
. //
. //
. LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
. {
. int wmId, wmEvent;
. PAINTSTRUCT ps;
. HDC hdc;
. switch (message)
. {
. case WM_CREATE:
. hwndEdit = CreateWindow( // Создаем доч.окно для
вывода данных от процессов
. TEXT("EDIT"), NULL,
. WS_CHILD | WS_VISIBLE | WS_VSCROLL |
. ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
. 0, 0, 400, 200, hWnd, NULL, hInst, NULL);
. //===========================================================
. err = WSAStartup( wVersionRequested, &wsaData );
. if( err ){
. MessageBox( hWnd, "WSAStartup
Error","ERROR", MB_OK | MB_ICONSTOP );
. return FALSE;
. }
. sprintf(m_mess, "Используется %s \r\nСтатус:
%s\r\n ",
. wsaData.szDescription, wsaData.szSystemStatus);
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)m_mess);
. break;
. case WM_COMMAND:
. wmId = LOWORD(wParam);
. wmEvent = HIWORD(wParam);
. // Разобрать выбор в меню:
. switch (wmId)
. {
. case ID_32771:
. SetConnection(hWnd);
. break;
. case ID_32772:
. Task1();
. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)szBuf);
. break;
. case ID_32773:
. SendMsg(hWnd);
. break;
. case WSA_NETEVENT:
. // если на сокете выполняется передача данных,
принимаем и отображаем их
. if( WSAGETSELECTEVENT( lParam ) == FD_READ )
. {
. int rc = recv( cln_socket, szBuf, sizeof(szBuf), 0
);
. if( rc )
. {
. szBuf[rc]='\0';
. sprintf(m_mess, "%s \r\n Данные от сервера:
%s\r\n ",m_mess ,szBuf);
. SendMessage(hwndEdit, WM_SETTEXT, 0,
(LPARAM)m_mess);
. }
. }
. // если соединение завершено, выводим сообщение об
этом
. if( WSAGETSELECTEVENT( lParam ) == FD_CLOSE )
. MessageBox( hWnd, "Сервер закрыт",
"Server", MB_OK );
. break;
. case IDM_ABOUT:
. DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX),
hWnd, About);
. break;
. case IDM_EXIT:
. DestroyWindow(hWnd);
. break;
. default:
. return DefWindowProc(hWnd, message, wParam, lParam);
. }
. break;
. case WM_PAINT:
. hdc = BeginPaint(hWnd, &ps);
. // TODO: добавьте любой код отрисовки...
. EndPaint(hWnd, &ps);
. break;
. case WM_DESTROY:
. PostQuitMessage(0);
. break;
. default:
. return DefWindowProc(hWnd, message, wParam, lParam);
. }
. return 0;
. }
. // Обработчик сообщений для окна "О
программе".
. INT_PTR CALLBACK About(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
. {
. UNREFERENCED_PARAMETER(lParam);
. switch (message)
. {
. case WM_INITDIALOG:
. return (INT_PTR)TRUE;
. case WM_COMMAND:
. if (LOWORD(wParam) == IDOK || LOWORD(wParam) ==
IDCANCEL)
. {
. EndDialog(hDlg, LOWORD(wParam));
. return (INT_PTR)TRUE;
. }
. break;
. }
. return (INT_PTR)FALSE;
. }