- •Крок 1 – Що такеWindows Sockets
- •Крок 2 – Ініціалізація
- •Крок 3 – Отримання імені хоста
- •If (bind(servsocket, (lpsockaddr)
- •Int bind(
- •Int namelen
- •Крок 6 – Зв’язок вікна з сокетом для отримання повідомлень
- •Назву вікна визначимо як
- •Void BindSocket();
- •Int listen (
- •Void StopServer();
- •If (!cDocument::OnNewDocument())
- •Void chttpServerView::OnDraw(cdc* pDc)
- •Void chttpServerView::OnLButtonDown(uint nFlags, cPoint point)
- •Invalidate();
- •Крок 9 – Відсилаємо документ
- •Invalidate();
- •If (wsagetasyncerror(lParam))
- •Void cServerWinsock::SendData(lpctstr buf, int len)
- •If accept() send()
- •Крок 10 – Порядок байтів
- •Коли Ви повинні перетворювати порядок байтів
- •Коли Вам не потрібно перетворювати порядок байтів
- •Функції перетворення порядку байтів у Windows Sockets
- •If (bind(servsocket, (lpsockaddr) &socketaddr, sizeof(socketaddr)))
- •Розрив зв’язку
- •Крок 12 – Робимо файл звіту
- •Void chttpServerView::OnToolsOptions()
- •Void chttpServerView::OnToolsOptions()
- •Void cServerWinsock::LogWrite(cString csStr)
- •If (wsaStartup(winsock_version, &wsaData))
- •Invalidate();
- •Функції адрес
- •Функції розширення Microsoft Winsock
Крок 3 – Отримання імені хоста
Створюємо проект, як і минулого разу, але з ім’ям Winsock2.
По-перше виносимо ініціалізацію і закриття Winsock в окремі процедури. Загальний код програми тепер виглядає ось так.
void StartWinsock();
void StopWinsock();
void WaitSocket();
void main()
{
StartWinsock();
WaitSocket();
StopWinsock();
}
Функція WaitSocket створена на перспективу, тобто потім будемо створювати сокет, що очікує. А поки у ній є тільки функція отримання імені хоста. Ось як вона виглядає:
void WaitSocket() {
char chInfo[64];
if (gethostname(chInfo, sizeof(chInfo)))
{
printf("Function gethostname...
Failed!\n");
return;
}
else
{
printf("Function gethostname...
Success!");
printf("\tHost name: \"%s\"\n",chInfo);
}
}
Головне у цьому коді – gethostname:
int gethostname (
char far * name,
int namelen
);
Ця функція повертає стандартне ім’я хоста для локальної машини. У неї передається буфер та його довжина для повертання імені. При відсутності помилок ця функція повертає 0.
Ось приклад роботи цієї програми
Startup Winsock... Success!
Function gethostname... Success! Host name: "MYCOMP"
Cleanup Winsock... Success!
Крок 4 – Створюємо сокет
Створюємо проект, як і минулого разу, але з ім’ям Winsock3.
Для поліпшення читання програми виносимо код для отримання і перевірки імені хоста в окрему процедуру.
void SocketGetHostName() {
char chInfo[64];
if (gethostname(chInfo, sizeof(chInfo)))
{
printf("Function gethostname...
Failed!\n");
return;
}
else
{
printf("Function gethostname...
Success!");
printf("\tHost name: \"%s\"\n",chInfo);
}
}
Вносимо зміни у WaitSocket для створення сокету.
void WaitSocket() {
SocketGetHostName();
SOCKET servsocket;
servsocket=socket(AF_INET, SOCK_STREAM, 0);
if (servsocket == INVALID_SOCKET)
{
printf("Creating socket... Failed!\n");
return;
}
else
printf("Creating socket... Success!\n");
if (closesocket(servsocket))
printf("Closing socket... Failed!\n");
else
printf("Closing socket... Success!\n");
}
Оголошуємо змінну servsocket типу SOCKET; ось як цей тип оголошений у “winsock.h”
typedef u_int SOCKET;
Після чого викликаємо функцію socket, яка наш сокет і створює.
SOCKET socket(
int af, // сім’я адрес; у нашому
// випадку AF_INET
int type, // тип сокету:SOCK_STREAM або
// SOCK_DGRAM
int protocol // протокол, у нашому випадку
// 0 (TCP/IP)
);
Якщо вказано тип SOCK_STREAM то буде використовуватися TCP, а якщо SOCK_DGRAM, то UDP.
Протокол ми використовували за умовчанням, тобто TCP/IP. Результат повернення треба перевіряти на INVALID_SOCKET. Після роботи сокет необхідно обов’язково закривати .
Крок 5 – Зв’язок сокету з портом
Знов створюємо той же проект , що і в попередніх кроках.
Знову виносимо попередній код у процедури. Тільки змінну servsocket зробимо глобальною, так як вона буде використовуватися у багатьох командах. Те, що повинно знаходитись у цих процедурах, зрозуміло із попередніх кроків.
……………………
void CreateSocket();
void CloseSocket();
SOCKET servsocket;
……………………
Після створення сокету його треба зв’язати з конкретною адресою (номер порту теж входить в структуру адреси). Для цього існує функція bind. Але для зв’язку ще потрібен номер порту, тому оголошуємо його так:
#define PORT_ADDR 80
Ми намагаємося реалізувати сервер, який буде працювати за протоколом HTTP, а для цього протоколу за умовчанням використовується порт 80. Але взагалі можна використовувати будь-який інший порт.
Для організації зв’язку нам необхідно створити структуру SOCKADDR_IN. Вона необхідна для виконання команди bind; у ній знаходяться параметри зв’язку, такі як порт і атрибути. Ось її опис.
struct sockaddr_in{
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
В даній структурі є вкладена структура sin_addr вона описана ось так:
struct in_addr {
union {
struct {unsigned char
s_b1, s_b2, s_b3, s_b4;}S_un_b;
struct {unsigned short s_w1, s_w2;} S_un_w;
unsigned long S_addr;
} S_un;
};
Після опису структур і їх заповнення даними можна викликати bind.
SOCKADDR_IN socketaddr;
socketaddr.sin_family = AF_INET;
socketaddr.sin_addr.s_addr = INADDR_ANY;
socketaddr.sin_port = PORT_ADDR;