Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ.docx
Скачиваний:
16
Добавлен:
18.03.2016
Размер:
125.48 Кб
Скачать

Передача коротких текстовых сообщений

В связи с указанными выше особенностями передачи пакетов этого типа по сети, на стороне получателя необходима процедура определения одинаковых сообщений, чтобы повторно пришедшие пакеты не показывались пользователю и не вводили его в заблуждение. Такую проверку можно проводить непосредственно по тексту сообщения и IP-адресу отправителя, но в разработанной программе эта проблема решается иначе. Для этого в структуру пакета, кроме поля с текстом сообщения, введено дополнительное поле с целочисленным идентификатором сообщения. При отправке всем пакетам, несущим одно и то же сообщение, присваивается одинаковый идентификатор. На приёме запоминаются

9

идентификаторы принятых сообщений, и в случае прихода нескольких пакетов с одинаковыми идентификаторами пользователю выводится только первое из них. Идентификатор формируется с помощью функции генерации случайных чисел, что при достаточно большом диапазоне генерации делает маловероятным ложное отбрасывание сообщений.

Кроме того, в структуру пакета могут быть введены и другие дополнительные поля для расширения функциональности протокола или решения специфических задач. Примерами таких полей могут быть: время отправки сообщения, имя отправителя, алгоритм шифрования сообщения (при их шифрации), код эмоционального содержания и так далее.

В примере (рис. 1.1) предполагается введение поля с уровнем важности сообщения, которое может нести только два значения: сообщение стандартной (2) и повышенной (1) важности.

Уровень важности

Идентификатор пакета

Данные

Рис. 1.1. Формат пакета приложения передачи коротких текстовых сообщений

Имея информацию об основных функциях программы и используемом формате пакетов, можно предположить какие понадобятся органы управления:

  • два поля текстового ввода (для ввода такой информации, как IP-адрес назначения и текст сообщения),

  • элемент переключения (для указания срочности сообщения),

  • управляющая кнопка (для инициализации процесса отправки сообщения),

  • текстовое поле (для вывода текста принятого сообщения),

  • элемент вывода текстовой информации (для вывода дополнительной информации о принятых данных).

Алгоритм на языке SDL приведен в прил. 1.

10

2 Программа реализация разработанных протоколов.

2.1 ОБЩИЕ ЗАМЕЧАНИЯ

2.1.1 Выбор языка программирования.

Для программной реализации выбран язык Delphi, который является в настоящее время самым распространённым, отличается универсальностью и богатыми функциональными возможностями. Кроме того, он привлекателен присутствующим в нём понятием классов.

2.2 ПЕРЕДАЧА КОРОТКИХ ТЕКСТОВЫХ СООБЩЕНИЙ.

Работая в сети Internet, мы очень часто встречаемся с разного рода многопользовательскими программами. Ими могут быть почтовые клиенты, чаты, форумы, FTP клиенты и т.п. Все эти приложения используют для своей работы разного рода протокола: FTP, POP, SMTP, HTTP, и т.д. Но базовым для них является единый протокол - TCP/IP.

Типичное же приложение TCP/IP построено на клиент-серверной архитектуре. Примером приложения построенного на данной архитектуре, является чат реального времени. В этой статье мы попытаемся создать чат средствами Borland Delphi. Для этой цели нам необходимы компоненты TClientSocket и TServerSocket .Выбранные нами компоненты при работе с протоколом TCP/IP используют интерфейс сокетов. Но прежде чем перейти к разработке чата, разберем, что же такое сокеты.

Сокеты – это интерфейс прикладного программирования для сетевых приложений TCP/IP. Интерфейс сокетов был создан в восьмидесятых годах для операционной системы UNIX. Позднее интерфейс сокетов был перенесен в Microsoft Windows. Сокеты до сих пор используются в приложениях для сетей TCP/IP. В переводе с английского "sockets" – гнезда, т.е. сетевые приложения используют сокеты, как виртуальные разъемы для обмена данными между собой. Сокеты бывают трех видов: клиентские, слушающие и серверные.

11

Клиентские сокеты устанавливают связь с сервером и обмениваются с ним данными. Клиентский сокет включен в компонент TClientSocket. Слушающий сокет принимает запрос на соединение от клиентского сокета, и соединяет сервер с клиентом. Слушающий сокет содержится в компоненте TServerSocket. Серверный сокет обменивается данными с клиентом по уже установленному (слушающим сокетом) соединению.

Теперь вернемся к компонентам TClientSocket и TServerSocket. Для того чтобы клиент мог установить соединение с сервером, ему необходимо указать его адрес (IP) и номер порта, через который будет происходить обмен данными.

Перейдем к примеру. У нас будет два приложения: сервер и клиент. Чат будет работать по принципу - один сервер и множество клиентов. Клиент будет посылать сообщение на сервер, а сервер будет рассылать это сообщение другим клиентам, т.е. клиенты будут обмениваться сообщения между собой через сервер. Для написания чата, мы создадим два проекта: сервер и клиент.

12

Приложение 1. Алгоритм программы на языке SDL.

НАЧАЛО

ЗАПУСК

СЕРВЕРА

OnListen

Прослушивает Client

ЗАПУСК

КЛИЕНТА

ЗАПУСК

КЛИЕНТА

OnClient

Read

ServerSocket1Accept

Принимает Client

ClientSocket1Connect Client подсоединяется

ClientWrite

Можно слать данные в Socket

SERVER

OPEN

Exit

SERVER

13

Приложение 2. Листинг программы.

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, ScktComp, ComCtrls, ExtCtrls;

type

TForm1 = class(TForm)

ClientSocket1: TClientSocket;

ServerSocket1: TServerSocket;

Button1: TButton;

Label1: TLabel;

Timer1: TTimer;

Memo1: TMemo;

Memo2: TMemo;

Label2: TLabel;

Button3: TButton;

Edit1: TEdit;

Button2: TButton;

Edit2: TEdit;

Edit3: TEdit;

Button4: TButton;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure OnClientRead(Sender: TObject; Socket: TCustomWinSocket);

procedure Button4Click(Sender: TObject);

procedure ClientSocket1Read(Sender: TObject; Socket:

14

TCustomWinSocket);

procedure Timer1Timer(Sender: TObject);

procedure ServerSocket1Accept(Sender: TObject;

Socket: TCustomWinSocket);

procedure OnListen(Sender: TObject; Socket: TCustomWinSocket);

procedure OnClientConnect(Sender: TObject; Socket: TCustomWinSocket);

procedure OnClientWrite(Sender: TObject; Socket: TCustomWinSocket);

procedure OnGetSocket1(Sender: TObject; Socket: Integer;

var ClientSocket: TServerClientWinSocket);

procedure OnGetThread(Sender: TObject;

ClientSocket: TServerClientWinSocket;

var SocketThread: TServerClientThread);

procedure OnThreadEnd(Sender: TObject; Thread: TServerClientThread);

procedure OnThreadStart(Sender: TObject; Thread: TServerClientThread);

procedure Button3Click(Sender: TObject);

procedure ClientSocket1Connect(Sender: TObject;

Socket: TCustomWinSocket);

procedure ClientSocket1Write(Sender: TObject;

Socket: TCustomWinSocket);

procedure FormCreate(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

15

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

begin

ServerSocket1.Port:=3110; //установка порта

{ вставляет строку в массив в указанную позицию}

Memo2.Lines.Insert(0, 'Server starting');

ServerSocket1.Open;

end;

procedure TForm1.Button2Click(Sender: TObject);

begin

ClientSocket1.Port :=3110;

ClientSocket1.Address :=(Edit2.Text); // локальный адрес компьютера

ClientSocket1.Active :=True;

end;

procedure TForm1.OnClientRead(Sender: TObject; Socket: TCustomWinSocket);

begin

{От клиента получаем сообщение - выводим его в Memo1}

Memo2.Lines.Insert(0, 'Сообщение, полученное от клиента');

Memo1.Lines.Insert(0, '> ' + Socket.ReceiveText );

end;

procedure TForm1.Button4Click(Sender: TObject);

begin

ServerSocket1.Socket.Connections[1].SendText(Edit3.Text+ '...'+Label1.Caption+'< ' + Label2.Caption);

16

Memo1.Lines.Insert(0, '< ' + Edit3.Text+ '...'+Label1.Caption);

Memo1.Lines.Insert(0, '< ' + Label2.Caption);

end;

procedure TForm1.ClientSocket1Read(Sender: TObject;

Socket: TCustomWinSocket);

begin

{Добавляем новое сообщение от сервера в список}

ShowMessage(Socket.ReceiveText );

end;

procedure TForm1.Timer1Timer(Sender: TObject);

begin

Label1.Caption:=timetostr (time)

end;

procedure TForm1.ServerSocket1Accept(Sender: TObject;

Socket: TCustomWinSocket);

begin

{Здесь сервер принимает клиента}

Memo2.Lines.Insert(0, 'Подключение клиента принимаются');

end;

procedure TForm1.OnListen(Sender: TObject; Socket: TCustomWinSocket);

begin

{Здесь сервер "прослушивает" сокет на наличие клиентов}

Memo2.Lines.Insert(0, 'Прослушивает порт ' + IntToStr(ServerSocket1.Port));

end;

procedure TForm1.OnClientConnect(Sender: TObject;

Socket: TCustomWinSocket);

begin

17

{Здесь клиент подсоединяется}

Memo2.Lines.Insert(0, 'Клиент подключен');

end;

procedure TForm1.OnClientWrite(Sender: TObject; Socket: TCustomWinSocket);

begin

{Теперь можно слать данные в сокет}

Memo2.Lines.Insert(0,'Теперь можете писать в сокет');

end;

procedure TForm1.OnGetSocket1(Sender: TObject; Socket: Integer;

var ClientSocket: TServerClientWinSocket);

begin

Memo2.Lines.Insert(0, 'Получить сокет');

end;

procedure TForm1.OnGetThread(Sender: TObject;

ClientSocket: TServerClientWinSocket;

var SocketThread: TServerClientThread);

begin

Memo2.Lines.Insert(0, 'Get Thread');

end;

procedure TForm1.OnThreadEnd(Sender: TObject; Thread: TServerClientThread);

begin

Memo2.Lines.Insert(0, 'Thread end');

end;

procedure TForm1.OnThreadStart(Sender: TObject;

Thread: TServerClientThread);

begin

Memo2.Lines.Insert(0, 'Thread start');

18

end;

procedure TForm1.Button3Click(Sender: TObject);

begin

ClientSocket1.Socket.SendText(Edit1.Text+ '...'+Label1.Caption+ '> ' + Label2.Caption);

end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;

Socket: TCustomWinSocket);

begin

Memo2.Lines.Insert(0, 'Клиент подключен');

end;

procedure TForm1.ClientSocket1Write(Sender: TObject;

Socket: TCustomWinSocket);

begin

Memo2.Lines.Insert(0,'Теперь можете писать в сокет');

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

end;

end.

19