Практическое введение в Internet, E-Mail, FTP, WWW и HTML

Приложение CLIENT


Исходные тексты приложения CLIENT, предназначенного для совместного использования с только что описанным приложением SERVER, приведены в листинге 5.4.

После запуска этого приложения вы должны создать канал связи с приложением SERVER, выбрав из меню File строку Connect, после чего можно посылать сообщение Test message, выбирая из этого же меню строку Send Message.

Сервер, получив сообщение, отобразит его на экране в отдельной диалоговой панели.

Листинг 5.4. Файл client/client.c

#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 SetConnection(HWND hWnd);

// Передача сообщения void SendMsg(HWND hWnd);



// Порт сервера #define SERV_PORT 5000

#define IDS_STATUSBAR 802

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

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

// Название приложения char szAppName[] = "WClient";

// Заголовок главного окна приложения char szAppTitle[] = "Windows Socket Client Demo";

// Идентификатор органа управления Statusbar HWND hwndSb;

// Сокет клиента SOCKET srv_socket ;

// Локальный сокет SOCKADDR _IN local_sin;

// Адрес сервера SOCKADDR _IN dest_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) { // Для сообщения 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 // -----------------------------------------------------

#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_CONNECT:

// Установка соединения с сервером SetConnection(hWnd); break;

case IDM_SEND:

// Посылка сообщения серверу SendMsg(hWnd); break;

default: MessageBox(NULL, "Unknown command", "Error", MB_OK); }

return FORWARD_WM_COMMAND (hWnd, id, hwndCtl, codeNotify, DefWindowProc); }

// ----------------------------------------------------- // Функция SetConnection // -----------------------------------------------------

void SetConnection(HWND hWnd) { PHOSTENT phe;

// Создаем сокет srv_socket = socket(AF_INET , SOCK_STREAM, 0); if(srv_socket == INVALID_SOCKET) { MessageBox(NULL, "socket Error", "Error", MB_OK); return; }

// Устанавливаем адрес IP и номер порта dest_sin.sin_family = AF_INET ;

// Определяем адрес узла

// Адрес локального узла для отладки phe = gethostbyname ("localhost ");

// Адрес удаленного узла //phe = gethostbyname ("frolov");



if(phe == NULL) { closesocket (srv_socket); MessageBox(NULL, "gethostbyname Error", "Error", MB_OK); return; }

// Копируем адрес узла memcpy((char FAR *)&(dest_sin.sin_addr ), phe->h_addr , phe->h_length);

// Другой способ указания адреса узла // dest_sin.sin_addr .s_addr = inet_addr ("200.200.200.201");

// Копируем номер порта dest_sin.sin_port = htons(SERV_PORT);

// Устанавливаем соединение if(connect(srv_socket , (PSOCKADDR )&dest_sin, sizeof(dest_sin)) < 0) { closesocket (srv_socket); MessageBox(NULL, "connect Error", "Error", MB_OK); return; }

// В случае успеха выводим сообщение об установке // соединения с узлом SendMessage(hwndSb, SB_SETTEXT, 0, (LPARAM)"Connected"); }

// ----------------------------------------------------- // Функция SendMsg // -----------------------------------------------------

void SendMsg(HWND hWnd) { char szBuf[80]; lstrcpy(szBuf, "Test string");

// Посылаем сообщение send (srv_socket , szBuf, lstrlen(szBuf), 0); }

Вы сможете разобраться с исходными текстами этого прилжоения самостоятельно, так как все использованные в нем функции были нами уже описаны. Обратим ваше внимание только на функцию SetConnection, предназначенную для установки канала связи с сервером.

Если вы будете проверять работу приложений SERVER и CLIENT на одном и том же компьютере, адрес сервера должен быть указан следующим образом:

phe = gethostbyname ("localhost ");

Для того чтобы установить канал связи с компьютером по его имени, закройте символом комментария приведенную выше строку и уберите символ комментария со строки, расположенной ниже:

//phe = gethostbyname ("frolov");

Разумеется, вы должны также изменить имя компьютера.

Можно также указать адрес узла в виде десятичных цифр, для чего следует убрать символ комментария со следующей строки:

// dest_sin.sin_addr .s_addr = inet_addr ("200.200.200.201");

Идентификаторы ресурсов приложения CLIENT определены в файле resource.h, представленном в листинге 5.5.



Листинг 5.5. Файл client/resource.h

//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by CLIENT.rc // #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

Файл client.rc (листинг 5.6) содержит определения ресурсов приложения.

Листинг 5.6. Файл client/client.rc

//Microsoft Developer Studio generated resource script. // #include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h"

///////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS

///////////////////////////////////////////////////////////////////// // Russian resources

#if !defined(AFX_RESOURCE_DLL) defined(AFX_TARG_RUS) #ifdef _WIN32 LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT #pragma code_page(1251) #endif //_WIN32

#ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////// // // TEXTINCLUDE //

1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END

2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END

3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END

#endif // APSTUDIO_INVOKED

///////////////////////////////////////////////////////////////////// // // Icon //

// 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

#endif // Russian resources /////////////////////////////////////////////////////////////////////

#ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. //

///////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED


Содержание раздела