Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие_Ч1_2014_18.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
4.89 Mб
Скачать

Теоретическое введение

Алгоритм передачи информации между клиентом и сервером по протоколу TCP изображен на рис. 1.

Часть функций библиотеки Winsock рассмотрена в предыдущей работе. Новые функции рассмотрены ниже.

Установление соединения

Установление соединения выполняется на стороне клиента с помощью функции connect:

function connect(

s: TSocket;

var name: TSockAddr;

namelen: Integer): Integer; stdcall;

где

s – входной параметр. Дескриптор сокета, созданного с помощью функции socket.

name – входной/выходной параметр. Структура sockaddr (адрес удаленного сокета). В данном случае IP-адрес и порт сервера.

namelen - входной параметр. Длина структуры sockaddr.

В случае ошибки функция возвращает значение SOCKET_ERROR

Перевод сокета в режим пассивного ожидания

Перевод сокета в режим пассивного ожидания выполняется на стороне сервера с помощью функции listen:

function listen(

s: TSocket;

backlog: Integer): Integer; stdcall;

где

s – входной параметр. Дескриптор сокета, созданного с помощью функции socket.

backlog – длина входной очереди сообщений, то есть сколько сообщений может одновременно принять сервер без потери данных. Обычно размер входной очереди равен 5 сообщениям.

Блокирование выполнения программы до тех пор, пока не поступит запрос на установление соединения

Данная функция называется accept и выполняется на стороне сервера

function accept(

s: TSocket;

addr: PSockAddr;

addrlen: PInteger): TSocket; stdcall;

где

s- входной параметр. Дескриптор сокета, созданного с помощью функции socket.

addr – входной/выходной параметр. Структура sockaddr. В данной структуре возвращается адрес сокета клиента, который установил соединение с сервером.

addrlen - Длина структуры sockaddr.

Функция accept возвращает дескриптор сокета, который будут использовать функции recv и send при приеме (передаче) данных от клиента (клиенту).

Передача данных

Передача данных поочередно выполняется на стороне и сервера и клиента. Для передачи данных используется функция send:

function send(

s: TSocket;

var Buf;

len,

flags: Integer): Integer; stdcall;

где

s - дескриптор сокета, созданного с помощью функции socket на стороне клиента, или полученного в результате выполнения функции accept на стороне сервера.

Buf – Буфер, содержит передаваемые данные

Len – длина буфера Buf.

Flags – специальные флаги. Обычно это поле равно 0.

В случае ошибки функция возвращает значение SOCKET_ERROR

Получение данных по сети

Получение данных по сети поочередно выполняется на стороне и сервера и клиента. Для получения

int recv (

SOCKET s,

char FAR* buf,

int len,

int flags

);

function recv(

s: TSocket;

var Buf;

len,

flags: Integer): Integer; stdcall;

где

s - Дескриптор сокета, созданного с помощью функции socket на стороне клиента, или полученного в результате выполнения функции accept на стороне сервера.

Buf – Выходной параметр. Буфер, куда будут записываться принимаемые по сети данные.

Len - входной параметр. Длина буфера Buf.

Flags – флаги. Обычно это поле равно 0.

В случае ошибки функция возвращает значение SOCKET_ERROR

Задание к работе

Создайте клиент-серверное приложение, выполняющее прием и передачу данных по сети. Серверное приложение, имеет вид, показанный на рис.2.

Серверное приложение должно выполнять следующие действия.

  1. Подключить библиотеку Winsock (следует сделать ссылку на библиотеку в списке подключаемых модулей - uses).

  2. Инициализировать интерфейс сокетов с помощью функции WSAStartup.

  3. Создавать сокет с помощью функции socket.

  4. Настраивать сокет с помощью функции setsockopt (необязательно).

  5. Объявлять с помощью функции Bind, на каком порту сервер будет принимать данные и от кого.

  6. Перевести сокет в режим пассивного ожидания с помощью функции listen.

  7. Блокировать выполнения программы до тех пор, пока не поступит запрос на установление соединения с помощью функции accept. Функция accept возвращает дескриптор сокета, на котором будет выполняться прием-передача данных.

  8. Получать данные от любого клиента с помощью функции recv.

  9. Выводить на экран полученное сообщение.

  10. Возвращать полученное сообщение клиенту в режиме эхо с помощью функции send.

  11. Закрывать сокет с помощью функции CloseSocket.

  12. Прекращать работу с интерфейсом сокетов с помощью функции WSACleanup.

Для реализации перечисленных функций сервера выполните следующие действия:

  1. Создайте проект (New Application). Назовите созданный проект каким-либо именем, например – Server.

  2. На созданную форму перенесите две командные кнопки:

  • Button1 - «Запустить сервер»;

  • Button2 - «Выход из программы».

  1. Для события OnClick командной кнопки «Запуск сервера» запишите следующий программный код:

procedure TForm1.Button1Click(Sender: TObject);

VAR

ServerSocket,ClientSocket:TSocket; {Сокет}

addr_server,addr_client:TSockAddr; {адреса сокета сервера и

сокета отправителя}

ret:Integer; {результат работы функций}

bufr :Array [1..90] of char;{буфер для получаемых от клиента данных}

msgstring:Array [1..90] of char;{буфер для вывода сообщения на экран}

bufs:Array [1..80] of char; {буфер для передачи ответа клиенту}

wsd:WSADATA;{Структура WSADATA, требуется для инициализации

интерфейса сокетов}

size_addr:Integer; {размер структуры TSockAddr}

on:Integer;

begin

// Инициализация интерфейса сокетов

If WSAStartup(MAKEWORD(2,2),wsd)<>0

then ShowMessageFmt('Ошибка %d при инициализации интерфеса сокетов',

[WSAGetLastError])

else

begin

// Создание сокета сервера

ServerSocket:=socket(AF_INET,SOCK_STREAM,0);

If ServerSocket=INVALID_SOCKET

then ShowMessageFmt('Ошибка %d при создании сокета',

[WSAGetLastError])

else

begin

// Запись в поля переменной local адреса и номера порта сервера,

// по которому сервер будет принимать датаграммы

addr_server.sin_family:=AF_INET;

addr_server.sin_port:=htons(2000);

addr_server.sin_addr.S_addr:=htonl(INADDR_ANY);

// настройка опций сокета

on:=1;

ret:=setsockopt(ServerSocket,SOL_SOCKET,SO_REUSEADDR,

@on,sizeof(on));

If ret=SOCKET_ERROR then

begin

ShowMessageFmt('Ошибка %d при настройке сокета',[WSAGetLastError]);

CloseSocket(ServerSocket);

end

else

begin

// привязка адреса и номера порта к сокету сервера

// т.е. сервер будет ожидать данные от любого клиента (INADDR_ANY)

// если данные передаются на порт 2000

ret:=bind(ServerSocket,addr_server,sizeof(addr_server));

If ret=SOCKET_ERROR then

begin

ShowMessageFmt('Ошибка %d при объявлении сокета ',

[WSAGetLastError]);

CloseSocket(ServerSocket);

end

else

begin

ret:=listen(ServerSocket,5);

If ret=SOCKET_ERROR then

begin

ShowMessageFmt('Ошибка %d при вызове listen ',[WSAGetLastError]);

CloseSocket(ServerSocket);

end

else

begin

size_addr:=Sizeof(addr_client);

ClientSocket:=accept(ServerSocket,@addr_client,@size_addr);

If ClientSocket=SOCKET_ERROR then

begin

ShowMessageFmt('Ошибка %d при вызове accept ',[WSAGetLastError]);

CloseSocket(ServerSocket);

end

else

begin

ZeroMemory(@bufr,sizeof(bufr));

// Получение данных от клиента

ret:=recv(ClientSocket,bufr,sizeof(bufr),0);

If ret=SOCKET_ERROR then

begin

ShowMessageFmt('Ошибка %d при получении данных ',

[WSAGetLastError]);

CloseSocket(ServerSocket);

end

else

begin

// Формирование сообщения msgstring для вывода на экран

StrCopy(@msgstring,'Получено сообщение: ');

StrCat(@msgstring,@bufr);

StrCat(@msgstring,' от ');

StrCat(@msgstring,inet_ntoa(addr_client.sin_addr));

ShowMessage(msgstring);

end;

StrCopy(@bufs,@bufr);

// Пересылка эхо-ответа клиенту

ret:=send(ClientSocket,bufs,sizeof(bufs),0);

If ret=SOCKET_ERROR then

begin

ShowMessageFmt('Ошибка %d при передаче данных ',

[WSAGetLastError]);

CloseSocket(ServerSocket);

end;

end;

// закрытие сокета

CloseSocket(ServerSocket);

end;

end;

end;

end;

WSACleanup;

end;

end;

Для события OnClick командной кнопки «Выход из программы» запишите следующий программный код:

procedure TForm1.Button2Click(Sender: TObject);

begin

Form1.Close;

end;

Откомпилируйте созданное приложение.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]