- •Крок 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
Int listen (
SOCKET s,
int backlog
);
Перший параметр – це існуючий сокет, а другий –максимальна кількість з’єднань, що очікують підключення. Залишимо кількість рівній 5, визначивши константу QUEUE_SIZE.
#define QUEUE_SIZE 5
При нормальному завершенні функція повертає 0, інакше – SOCKET_ERROR. До речі, коли ця функція, а також і функції, які були розглянуті у попередніх кроках, повертають SOCKET_ERROR, то розширений код похибки можна отримати, викликавши функцію WSAGetLastError.
Крок 8 – З’єднання з сервером
Створюємо проект
Запускайте VC і вибирайте MFC AppWizard, ім’я проекту даємо HTTPServer. На кроці 1 поставте Single Document, на кроці 3 відключіть ActiveX Control – нам це не потрібно, на кроці 4 відключіть усе і натискуйте Finish.
Створюємо код
Давайте на основі минулих кроків створимо клас CServerWinsock. Переходьте у Class View, натискуйте праву кнопку миші і вибирайте Add New Class. Вибираємо Generic Class, вносимо ім’я і натискаємо ОК. Усі функції printf треба замінити на AfxMessageBox, а всі функції із void стануть BOOL. Приведемо опис класу і дві важливі функції.
class CServerWinsock
{
public:
BOOL StartWinsock();
BOOL StopWinsock();
BOOL WaitSocket();
BOOL SocketGetHostName();
BOOL CreateSocket();
BOOL BindSocket();
BOOL LinkWindowSocket(HWND m_hWnd);
BOOL ListenSocket();
BOOL CloseSocket();
BOOL StartServer(HWND m_hWnd);
Void StopServer();
CServerWinsock();
virtual ~CServerWinsock();
private:
SOCKET servsocket;
};
BOOL CServerWinsock::StartServer(HWND m_hWnd)
{
if (!StartWinsock()) return FALSE;
if (!SocketGetHostName()) return FALSE;
if (!CreateSocket()) return FALSE;
if (!BindSocket()) return FALSE;
if (!LinkWindowSocket(m_hWnd)) return FALSE;
if (!ListenSocket()) return FALSE;
return TRUE;
}
void CServerWinsock::StopServer()
{
CloseSocket();
StopWinsock();
}
Так, нам треба запускати і зупиняти сервер. Ми будемо це робити по натисканню кнопок миші, лівою будемо запускати, а правою зупиняти. Але спочатку створимо змінну csInfo для виводу на екран стану сервера. Її ми опишемо у класі CHTTPServerDoc і там же ініціалізуємо.
………………………
class CHTTPServerDoc : public CDocument
{
protected: // create from serialization only
CHTTPServerDoc();
DECLARE_DYNCREATE(CHTTPServerDoc);
// Attributes
public:
CString csInfo;
// Operations
public:
// Overrides
………………………
BOOL CHTTPServerDoc::OnNewDocument()
{
If (!cDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
csInfo="Stop Server";
return TRUE;
}
У класі CHTTPServerView опишемо виведення до екрану.
Void chttpServerView::OnDraw(cdc* pDc)
{
CHTTPServerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->TextOut(10,10,pDoc->csInfo);
}
У класі CHTTPServerView заведемо логічну змінну blTestStartServer та в конструкторі ініціалізуємо її значенням FALSE – сервер не працює.
CHTTPServerView::CHTTPServerView()
{
// TODO: add construction code here
blTestStartServer=FALSE;
}
Додамо до класу CHTTPServerView реакцію на натискання правої та лівої кнопки миші і у опису цього класу посилання на заголовочний файл.
#pragma once
#endif // _MSC_VER > 1000
#include "ServerWinsock.h"
Включимо до опису класу CHTTPServerView екземпляр класу CServerWinsock.
public:
CHTTPServerDoc* GetDocument();
BOOL blTestStartServer;
CServerWinsock HTTPServer;
Тепер усе готове і можна обробляти натискання клавіш миші.
/////////////////////////////////////////////////////////////////////////////
// CHTTPServerView message handlers