Сетевое программирование в .NET. Расшифровка IP-адреса (IP address specification). Обеспечение надежности доставки пакетов, страница 15

#pragma comment (lib, "Ws2_32.lib")

#define WIN32_LEAN_AND_MEAN    // Exclude rarely-used stuff from Windows headers

#include <iostream>

#include <string>

#include <tchar.h>

#include <winsock2.h>

using namespace std;

Важным моментом является подключение библиотеки Ws2_32.lib (WinSock). Найдите две строки кода, которые делают это. Замените весь код серверного приложения (файла WinSockServer.cpp) на тот, что приведен ниже. В нем реализуется алгоритм вызова API-функций, соответствующий серверной части диаграммы.

#include "stdafx.h"

void main()

{

WSADATA data;

int res = WSAStartup (MAKEWORD(2,2), &data);  // Initialize WSA (Winsock Applications)

if (res != NO_ERROR)

cout << "Error at WSAStartup()";

SOCKET sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (sock == INVALID_SOCKET)

{

cout << "\nError at socket(): " << WSAGetLastError();

WSACleanup();

return;

}

string myAddr = "127.0.0.1"; // Потом вставьте реальный адрес

sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_addr.s_addr = inet_addr (myAddr.c_str());

addr.sin_port = htons (0x6987); // 27015

if (bind (sock, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR)

{

cout <<  "\nbind() failed";

closesocket (sock);

return;

}

if (listen (sock, 1) == SOCKET_ERROR)

cout << "\nError listening on socket";

cout << "\nMy address: " << myAddr << "\nWaiting for a client to connect...";

SOCKET acceptSocket = SOCKET_ERROR;

while (acceptSocket == SOCKET_ERROR)

acceptSocket = accept (sock, 0, 0);

cout <<  "\nClient Connected\n";

sock = acceptSocket;

char* buf = new char[32];

while (true)

{

int nBytes = recv (sock, buf, 32, 0);

if (nBytes < 0 || strcmp (buf, "Bye") == 0)

break;

cout << "\nReceived: " << buf << "  (" << nBytes << " bytes)";;

strcpy (buf, "Yes, Client!");

nBytes = send (sock, buf, (int)strlen(buf) + 1, 0);

cout << "\nSent: " << buf << "  (" << nBytes << " bytes)\n";

}

cout << "\n\n";

}

Вызов функции WSAStartup рассматривайте, как инициализацию библиотеки ws2_32.dll, то есть загрузку ее в адресное пространство процесса серверного приложения. Далее в функции main создается разъем (socket), заполняется определяющая его тип структура sockaddr_in, производится связывание (bind) разъема с этой структурой, точнее, с парой (локальный адрес, порт), и разъем переводится в режим прослушивания сети. Разъем ждет, когда какой-либо клиент откроет с ним соединение. Цикл ожидания этого события имеет такой вид.

SOCKET acceptSocket = SOCKET_ERROR;

while (acceptSocket == SOCKET_ERROR)

acceptSocket = accept (sock, 0, 0);

После открытия соединения разъем переходит в режим циклического обмена данными с клиентским приложением. Цикл обмена (вызов функций recv, send) завершается, когда от клиента придет сообщение с текстом: "Bye". Такое решение принято произвольно. Вы можете изменить алгоритм и завершать сессию, по прибытии любого другого сигнала. Например, сервер может решить сложную задачу, по ее окончании переслать ответ (массив данных) клиенту, и завершить цикл обмена, когда клиент подтвердит получение массива. Перейдите в клиентское приложение (файл WinSockClient.cpp) и полностью замените его код.

#include "stdafx.h"

void main()

{

WSADATA data;

int res = WSAStartup (MAKEWORD(2,2), &data); // Initialize WSA (Winsock Applications)

if (res != NO_ERROR)

cout << "Error at WSAStartup()";

SOCKET sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (sock == INVALID_SOCKET)

{

cout << "\nError at socket(): " << WSAGetLastError();

WSACleanup();

return;

}

string myAddr = "127.0.0.1"; // Потом вставьте реальный адрес

sockaddr_in addr;

addr.sin_family = AF_INET;