Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лаба14.doc
Скачиваний:
9
Добавлен:
12.11.2019
Размер:
572.93 Кб
Скачать

2. Сервер сокетов с оконным интерфейсом (протокол tcp/ip).

Файл server.cpp

#include <windows.h>

#include <windowsx.h>

#include <winsock.h>

#include <commctrl.h>

#include "resource.h"

// -----------------------------------------------------

// Описание функций

// -----------------------------------------------------

// Функция главного окна

LRESULT WINAPI

WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Функция для обработки сообщения WM_CREATE

BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct);

// Функция для обработки сообщения WM_DESTROY

void WndProc_OnDestroy(HWND hWnd);

// Функция для обработки сообщения WM_COMMAND

void WndProc_OnCommand(HWND hWnd, int id,

HWND hwndCtl, UINT codeNotify);

// Функция для обработки сообщения WM_SIZE

void WndProc_OnSize(HWND hWnd, UINT state, int cx, int cy);

// Запуск сервера

void ServerStart(HWND hWnd);

// Останов сервера

void ServerStop(HWND hWnd);

// Обработка сообщения WSA_ACCEPT

void WndProc_OnWSAAccept(HWND hWnd, UINT msg,

WPARAM wParam, LPARAM lParam);

// Обработка сообщения WSA_NETEVENT

void WndProc_OnWSANetEvent(HWND hWnd, UINT msg,

WPARAM wParam, LPARAM lParam);

// Порт сервера

#define SERV_PORT 5000

#define IDS_STATUSBAR 802

// Определение кодов сообщений

#define WSA_ACCEPT (WM_USER + 1)

#define WSA_NETEVENT (WM_USER + 2)

// -----------------------------------------------------

// Глобальные переменные

// -----------------------------------------------------

// Идентификатор приложения

HINSTANCE hInst;

// Название приложения

char szAppName[] = "WServer";

// Заголовок главного окна приложения

char szAppTitle[] = "Windows Socket Server Demo";

// Идентификатор органа Statusbar

HWND hwndSb;

// Сокет сервера

SOCKET srv_socket;

// Длина использованного сокета

int acc_sin_len;

// Адрес использованного сокета

SOCKADDR_IN acc_sin;

// Локальный сокет

SOCKADDR_IN local_sin;

// -----------------------------------------------------

// Функция WinMain

// -----------------------------------------------------

int APIENTRY

WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

WNDCLASSEX wc;

HWND hWnd;

MSG msg;

hInst = hInstance;

// Преверяем, не было ли это приложение запущено ранее

hWnd = FindWindow(szAppName, NULL);

if(hWnd)

{

// Если окно приложения было свернуто в пиктограмму,

// восстанавливаем его

if(IsIconic(hWnd))

ShowWindow(hWnd, SW_RESTORE);

// Выдвигаем окно приложения на передний план

SetForegroundWindow(hWnd);

return FALSE;

}

// Регистрируем класс окна

memset(&wc, 0, sizeof(wc));

// Поля wc.cbSize и wc.hIconSm определены в структуре

// WNDCLASSEX, которой можно пользоваться для

// регистрации класса окна в Windows 95

wc.cbSize = sizeof(WNDCLASSEX);

// Поле wc.hIconSm задает идентификатор маленькой

// пиктограммы, которая будет отображаться в левой

// части заголовка окна (в области системного меню).

// Загружаем пиктограмму из ресурсов приложения при

// помощи функции LoadImage, так как функция

// LoadIcon может загрузить только обычную пиктограмму

wc.hIconSm = LoadImage(hInst,

MAKEINTRESOURCE(IDI_APPICON_SM), IMAGE_ICON, 16, 16, 0);

// Завершаем заполнение структуры WNDCLASSEX

wc.style = CS_HREDRAW | CS_VREDRAW;

wc.lpfnWndProc = (WNDPROC)WndProc;

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hInstance = hInst;

// Для загрузки обычной пиктограммы вы можете

// использовать функцию LoadImage

wc.hIcon = LoadImage(hInst,

MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 32, 32, 0);

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);

wc.lpszClassName = szAppName;

// Вызываем функцию RegisterClassEx, которая выполняет

// регистрацию окна

if(!RegisterClassEx(&wc))

// В случае ошибки пытаемся зарегистрировать окно

// функцией RegisterClass

if(!RegisterClass((LPWNDCLASS)&wc.style))

return FALSE;

// Инициализация библиотеки органов управления

// общего назначения. Необходима для работы с

// органом управления Statusbar

InitCommonControls();

// Создаем главное окно приложения

hWnd = CreateWindow(szAppName, szAppTitle, WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL);

if(!hWnd) return(FALSE);

// Отображаем окно

ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);

// Запускаем цикл обработки сообщений

while(GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

}

// -----------------------------------------------------

// Функция WndProc

// -----------------------------------------------------

LRESULT WINAPI

WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

// Вызываем обработчик сообщения WSA_ACCEPT

case WSA_ACCEPT:

WndProc_OnWSAAccept(hWnd, msg, wParam, lParam);

break;

// Вызываем обработчик сообщения WSA_NETEVENT

case WSA_NETEVENT:

WndProc_OnWSANetEvent(hWnd, msg, wParam, lParam);

break;

// Для сообщения WM_CREATE назначаем обработчик,

// расположенный в функции WndProc_OnCreate

HANDLE_MSG(hWnd, WM_CREATE, WndProc_OnCreate);

// Для сообщения WM_COMMAND назначаем обработчик,

// расположенный в функции WndProc_OnCommand

HANDLE_MSG(hWnd, WM_COMMAND, WndProc_OnCommand);

// Для сообщения WM_SIZE назначаем обработчик,

// расположенный в функции WndProc_OnSize

HANDLE_MSG(hWnd, WM_SIZE, WndProc_OnSize);

// Для сообщения WM_DESTROY назначаем обработчик,

// расположенный в функции WndProc_OnDestroy

HANDLE_MSG(hWnd, WM_DESTROY, WndProc_OnDestroy);

default:

return(DefWindowProc(hWnd, msg, wParam, lParam));

}

}

// -----------------------------------------------------

// Функция WndProc_OnCreate

// -----------------------------------------------------

BOOL WndProc_OnCreate(HWND hWnd,

LPCREATESTRUCT lpCreateStruct)

{

int rc;

WSADATA WSAData;

char szTemp[128];

// Инициализация и проверка версии Windows Sockets

rc = WSAStartup(MAKEWORD(1, 1), &WSAData);

if(rc != 0)

{

MessageBox(NULL, "WSAStartup Error", "Error", MB_OK);

return FALSE;

}

// Отображаем описание и версию системы Windows Sockets

// в окне органа управления Statusbar

wsprintf(szTemp, "Server use %s %s",

WSAData.szDescription,WSAData.szSystemStatus);

hwndSb = CreateStatusWindow(WS_CHILD | WS_VISIBLE

| WS_BORDER | SBARS_SIZEGRIP,

szTemp, hWnd, IDS_STATUSBAR);

return TRUE;

}

// -----------------------------------------------------

// Функция WndProc_OnDestroy

// -----------------------------------------------------

// Отключаем предупреждающее сообщение о том, что

// функция типа void возвращает управление при помощи

// оператора return. Этот оператор нужен для

// использования макрокоманды FORWARD_WM_LBUTTONDOWN

#pragma warning(disable: 4098)

void WndProc_OnDestroy(HWND hWnd)

{

// Освобождение ресурсов, полученных для

// работы с Windows Sockets

WSACleanup();

// Завершение цикла обработки сообщений

PostQuitMessage(0);

return FORWARD_WM_DESTROY(hWnd, DefWindowProc);

}

// -----------------------------------------------------

// Функция WndProc_OnSize

// -----------------------------------------------------

#pragma warning(disable: 4098)

void

WndProc_OnSize(HWND hWnd, UINT state, int cx, int cy)

{

SendMessage(hwndSb, WM_SIZE, cx, cy);

return FORWARD_WM_SIZE(hWnd, state, cx, cy, DefWindowProc);

}

// -----------------------------------------------------

// Функция WndProc_OnCommand

// -----------------------------------------------------

#pragma warning(disable: 4098)

void

WndProc_OnCommand(HWND hWnd, int id,

HWND hwndCtl, UINT codeNotify)

{

switch (id)

{

case IDM_EXIT:

// Уничтожение главного окна прилоджения

DestroyWindow(hWnd);

break;

case IDM_START:

// Запуск сервера

ServerStart(hWnd);

break;

case IDM_STOP:

// Останов сервера

ServerStop(hWnd);

break;

default:

MessageBox(NULL, "Unknown command", "Error", MB_OK);

}

return FORWARD_WM_COMMAND(hWnd, id, hwndCtl,

codeNotify, DefWindowProc);

}

// -----------------------------------------------------

// Функция ServerStart

// -----------------------------------------------------

void ServerStart(HWND hWnd)

{

struct sockaddr_in srv_address;

int rc;

// Создаем сокет сервера для работы с потоком данных

srv_socket = socket(AF_INET, SOCK_STREAM, 0);

if(srv_socket == INVALID_SOCKET)

{

MessageBox(NULL, "socket Error", "Error", MB_OK);

return;

}

// Устанавливаем адрес IP и номер порта

srv_address.sin_family = AF_INET;

srv_address.sin_addr.s_addr = INADDR_ANY;

srv_address.sin_port = htons(SERV_PORT);

// Связываем адрес IP с сокетом

if(bind(srv_socket, (LPSOCKADDR)&srv_address,

sizeof(srv_address)) == SOCKET_ERROR)

{

// При ошибке закрываем сокет

closesocket(srv_socket);

MessageBox(NULL, "bind Error", "Error", MB_OK);

return;

}

// Устанавливаем сокет в режим приема для

// выполнения ожидания соединения с клиентом

if(listen(srv_socket, 1) == SOCKET_ERROR)

{

closesocket(srv_socket);

MessageBox(NULL, "listen Error", "Error", MB_OK);

return;

}

// При попытке установки соединения главное окно приложения

// получит сообщение WSA_ACCEPT

rc = WSAAsyncSelect(srv_socket, hWnd, WSA_ACCEPT, FD_ACCEPT);

if(rc > 0)

{

closesocket(srv_socket);

MessageBox(NULL, "WSAAsyncSelect Error", "Error", MB_OK);

return;

}

// Выводим в окна Statusbar сообщение о запуске сервера

SendMessage(hwndSb, SB_SETTEXT, 0,

(LPARAM)"Server started");

}

// -----------------------------------------------------

// Функция ServerStop

// -----------------------------------------------------

void ServerStop(HWND hWnd)

{

// Отменяем приход любых извещений в главную функцию

// окна при возникновении любых событий, связанных

// с системой Windows Sockets

WSAAsyncSelect(srv_socket, hWnd, 0, 0);

// Если сокет был создан, закрываем его

if(srv_socket != INVALID_SOCKET)

{

closesocket(srv_socket);

}

// Выводим в окна Statusbar сообщение об останове сервера

SendMessage(hwndSb, SB_SETTEXT, 0,

(LPARAM)"Server stopped");

}

// -----------------------------------------------------

// Функция WndProc_OnWSAAccept

// -----------------------------------------------------

void WndProc_OnWSAAccept(HWND hWnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

int rc;

// При ошибке отменяем поступление извещений

// в главное окно приложения

if(WSAGETSELECTERROR(lParam) != 0)

{

MessageBox(NULL, "accept Error", "Error", MB_OK);

WSAAsyncSelect(srv_socket, hWnd, 0, 0);

return;

}

// Определяем размер адреса сокета

acc_sin_len = sizeof(acc_sin);

// Разрешаем установку соединения

srv_socket = accept(srv_socket, (LPSOCKADDR)&acc_sin,

(int FAR *)&acc_sin_len);

if(srv_socket == INVALID_SOCKET)

{

MessageBox(NULL, "accept Error, invalid socket",

"Error", MB_OK);

return;

}

// Если на данном сокете начнется передача данных от

// клиента, в главное окно приложения поступит сообщение WSA_NETEVENT.

// Это же сообщение поступит при разрыве соединения

rc = WSAAsyncSelect(srv_socket, hWnd, WSA_NETEVENT,

FD_READ | FD_CLOSE);

if(rc > 0)

{

closesocket(srv_socket);

MessageBox(NULL, "WSAAsyncSelect Error", "Error", MB_OK);

return;

}

}

// -----------------------------------------------------

// Функция WndProc_OnWSANetEvent

// -----------------------------------------------------

void WndProc_OnWSANetEvent(HWND hWnd, UINT msg,

WPARAM wParam, LPARAM lParam)

{

char szTemp[256];

int rc;

// Если на сокете выполняется передача данных,

// принимаем и отображаем эти данные в виде

// текстовой строки

if(WSAGETSELECTEVENT(lParam) == FD_READ)

{

rc = recv((SOCKET)wParam, szTemp, 256, 0);

if(rc)

{

szTemp[rc] = '\0';

MessageBox(NULL, szTemp, "Reсeived data", MB_OK);

}

return;

}

// Если соединение завершено, выводми об этом сообщение

else if(WSAGETSELECTEVENT(lParam) == FD_CLOSE)

{

MessageBox(NULL, "Connection closed", "Server", MB_OK);

}

}

Файл server.rc

#include "resource.h"

#include "afxres.h"

// Icon with lowest ID value placed first to ensure application icon

// remains consistent on all systems.

IDI_APPICON ICON DISCARDABLE "client.ico"

IDI_APPICON_SM ICON DISCARDABLE "clientsm.ico"

/////////////////////////////////////////////////////////////////////////////

//

// Menu

//

IDR_MENU1 MENU DISCARDABLE

BEGIN

POPUP "&File"

BEGIN

MENUITEM "&Connect", IDM_CONNECT

MENUITEM "S&end message", IDM_SEND

MENUITEM SEPARATOR

MENUITEM "&Exit", IDM_EXIT

END

END

Файл resource.h

#define IDI_APPICON 101

#define IDI_APPICON_SM 102

#define IDR_MENU1 105

#define IDM_START 40001

#define IDM_EXIT 40002

#define IDM_STOP 40003

#define IDM_CONNECT 40004

#define IDM_SEND 40005

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NO_MFC 1

#define _APS_NEXT_RESOURCE_VALUE 106

#define _APS_NEXT_COMMAND_VALUE 40006

#define _APS_NEXT_CONTROL_VALUE 1000

#define _APS_NEXT_SYMED_VALUE 101

#endif

#endif

Приложение 3

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]