- •1. Сокеты, датаграммы и каналы связи
- •2. Инициализация приложения при работе с сокетами и завершение его работы
- •3. Создание и инициализация сокета
- •3.1. Создание сокета
- •3.2. Удаление сокета
- •3.3. Параметры сокета
- •3.4. Привязка адреса к сокету
- •3.5. Создание канала связи
- •3.5.1.Сторона сервера
- •3.5.1. Сторона клиента
- •3.5.3. Передача и прием данных
- •4. Решения при работе с сокетами
- •5. Порядок выполнения работы
- •6. Контрольные вопросы
- •Приложения
- •1. Коды ошибок различных функций при работе с сокетами
- •2. Сервер сокетов с оконным интерфейсом (протокол tcp/ip).
- •3. Клиент сокетов с оконным интерфейсом (протокол tcp/ip).
- •4. Сервер сокетов с оконным интерфейсом (протокол udp).
- •5. Клиент сокетов с оконным интерфейсом (протокол udp).
- •6. Сервер неблокирующих сокетов с использованием события wsaevent (протокол tcp/ip)
- •7. Клиент неблокирующих сокетов с использованием события wsaevent (протокол tcp/ip)
- •8. Сервер неблокирующих сокетов с использованием функции select
- •9.Клиент неблокирующих сокетов с использованием функции select
- •10. Сервер блокируюющих сокетов (протокол tcp/ip)
- •11. Клиент блокируюющих сокетов (протокол tcp/ip)
4. Сервер сокетов с оконным интерфейсом (протокол udp).
#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_NETEVENT
void WndProc_OnWSANetEvent(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam);
// Порт сервера
#define SERV_PORT 5000
#define IDS_STATUSBAR 802
// Определение кодов сообщений
#define WSA_NETEVENT (WM_USER + 1)
// -----------------------------------------------------
// Глобальные переменные
// -----------------------------------------------------
// Идентификатор приложения
HINSTANCE hInst;
// Название приложения
char szAppName[] = "WServerUDP";
// Заголовок главного окна приложения
char szAppTitle[] = "Windows Socket UDP Server Demo";
// Идентификатор органа Statusbar
HWND hwndSb;
// Сокет сервера
SOCKET srv_socket;
// -----------------------------------------------------
// Функция 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 = sizeof(WNDCLASSEX);
wc.hIconSm = LoadImage(hInst,
MAKEINTRESOURCE(IDI_APPICON_SM), IMAGE_ICON, 16, 16, 0);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
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))
if(!RegisterClass((LPWNDCLASS)&wc.style))
return FALSE;
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_NETEVENT
case WSA_NETEVENT:
WndProc_OnWSANetEvent(hWnd, msg, wParam, lParam);
break;
HANDLE_MSG(hWnd, WM_CREATE, WndProc_OnCreate);
HANDLE_MSG(hWnd, WM_COMMAND, WndProc_OnCommand);
HANDLE_MSG(hWnd, WM_SIZE, WndProc_OnSize);
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_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_DGRAM, 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;
}
// Если на данном сокете начнется передача данных от
// клиента, в главное окно приложения поступит
// сообщение WSA_NETEVENT.
rc = WSAAsyncSelect(srv_socket, hWnd, WSA_NETEVENT, FD_READ);
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_OnWSANetEvent
// -----------------------------------------------------
void WndProc_OnWSANetEvent(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
char szTemp[256];
int rc;
SOCKADDR_IN addr;
int nAddrSize;
char szBuf[80];
LPSTR lpAddr;
if(WSAGETSELECTEVENT(lParam) == FD_READ)
{
// Принимаем данные
rc = recvfrom((SOCKET)wParam, szTemp, 256, 0,
(PSOCKADDR)&addr, &nAddrSize);
if(rc)
{
szTemp[rc] = '\0';
strcpy(szBuf, "Received from ");
// Преобразовываем адрес IP удаленного клиента
// в текстовую строку
lpAddr = inet_ntoa(addr.sin_addr);
strcat(szBuf, lpAddr);
// Отображаем адрес удаленного клиента
// и полученную от него строку
MessageBox(NULL, szTemp, szBuf, MB_OK);
}
return;
}
}
Файл serverd.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 "server.ico"
IDI_APPICON_SM ICON DISCARDABLE "serversm.ico"
IDR_MENU1 MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Start server", IDM_START
MENUITEM "S&top server", IDM_STOP
MENUITEM SEPARATOR
MENUITEM "&Exit", IDM_EXIT
END
END
Файл resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by server.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
Приложение 5