Шаг 8 - Соединение с сервером

Запускайте VC и выбирайте MFC AppWizard, имя проекту дайте HTTPServer. На шаге 1 поставьте Single Document, на шаге 3 отключите ActiveX Control нам пока это не нужно, на шаге 4 отключите всё, и жмите Finish.

Давайте на основе прошлых шагов создадим класс CSeverWinSock. Переходите в ClassView, нажимайте правую кнопку мыши и выбирайте Add New Class. Выбирите Generic Class внесите имя и жмите OK, я не буду разбирать подробности переноса, скажу только, что все функции printf поменяю на AfxmessageBox, и все функции из void станут BOOL. Посмотрите проект. Но описание класса и две важные функции приведу:

class CSeverWinSock  
{
public:
	CSeverWinSock();
	virtual ~CSeverWinSock();
	BOOL StartWinSock();
	BOOL SocketGetHostName();
	BOOL CreateSocket();
	BOOL LinkWindowSocket(HWND m_hWnd);
	BOOL ListenSocket();
	void CloseScoket();
	BOOL LinkSoketPort();
	BOOL StopWinSock();
	BOOL StartServer(HWND m_hWnd);
	void StopServer();
private:
	SOCKET servsocket;
};


void CSeverWinSock::StopServer()
{
	CloseScoket();
	StopWinSock();
}

BOOL CSeverWinSock::StartServer()
{
	if (!StartWinSock()) return FALSE;
	if (!SocketGetHostName()) return FALSE;
	if (!CreateSocket()) return FALSE;
	if (!LinkSoketPort()) return FALSE;
	if (!LinkWindowSocket(m_hWnd)) return FALSE;
	if (!ListenSocket()) return FALSE;
	return TRUE;
}

Итак, нам нужно запустить и остановить сервер. Мы будем это делать по нажатию левой кнопки мыши - запускать, правой - останавливать. Но сначала заведем переменную csInfo для вывода на экран состояния. Мы опишем её в классе CHTTPServerDoc и там же инициализируем.

// ......
// Implementation
public:
	CString csInfo;
	virtual ~CHTTPServerDoc();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

//......

BOOL CHTTPServerDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	csInfo="Stop Server";

	return TRUE;
}

В классе CHTTPServerView опишем вывод на экран:

void CHTTPServerView::OnDraw(CDC* pDC)
{
	CHTTPServerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	pDC->TextOut(10,10,pDoc->csInfo);  
}

В классе CHTTPServerView заведем логическую переменную blTestStartServer и в конструкторе скажем, что она FALSE - типа сервер стоит.

CHTTPServerView::CHTTPServerView()
{
	blTestStartServer=FALSE;
}

Добавим для класса CHTTPServerView реакцию на нажатие правой и левой кнопки мыши. А также в описание этого класса ссылку на наш заголовочный файл.

#pragma once
#endif // _MSC_VER > 1000

#include "SeverWinSock.h"

Включим в описание класса CHTTPServerView экземпляр класса CSeverWinSock:

public:
	BOOL blTestStartServer;
	virtual ~CHTTPServerView();
	CSeverWinSock  HTTPServer;
#ifdef _DEBUG

Ну вот и всё готово. Теперь можно обрабатывать нажатие мышки.

////////////////////////////////////
// CHTTPServerView message handlers

void CHTTPServerView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if (!blTestStartServer)
	{
		if (HTTPServer.StartServer(m_hWnd))
		{
			CHTTPServerDoc* pDoc = GetDocument();
			ASSERT_VALID(pDoc);
			pDoc->csInfo = "Server Start"; 
			Invalidate();
			blTestStartServer=TRUE;
		}
	}
	CView::OnLButtonDown(nFlags, point);
}

void CHTTPServerView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	HTTPServer.StopServer();
	CHTTPServerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->csInfo = "Server Stop"; 
	Invalidate();
	blTestStartServer=FALSE;
	CView::OnRButtonDown(nFlags, point);
}

Когда к серверу обратится клиент будет сгенерировано сообщение WM_SERVER_ACCEPT, отловом которого мы займемся.

BEGIN_MESSAGE_MAP(CHTTPServerView, CView)
	//{{AFX_MSG_MAP(CHTTPServerView)
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_SERVER_ACCEPT,OnServerAccept)
END_MESSAGE_MAP()

afx_msg LRESULT CHTTPServerView::OnServerAccept(WPARAM wParam, LPARAM lParam)
{
	CHTTPServerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->csInfo = "Client Connect !!!!!"; 
	Invalidate();
	return 0L;
}

Надо устранить еще одну ошибку допушенную мною в прошлом шаге, при указании порта в LinkSoketPort. Это функция конвертации.

socketaddr.sin_port = htons(PORT_ADDR);

Собирайте проект. Устанавливайте связь с интернетом и запускайте.

А вот теперь нужно протестировать. Я тестировал на Windows 98 с удаленным доступом к Internet. Так как IP адрес динамический я его посмотрел используя IPconfig и ввел в Exploler. Вот смотрите рисунок ниже. Конечно соединение прошло, но Internet Explorer нечего не показал, хотя пытался. Конечно :-) Нужен код типа Client_Read, но мы его сделаем :-) в следующем шаге.

gif/8_1.gif (15583 b)


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 15.01.2000