Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Zemskov_my_sppo1

.pdf
Скачиваний:
30
Добавлен:
18.04.2015
Размер:
595.32 Кб
Скачать

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 5.1. Пример сервера WinSock на Си

// Пример использования классических блокирующих сокетов в MS Visual C //======= Сервер Winsock (консольное приложение) ============

#include<Winsock2.h> // к проекту надо подключить библиотеку Ws2_32.lib #include<stdio.h>

#include<winbase.h> // Для Sleep #define BUFNUM 5 // Длина буфера приёма

#define HOSTNAME "localhost"// Имя сервера ( используем локальную машину) int main(int argc, char ** argv){

SOCKET mysock, mysock1; // две переменные типа <<сокет>>

WSADATA wsaData; // Данные, возвращаемые функцией инициализации библиотеки struct sockaddr_in myaddr, myaddr1; // Адреса сокетов

int err,len1,len2; // Код ошибки, длина сообщения

char buf[BUFNUM+1]={’_’,’_’,’_’,’_’,’_’,’\0’}; // сначала в буфере приёма только подчерки и 0 в конце struct hostent FAR *hp;

err=WSAStartup(0x0101,&wsaData); // инициализируем библиотеку Winsock,

//это нестандартная функция (по сравнению с Unix)

//Вместо версии 1.1 уже можно использовать 2.2

if(err<0){ // если была ошибка, то выведем её код и закончим printf("Winsock starting error %i",WSAGetLastError()); exit(1);

}

mysock=socket(AF_INET,SOCK_STREAM,0); // создали сокет,

// область имён - INET, тип - с установлением соединения, протокол - по умолчанию if(mysock==INVALID_SOCKET){ // если ошибка, то выведем её код, закроем

// библиотеку Winsock и закончим printf("\nCannot create socket, error %i\n",WSAGetLastError()); WSACleanup(); exit(1);

}

hp = gethostbyname(HOSTNAME); // перевели имя хоста в адрес memcpy(&myaddr.sin_addr, hp->h_addr, hp->h_length); myaddr.sin_family = hp->h_addrtype;

//myaddr.sin_addr.s_addr = INADDR_ANY; // если хотим устанавливать

//соединение с любой сетевой службой, то последние две строки

//надо заменить данной функцией.

myaddr.sin_port=htons(1000); // номер порта, переведённый в ‘сетевой порядок’ err=bind(mysock, (struct sockaddr *) &myaddr,

sizeof(myaddr)); // связываем сокет if(err<0){ // если была ошибка

printf("\nCannot bind socket, error %i\n",WSAGetLastError()); WSACleanup(); exit(1);

}

ioctlsocket(mysock, FIONBIO, 0); // устанавливаем блокирующий режим // (данный режим устанавливается по умолчанию, поэтому можно опустить) printf("\nListening...\n");

err=listen(mysock,1); // переводим сокет в прослушивающий режим, // длина очереди - только один вызов

if (err<0){ // если была ошибка

printf("\nCannot listen socket, error %i\n", WSAGetLastError()); WSACleanup(); exit(1);

}

len1=sizeof(myaddr1);

mysock1=accept(mysock, (struct sockaddr FAR*)&myaddr1, &len1);

//приняли запрос на соединение

//(accept ждёт, пока не будет выполнен connect клиента) if(mysock1==INVALID_SOCKET){ // если ошибка

printf("\nError accepting connection, error %i\n",WSAGetLastError()); WSACleanup(); exit(1);

}

printf("\nAccepted %i.%i.%i.%i\n",myaddr1.sin_addr.S_un.S_un_b.s_b1, myaddr1.sin_addr.S_un.S_un_b.s_b2, myaddr1.sin_addr.S_un.S_un_b.s_b3, myaddr1.sin_addr.S_un.S_un_b.s_b4); // кто нас вызвал

Sleep(1000); printf("\nWaiting message...\n"); len1=0;

while(len1<BUFNUM){ // принимаем символ за символом сообщение длиной BUFNUM len2=recv(mysock1,&buf[len1],BUFNUM-len1,0); len1+=len2; printf("\nReceived message:\t%s,\tlength is %i\n", buf, len2);

}// (принять всю строку нельзя, т.к. сообщения в сети могут

// дробиться на пакеты и наоборот, слипаться) buf[BUFNUM]=’\0’; // конец строки

Sleep(1000); // чтобы на экране всё менялось не слишком быстро printf("\nReceived:\t%s;\tlength is %i\n",buf,len1); shutdown(mysock1, 2); // 2 - закрыли сокет и для чтения, и для записи closesocket(mysock1);

closesocket(mysock);

WSACleanup(); // закрыли библиотеку Winsock (в Unix этого нет) Sleep(5000); // подождали 5 сек

return 0;

}

43

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 5.2. Пример клиента WinSock на Си

\\========== Клиент (консольное приложение) ============

#include<Winsock2.h>

#include<stdio.h>

#include<winbase.h>

#define HOSTNAME "GEORGE" // Имя машины, к которой будем подключаться #define BUFNUM 5

char buf[BUFNUM+1]={’a’,’b’,’c’,’d’,’e’,0};

// это сообщение, которое будем посылать серверу

int main(int argc, char ** argv){

SOCKET mysock;

struct sockaddr_in myaddr; int err,len;

WSADATA wsaData; struct hostent FAR *hp;

err=WSAStartup(0x0101,&wsaData); mysock=socket(AF_INET,SOCK_STREAM,0); if(mysock==0)

printf("\nCannot create socket\n"); hp = gethostbyname(HOSTNAME);

if (hp == NULL){

printf("\nInvalid host name\n"); WSACleanup();

exit(1);

}

memcpy(&myaddr.sin_addr, hp->h_addr, hp->h_length); myaddr.sin_family = hp->h_addrtype; myaddr.sin_port=htons(1000);

printf("Connecting to the sever..."); err=-1;

ioctlsocket(mysock, FIONBIO, 0); while(err<0){

err=connect(mysock,(struct sockaddr*)&myaddr,sizeof(myaddr));

//connect ждёт, пока запрос не попадёт в очередь сервера

//или пока сервер не ответит, что связь невозможна if(err==SOCKET_ERROR)

printf("\nCannot connecting, error %i\n", WSAGetLastError());

}

printf("\nConnecting OK\n");Sleep(1000);

len=send(mysock,buf,sizeof(char)*BUFNUM,0);

if(len==0)

printf("\nError sending\n");

else

printf("\nSending: %s, actual sended length is %i\n",buf,len); Sleep(4000);

shutdown(mysock,2);

closesocket(mysock);

WSACleanup(); return 0;

}

44

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 5.3. Пример сервера WinSock на Паскале

program WinSockServer;

//Пример использования классических блокирующих сокетов в Delphi

//используются только функции WinSock (без компонентов Delphi) //======= Сервер Winsock (консольное приложение) ============

{$APPTYPE CONSOLE} uses

SysUtils, Windows, WinSock; const

BUFNUM = 5; // Длина буфера приёма

HOSTNAME = ’localhost’; // Имя сервера (используем локальную машину) var

mysock, mysock1 : integer; // две переменные типа <<сокет>>

wsaData : TWSAData; // Указатель на данные, возвращаемые функцией инициализации библиотеки; myaddr, myaddr1 : sockaddr_in; // Адреса сокетов

err,len1,len2 : integer; // Код ошибки, длина сообщения

bufstr : string[BUFNUM+1] = ’_____’+chr(0); // сначала в буфере приёма только подчерки и 0 в конце

begin

err:=WSAStartup($0101, wsaData); // инициализируем библиотеку Winsock,

//это нестандартная функция (по сравнению с Unix)

//Вместо версии 1.1 уже можно использовать 2.2

if(err<0) then begin // если была ошибка, то выведем её код и закончим writeln(Format(’Winsock starting error %i’,[WSAGetLastError])); Halt(1);

end;

mysock:=socket(AF_INET,SOCK_STREAM,0); // создали сокет,

// область имён - INET, тип - с установлением соединения, протокол - по умолчанию if(mysock=INVALID_SOCKET) then begin

// если ошибка, то выведем её код, закроем библиотеку Winsock и закончим writeln(Format(’\nCannot create socket, error %i\n’,[WSAGetLastError]));

WSACleanup; halt(1);

end;

myaddr.sin_addr.s_addr := htonl(INADDR_ANY); // host to network long myaddr.sin_family := AF_INET;

myaddr.sin_port:=htons(1000); // номер порта, переведённый в <<сетевой порядок>> err:=bind(mysock, myaddr, sizeof(myaddr)); // связываем сокет

if(err<0) then begin // если была ошибка

writeln(Format(’\nCannot bind socket, error %i\n’,[WSAGetLastError()])); Sleep(3000); WSACleanup(); halt(1);

end; writeln(’Listening...’);

err:=listen(mysock,1); // переводим сокет в прослушивающий режим, // длина очереди - только один вызов

if (err<0) then begin // если была ошибка

Writeln(Format(’\nCannot listen socket, error %i\n’, [WSAGetLastError])); WSACleanup; halt(1);

end;

len1:=sizeof(myaddr1);

mysock1:=accept(mysock, PSockAddr(@myaddr1), @len1);

//приняли запрос на соединение

//(accept ждёт, пока не будет выполнен connect клиента) if(mysock1=INVALID_SOCKET) then begin // если ошибка

writeln(Format(’\nError accepting connection, error %i\n’,[WSAGetLastError])); WSACleanup(); halt(1);

end;

writeln(’Accepted ’,myaddr1.sin_addr.S_un_b.s_b1, ’.’, myaddr1.sin_addr.S_un_b.s_b2, ’.’, myaddr1.sin_addr.S_un_b.s_b3, ’.’, myaddr1.sin_addr.S_un_b.s_b4); // кто нас вызвал

Sleep(1000);

writeln(’Waiting message...’); len1:=0;

while(len1<BUFNUM) do begin // принимаем символ за символом сообщение длиной BUFNUM

len2:=recv(mysock1,bufstr[len1+1],BUFNUM-len1,0); len1:=len1+len2; writeln(’Received message: ’, bufstr);

end; // (принять всю строку нельзя, т.к. сообщения в сети могут

//

дробиться на пакеты и наоборот, слипаться)

bufstr[BUFNUM+1]:=chr(0); // конец строки

Sleep(2000); // чтобы

на экране всё менялось не слишком быстро

writeln(’Received: ’,

bufstr, ’; length = ’,len1);

shutdown(mysock1, 2);

// 2 - закрыли сокет и для чтения, и для записи

closesocket(mysock1);

 

closesocket(mysock);

WSACleanup; // закрыли библиотеку Winsock (в Unix этого нет) Sleep(2000); // подождали 5 сек

end.

45

Ю.В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

5.2.Программирование чат-сервера и клиента с использованием компонентов Delphi

Создадим простое приложение, которое будет играть роль чат-сервера. На форме будущего приложения разместим визуальные компоненты: ListBox (для отображения сообщений от клиентов) и Button (для завершения работы программы), а также невизуальный компонент Internet ServerSocket.

Настроим адрес порта серверного сокета Port := 777 (или любой другой свободный порт). Определим обработчики для двух событий серверного сокета (вкладка Events инспектора объектов): OnClientConnect и OnClientRead (листинг 5.4). Первое событие происходит при поступлении запроса на соединение от нового клиента, а второе — когда приходит очередное сообщение от клиента, с которым ранее было установлено соединение.

Кроме метода ReceiveText, принимающего данные через сокет в виде строки типа String, можно также использовать метод ReceiveBuf, принимающий данные в виде массива байтов.

Опишем обработчик события OnCreate для формы (см. листинг 5.4). При запуске приложения он будет активизировать серверный сокет.

Теперь осталось описать обработчик Button1Click для кнопки закрытия программы. Перед закрытием формы надо отключить и закрыть серверный сокет.

Сохраним проект и текст модуля в отдельную папку. Выполним компиляцию и запустим программу на выполнение. Проверить работу чат-сервера можно с помощью программы Windowsntelnet.exe. Подключитесь к порту 777 (имя машины localhost) и проверьте, отображаются ли в окне сервера символы, набираемые в окне клиента (telnet), и получает ли клиент от сервера копию своего сообщения.

Если всё работает, то приступим к программированию чат-клиента. Для этого нажмём комбинацию клавиш Ctrl+Alt+F11, чтобы вызвать браузер проекта. Нажмём правой кнопкой мыши на пункт ProjectGroup1 и выберем в появившемся контекстном меню команду Add New Project. Разместим на появившейся форме нового проекта компоненты ListBox, Edit и три кнопки («Подключиться к серверу», «Послать сообщение» и «Выход»).

Разместим на форме невизуальный компонент ClientSocket. Для него зададим значения свойств Host := localhost (или сетевое имя машины, на которой запущен чат-сервер) и Port := 777 и определим обработчики событий OnRead, OnError и обработчики нажатий на кнопки (листинг 5.5).

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

отправим несколько сообщений из каждого клиентского окна. Как всё работает? Желательно также проверить работу клиентов и сервера в сети.

Описанное приложение основывалось на клиент-серверной архитектуре (отдельно создавались приложения для клиента и сервера). Но данную задачу можно решить также и в рамках одноранговой (peer- to-peer) архитектуры, если объединить в одном приложении и свойства клиента, и свойства сервера. Для этого необходимо использовать одновременно и компонент ServerSocket, и компонент ClientSocket.

Пример такого “двуликого” приложения приведён в листингах 5.6–5.8. Главное меню данного приложения имеет единственный пункт File и четыре подпункта: Listen (Слушать), Connect (Соединиться), Disconnect (Разъединиться) и Exit (Выход).

В режиме сервера эта программа, как и предыдущие, может обрабатывать соединения с telnet. Заметим, что при попытке запустить несколько экземпляров этого приложения на одном компьютере будет возникать ошибка из-за связывания более чем одного серверного сокета с одним и тем же портом.

46

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 5.4. Чат-сервер

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ScktComp;

type

TForm1 = class(TForm) ServerSocket1: TServerSocket; ListBox1: TListBox;

Button1: TButton;

procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject);

procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); procedure ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject); // активизация серверного сокета begin

ServerSocket1.Active := True; end;

procedure TForm1.Button1Click(Sender: TObject); // завершение работы сервера begin

ServerSocket1.Active := False; ServerSocket1.Close;

Close;

end;

// Обработчик события OnClientRead (при поступлении сообщения от клиента):

procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var s : String; i : Integer;

begin

// Номер клиента > Текст сообщения:

s := IntToStr(Socket.SocketHandle) + ’> ’ + Socket.ReceiveText;

//Добавим сообщение в список: ListBox1.Items.Add(s);

//Перебор всех установленных соединений:

for i:=0 to ServerSocket1.Socket.ActiveConnections-1 do

// послать очередной клиентской программе новое сообщение:

if ServerSocket1.Socket.Connections[i].SocketHandle = Socket.SocketHandle then ServerSocket1.Socket.Connections[i].SendText(’ Я сказал: ’ + s)

else

ServerSocket1.Socket.Connections[i].SendText(s);

end;

// Обработчик события OnClientConnect (при подключении нового клиента):

procedure TForm1.ServerSocket1ClientConnect(Sender:TObject; Socket:TCustomWinSocket); begin

ListBox1.Items.Add(’Подключился ’ + IntToStr(Socket.SocketHandle)); end;

end.

47

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 5.5. Чат-клиент unit Unit2; interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ScktComp, StdCtrls;

type

TForm2 = class(TForm) ListBox1: TListBox; Edit1: TEdit; Button1: TButton; Button2: TButton; Button3: TButton;

ClientSocket1: TClientSocket;

procedure Button1Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button2Click(Sender: TObject);

procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);

end;

var

Form2: TForm2;

implementation {$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject); // Подключение к серверу begin

if not ClientSocket1.Active then ClientSocket1.Active := True; end;

procedure TForm2.Button2Click(Sender: TObject); // Отправка сообщения на сервер begin

ClientSocket1.Socket.SendText(Edit1.Text)

end;

procedure TForm2.Button3Click(Sender: TObject); // Завершение работы begin

ClientSocket1.Active := False; ClientSocket1.Close;

Close;

end;

//Обработчик события OnRead компонента ClientSocket (при получении сообщения): procedure TForm2.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); begin

ListBox1.Items.Add(Socket.ReceiveText);

end;

//Обработчик события OnError:

procedure TForm2.ClientSocket1Error(Sender: TObject;

Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); begin

if ClientSocket1.Active then ClientSocket1.Active := False; ShowMessage(’Ошибка!’);

ErrorCode := 0; // Подавляем обработку этой ошибки системой end;

end.

48

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 5.6. Одноранговое чат-приложение (начало)

unit main; interface uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus, StdCtrls, Buttons, ScktComp, ExtCtrls, ComCtrls;

type

TChatForm = class(TForm) MainMenu1: TMainMenu; File1: TMenuItem; Exit1: TMenuItem;

FileConnectItem: TMenuItem;

FileListenItem: TMenuItem; StatusBar1: TStatusBar; Bevel1: TBevel;

Panel1: TPanel; Memo1: TMemo; Memo2: TMemo; N1: TMenuItem;

SpeedButton1: TSpeedButton; Disconnect1: TMenuItem; ServerSocket: TServerSocket; ClientSocket: TClientSocket;

procedure FileListenItemClick(Sender: TObject); procedure FileConnectItemClick(Sender: TObject); procedure Exit1Click(Sender: TObject);

procedure Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormCreate(Sender: TObject);

procedure ServerSocketError(Sender: TObject; Number: Smallint; var Description: string; Scode: Integer; const Source,

HelpFile: string; HelpContext: Integer; var CancelDisplay: Wordbool); procedure Disconnect1Click(Sender: TObject);

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

Socket: TCustomWinSocket);

procedure ServerSocketAccept(Sender: TObject; Socket: TCustomWinSocket); procedure ServerSocketClientConnect(Sender: TObject;

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

Socket: TCustomWinSocket);

procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);

procedure ServerSocketClientDisconnect(Sender: TObject;

Socket: TCustomWinSocket);

protected

IsServer: Boolean; end;

var

ChatForm: TChatForm; Server: String;

49

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 5.7. Одноранговое чат-приложение (продолжение)

implementation {$R *.DFM}

procedure TChatForm.FileListenItemClick(Sender: TObject); begin

FileListenItem.Checked := not FileListenItem.Checked; if FileListenItem.Checked then begin

ClientSocket.Active := False; ServerSocket.Active := True; Statusbar1.Panels[0].Text := ’Listening...’;

end else begin

if ServerSocket.Active then ServerSocket.Active := False; Statusbar1.Panels[0].Text := ’’;

end;

end;

procedure TChatForm.FileConnectItemClick(Sender: TObject); begin

if ClientSocket.Active then ClientSocket.Active := False;

if InputQuery(’Computer to connect to’, ’Address Name:’, Server) then

if Length(Server) >

0 then

with ClientSocket

do begin

Host := Server;

Active := True;

FileListenItem.Checked := False; end;

end;

procedure TChatForm.Exit1Click(Sender: TObject); begin

ServerSocket.Close; ClientSocket.Close; Close; end;

procedure TChatForm.Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);

begin

if Key = VK_Return then if IsServer then

ServerSocket.Socket.Connections[0].SendText( Memo1.Lines[Memo1.Lines.Count - 1] )

else

ClientSocket.Socket.SendText( Memo1.Lines[Memo1.Lines.Count - 1] );

end;

procedure TChatForm.FormCreate(Sender: TObject); begin

FileListenItemClick(nil);

end;

procedure TChatForm.ServerSocketError(Sender: TObject; Number: Smallint; var Description: string; Scode: Integer; const Source, HelpFile: string; HelpContext: Integer; var CancelDisplay: Wordbool);

begin ShowMessage(Description);

end;

procedure TChatForm.Disconnect1Click(Sender: TObject); begin

ClientSocket.Active := False; ServerSocket.Active := True; Statusbar1.Panels[0].Text := ’Listening...’;

end;

50

Ю. В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

Листинг 5.8. Одноранговое чат-приложение (окончание)

procedure TChatForm.ClientSocketConnect(Sender: TObject;

Socket: TCustomWinSocket);

begin

Statusbar1.Panels[0].Text := ’Connected to: ’ + Socket.RemoteHost; end;

procedure TChatForm.ClientSocketRead(Sender: TObject;

Socket: TCustomWinSocket);

begin Memo2.Lines.Add(Socket.ReceiveText);

end;

procedure TChatForm.ServerSocketClientRead(Sender: TObject;

Socket: TCustomWinSocket);

begin Memo2.Lines.Add(Socket.ReceiveText);

end;

procedure TChatForm.ServerSocketAccept(Sender: TObject;

Socket: TCustomWinSocket);

begin

IsServer := True;

Statusbar1.Panels[0].Text := ’Connected to: ’ + Socket.RemoteAddress; end;

procedure TChatForm.ServerSocketClientConnect(Sender: TObject;

Socket: TCustomWinSocket);

begin Memo2.Lines.Clear;

end;

procedure TChatForm.ClientSocketDisconnect(Sender: TObject;

Socket: TCustomWinSocket);

begin FileListenItemClick(nil);

end;

procedure TChatForm.ClientSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);

begin

Memo2.Lines.Add(’Error connecting to : ’ + Server); ErrorCode := 0;

end;

procedure TChatForm.ServerSocketClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);

begin

Statusbar1.Panels[0].Text := ’Listening...’; end;

end.

51

Ю.В. Земсков. Системное и прикладное программное обеспечение. Конспект лекций, варианты заданий и методические указания в лабораторным работам. ВГИ ВолГУ, 2002 г.

5.3.Варианты заданий

1.Модифицируйте описанные здесь программы чат-сервера и клиента, чтобы каждый клиент при ведении протокола отправленных сообщений идентифицировался не номером (дескриптором соединения на серверной стороне), а именем, которое он определит при подключении к серверу (имена могут совпадать). Необходимо также заблокировать кнопку установления соединения, если оно уже активно, а при разрыве соединения выводить об этом сообщение (и на клиентской, и на серверной стороне).

2.Запрограммируйте чат-сервер и клиент, но с использованием блокирующих сокетов библиотеки WinSock.

3.Создайте сетевое приложение для вычисления числа по формуле

1

 

 

= 0

4

dx:

 

1 + x2

Интеграл необходимо вычислять методом прямоугольников. Сервер должен спрашивать у пользователя количество интервалов, на которые необходимо разбить отрезок интегрирования. Затем сервер должен рассылать клиентам необходимые параметры и ждать от них результатов, после чего находить сумму пришедших чисел и выводить на экран результат интегрирования.

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

5.То же, что и в пункте 4, но для произведения двух матриц.

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

Развитие задачи: LATEX–сервер.

7.Запрограммируйте простейший вариант Web-сервера (клиентом может быть обычный браузер), обрабатывающий только один запрос клиента — передать файл с указанным именем.

8.Создайте приложение для сетевой игры “крестики–нолики”:

а) одноранговый вариант, без сервера;

б) клиент-серверный вариант, каждый игрок выбирает себе партнёра из списка свободных игроков, подключенных к серверу; игра начинается, если второй игрок согласен начать партию.

9. Создайте приложение для сетевой игры “реверси”:

а) одноранговый вариант, без сервера;

б) клиент-серверный вариант, каждый игрок выбирает себе партнёра из списка свободных игроков, подключенных к серверу; игра начинается, если второй игрок согласен начать партию.

10. Создайте приложение для сетевой игры “морской бой”:

а) одноранговый вариант, без сервера;

б) клиент-серверный вариант, каждый игрок выбирает себе партнёра из списка свободных игроков, подключенных к серверу; игра начинается, если второй игрок согласен начать партию.

11. Создайте сетевой вариант графического редактора (на основе графического редактора из демонстрационных программ, расположенных в папке BorlandnDelphi6nDemosnDocnGraphex): при рисовании графических примитивов в окне одного приложения в окне второго дублируются все действия пользователя.

52

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