Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Zadania_2-y_praktiki.docx
Скачиваний:
6
Добавлен:
01.07.2025
Размер:
149 Кб
Скачать
☆

Задание №7. Лабораторный практикум №2. Организация обмена данными с использованием протокола tcp/udp.

Цель работы:

  1. Изучить принципы работы с блокирующими сокетами с использованием библиотеки Winsock 2 для ОС Windows.

  2. Изучить основы построения «Клиент-серверных» приложений с использованием сокетов.

Задания для самостоятельной работы:

Вариант 3. Необходимо разработать приложение-чат для обмена сообщениями между несколькими клиентами через сервер с использованием блокирующих сокетов, протокола TCP.

Листинг программы

unit MainUnit;

interface

uses

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

 Dialogs, StdCtrls, ScktComp, ExtCtrls, ImgList, ComCtrls, jpeg;

type

 TForm1 = class(TForm)

 ServerSocket: TServerSocket;

 ClientSocket: TClientSocket;

 PortEdit: TEdit;

 NikEdit: TEdit;

 TextEdit: TEdit;

 ChatMemo: TMemo;

 HostEdit: TEdit;

 ServerBtn: TButton;

 ClientBtn: TButton;

 SendBtn: TButton;

 Label1: TLabel;

 Label2: TLabel;

 Label3: TLabel;

 Label4: TLabel;

 Label5: TLabel;

 UserListView: TListView;

 Label6: TLabel;

 ImageList: TImageList;

 ServerTimer: TTimer;

 Image1: TImage;

 procedure FormCreate(Sender: TObject);

 procedure UpdateUserList;

 procedure UpdateUserMas;

 procedure ServerBtnClick(Sender: TObject);

 procedure ClientBtnClick(Sender: TObject);

 procedure ServerSocketClientConnect(Sender: TObject;

 Socket: TCustomWinSocket);

 procedure ServerSocketClientDisconnect(Sender: TObject;

 Socket: TCustomWinSocket);

 procedure SendBtnClick(Sender: TObject);

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

 procedure ClientSocketDisconnect(Sender: TObject;

 Socket: TCustomWinSocket);

 procedure ClientSocketConnect(Sender: TObject;

 Socket: TCustomWinSocket);

 procedure ServerTimerTimer(Sender: TObject);

 procedure TextEditKeyDown(Sender: TObject; var Key: Word;

 Shift: TShiftState);

 private

 { Private declarations }

 public

 { Public declarations }

 end;

Type

 TUserList = object

 Status: Byte;

 Rec: Boolean;

 Name: String;

 Image: Byte;

 end;

var

 Form1: TForm1;

 i, j, com, ContList: Byte;

 len, pos, x: Word;

 text, StrUserList: String;

 UpdDo: Boolean;

 Buf: array[0..3] of Byte;

 UserMas: array[0..255] of TUserList;

 UItems: TListItem;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

begin

 Caption:='Многопользовательский чат';

 Application.Title:=Caption;

 PortEdit.Text:='Порт сервера';

 HostEdit.Text:='Адрес сервера';

 NikEdit.Text:='Ананим';

 TextEdit.Clear;

 ChatMemo.Lines.Clear;

end;

procedure TForm1.UpdateUserList;

begin

 UserListView.Items.Clear;

 StrUserList:='';

 ContList:=0;

 For i:=0 to 255 do

 Begin

 If UserMas[i].Status<>0 then

 Begin

 UItems:=UserListView.Items.Add;

 UItems.Caption:=UserMas[i].Name;

 UItems.ImageIndex:=UserMas[i].Image;

 If UserMas[i].Rec=False then ContList:=1;

 StrUserList:=StrUserList+UserMas[i].Name+Chr(152);

 end;

 end;

 If (ContList=0) And (ServerSocket.Socket.ActiveConnections<>0) then

 Begin

 For i:=0 to ServerSocket.Socket.ActiveConnections-1 do

 Begin

 ServerSocket.Socket.Connections[i].SendText('2'+StrUserList);

 end;

 end;

end;

procedure TForm1.UpdateUserMas;

begin

 For i:=1 to 255 do

 Begin

 UserMas[i].Status:=0;

 UserMas[i].Rec:=False;

 UserMas[i].Name:='Неизвестный';

 UserMas[i].Image:=0;

 end;

 If ServerSocket.Socket.ActiveConnections<>0 then

 Begin

 For i:=1 to ServerSocket.Socket.ActiveConnections do

 Begin

 UserMas[i].Status:=2;

 UserMas[i].Name:='Неизвестный';

 UserMas[i].Image:=0;

 ServerSocket.Socket.Connections[i-1].SendText('1');

 end;

 end;

end;

procedure TForm1.ServerBtnClick(Sender: TObject);

begin

 If ServerBtn.Tag=0 then

 Begin

 ClientBtn.Enabled:=False;

 HostEdit.Enabled:=False;

 PortEdit.Enabled:=False;

 NikEdit.Enabled:=False;

 ServerSocket.Port:=StrToInt(PortEdit.Text);

 ServerSocket.Active:=True;

 ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Сервер создан.');

 ServerBtn.Tag:=1;

 ServerBtn.Caption:='Закрыть сервер';

 ServerTimer.Enabled:=True;

 UserMas[0].Status:=1;

 UserMas[0].Rec:=True;

 UserMas[0].Name:=NikEdit.Text;

 UserMas[0].Image:=1;

 UpdDo:=True;

 end

 else

 Begin

 ServerTimer.Enabled:=False;

 UserMas[0].Status:=0;

 UserMas[0].Rec:=False;

 UserMas[0].Name:='Неизвестный';

 UserMas[0].Image:=0;

 UpdDo:=True;

 UserListView.Items.Clear;

 ClientBtn.Enabled:=True;

 HostEdit.Enabled:=True;

 PortEdit.Enabled:=True;

 NikEdit.Enabled:=True;

 ServerSocket.Active:=False;

 ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Сервер закрыт.');

 ServerBtn.Tag:=0;

 ServerBtn.Caption:='Создать сервер';

 end;

end;

procedure TForm1.ClientBtnClick(Sender: TObject);

begin

 If ClientBtn.Tag=0 then

 Begin

 ServerBtn.Enabled:=False;

 HostEdit.Enabled:=False;

 PortEdit.Enabled:=False;

 ClientSocket.Port:=StrToInt(PortEdit.Text);

 ClientSocket.Host:=HostEdit.Text;

 ClientSocket.Address:=HostEdit.Text;

 ClientSocket.Active:=True;

 ClientBtn.Tag:=1;

 ClientBtn.Caption:='Отключиться';

 end

 else

 Begin

 ServerBtn.Enabled:=True;

 HostEdit.Enabled:=True;

 PortEdit.Enabled:=True;

 ClientSocket.Active:=False;

 UserListView.Items.Clear;

 ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Сессия закрыта.');

 ClientBtn.Tag:=0;

 ClientBtn.Caption:='Подключиться';

 end;

end;

procedure TForm1.ServerSocketClientConnect(Sender: TObject;

 Socket: TCustomWinSocket);

begin

 ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Подключился клиент.');

 UpdDo:=True;

end;

procedure TForm1.ServerSocketClientDisconnect(Sender: TObject;

 Socket: TCustomWinSocket);

begin

 ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Клиент отключился.');

 UpdDo:=True;

end;

procedure TForm1.SendBtnClick(Sender: TObject);

begin

 If ServerSocket.Active=True then

 For i:=0 to ServerSocket.Socket.ActiveConnections-1 do

 ServerSocket.Socket.Connections[i].SendText('0['+TimeToStr(Time)+'] '+NikEdit.Text+': '+TextEdit.Text)

 else

 ClientSocket.Socket.SendText('0['+TimeToStr(Time)+'] '+NikEdit.Text+': '+TextEdit.Text);

 ChatMemo.Lines.Add('['+TimeToStr(Time)+'] '+NikEdit.Text+': '+TextEdit.Text);

 TextEdit.Clear;

end;

procedure TForm1.ClientSocketRead(Sender: TObject;

 Socket: TCustomWinSocket);

begin

 text:=Socket.ReceiveText();

 com:=StrToInt(Copy(text,1,1));

 len:=Length(text)-1;

 Case com of

 0: ChatMemo.Lines.Add(Copy(text,2,len));

 1: ClientSocket.Socket.SendText('1'+NikEdit.Text);

 2: Begin

 UserListView.Items.Clear;

 text:=text+Chr(152);

 pos:=2;

 x:=0;

 For j:=2 to len+1 do

 Begin

 x:=x+1;

 If Copy(text,j,1)=Chr(152) then

 Begin

 UItems:=UserListView.Items.Add;

 UItems.Caption:=Copy(text,pos,x-1);

 If pos>2 then UItems.ImageIndex:=0 else UItems.ImageIndex:=1;

 pos:=j+1;

 x:=0;

 end;

 end;

 end;

 end;

end;

procedure TForm1.ClientSocketConnect(Sender: TObject;

 Socket: TCustomWinSocket);

begin

 ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Подключение к серверу.');

end;

procedure TForm1.ClientSocketDisconnect(Sender: TObject;

 Socket: TCustomWinSocket);

begin

 ChatMemo.Lines.Add('['+TimeToStr(Time)+'] Сервер не найден.');

end;

procedure TForm1.ServerTimerTimer(Sender: TObject);

begin

 If ServerSocket.Socket.ActiveConnections<>0 then

 Begin

 For i:=1 to ServerSocket.Socket.ActiveConnections do

 Begin

 text:=ServerSocket.Socket.Connections[i-1].ReceiveText();

 If text<>'' then

 Begin

 com:=StrToInt(Copy(text,1,1));

 len:=Length(text)-1;

 Case com of

 0: Begin

 ChatMemo.Lines.Add(Copy(text,2,len));

 For j:=0 to ServerSocket.Socket.ActiveConnections-1 do

 Begin

 If (j+1)<>i then ServerSocket.Socket.Connections[j].SendText('0'+Copy(text,2,len));

 end;

 end;

 1: Begin

 UserMas[i].Name:=Copy(text,2,len);

 UserMas[i].Rec:=True;

 UpdateUserList;

 end;

 end;

 end;

 end;

 end;

 If UpdDo=True then

 Begin

 UpdateUserMas;

 UpdateUserList;

 UpdDo:=False;

 end;

end;

procedure TForm1.TextEditKeyDown(Sender: TObject; var Key: Word;

 Shift: TShiftState);

begin

 If Key=VK_RETURN then SendBtn.Click;

end;

end.

Вывод по лабораторной работе.

В ходе лабораторной работы я ознакомился с организацией обмена данными с использованием протокола TCP/UDP. Изучил принципы работа с блокирующими сокетами с использованием библиотеки Winsock 2 для ОС Windows и основы построения «Клиент-серверных» приложений с использованием сокетов.