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

Міністерство освіти і науки, молоді та спорту України

Кіровоградський національний технічний університет

Механіко-технологічний факультет

Кафедра: Програмного забезпечення

Дисципліна: ”Обчислювальні системи”

Лабораторна робота № 6

Тема: «Комунікаційне програмне забезпечення рівня користувача. Виклик віддаленої процедури»

Виконав: ст.гр.КІ-10-1

Перевірив: викладач

Минайленко Р.М.

Кіровоград 2013

Завдання до лабораторної роботи

Напишіть на мові С функції, які могли б використовувати як клієнтський так і серверний сурогати для виконання RPC - виклику стандартної функції printf, а також головний модуль для тестування цих функцій.

Клієнт та сервер повинні спілкуватися за допомогою структури даних, яка передається по мережі. Накладіть розумні обмеження на довжину рядка, формату та число, типи та розміри змінних, які будуть приймати клієнтські сурогати.

Створення DEF-файла

Напишемо функцію для обчислення синуса:

double sin1(double x)

{

int ii; double xx,r,sl,f,delta=0.0001;

sl=x; ii=1; r=0; xx=x*x;

f= fabs(sl);

while (f>delta)

{

r=r+sl;

sl=-(sl*xx/(2*ii))/(2*ii+1);

f=fabs(sl);

ii=ii+1 ;

}

return(r);

}

Программа для тестування функції

unit SINTST;

interface

uses

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

Dialogs,

StdCtrls, Buttons, TeEngine, Series, ExtCtrls,

TeeProcs, Chart,a1;

type

TForm1 = class(TForm)

Chart1: TChart;

Series1: TFastLineSeries;

BitBtn1: TBitBtn;

procedure BitBtn1Click(Sender: TObject);

private

{ Private declarations }

public { Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

function sin1(x: Double): Double;

VAR I:INTEGER; R:DOUBLE;SL:DOUBLE;XX:DOUBLE;

CONST DELTA=0.0001 ;

begin

SL:=X; I:=1;

R:=0; XX:=X*X;

WHILE (ABS(SL)>DELTA) DO

BEGIN

R:=R+SL;

SL:=-(SL*XX/(2*I))/(2*I+1);

inc(i);

END;

result:=R;

end; {sin1}

procedure TForm1.BitBtn1Click(Sender: TObject);

VAR I:INTEGER;X:DOUBLE;Y:DOUBLE;

begin

FOR I:=1 TO 270 DO

BEGIN X:=0.1*I;

Y:=sin1(X);

CHART1.SERIES[0].ADDXY(X,Y,FLOATTOSTR(X),clwHITE);

END

end;

end.

Створення серверної частини (C/C++)

В результаті використання утиліти rpcmake.exe (або rpcmgui.exe) з парамерамі, відповідними вибору C або C++ як мова для сервера, отримаємо наступні файли: a1_c.c (stub-код, який можна вбудовувати в клієнтське застосування), a1_s.c (вихідний текст консольного застосування для сервера функціональності), a1_s.h - h-файл для myserv_s.c, a1.h - h-файл, що містить оголошення функцій без їх реалізації (використовується в клієнтському застосуванні). Реалізацію цих функцій (a1.c) слід створити розробнику. Код для сервера a1.с, сгенерований цією утилитою, виглядає наступним чином:

/*########################

# Server Proxy Procedure Code

# generated by rpcmake version2.0

# on Thursday, December 31, 1998 at 19:17:39

#

# interface: a1

#

########################

# server stub routines #

########################*/

#ifdef __mpexl

#include "dceinc.h"

#else

#include <dceinc.h>

#endif

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#ifdef __cplusplus

extern "C" {

#endif

/* RPC stub and stub handle definitions */

void rpc_handle (char *, struct table *, int);

void rpc_sin1 (struct table *, int);

#ifdef __cplusplus

}

#endif

void rpc_sin1 (struct table *dce_table,int Socket)

{

double x;

int _i;

double sin1(double);

x = dce_pop_double(dce_table,"x");

dce_push_double(Socket,"dce_result",

sin1(x));

}

int main(int argc,char **argv)

{

char *ode_file = NULL,*ode_server = NULL;

char dce_func[VARLEN];

struct table *dce_table;

int called_init_func = 0;

int socket,rsocket;

if (!parse_args(&argc, argv,&ode_file)) {

printf ("Env flag (-e) not set\n");

ode_file = argc > 1 ? argv[argc-1] : (char *) NULL;

}

if (dce_setenv(ode_file,NULL,NULL) == 0) {

fprintf(stderr,"Set env %s failed\n", ode_file);

fprintf (stderr,"Reason: %s\n", dce_errstr());

exit(1);

}

ode_server = dce_servername("a1");

dce_checkver(2, 0);

if ((socket = dce_init_server( ode_file,ode_server)) <= 0) {

fprintf (stderr,"setup server failed\n");

fprintf (stderr,"Reason: %s\n", dce_errstr());

dce_set_exit();

}

while(1) {

dce_table = dce_waitfor_call(socket,dce_func);

if (dce_should_exit() ||

dce_err_is_fatal() )

{break;

}

else{

if (dce_server_is_ded()) {

dce_spawn(socket,argc,argv,ode_file,ode_server);

socket = dce_retsocket(); /* save for future */

}

rsocket = dce_retsocket(); /* (old socket closed) */

rpc_handle(dce_func,dce_table,rsocket);

dce_send(rsocket,dce_func);

dce_recv_conf(rsocket);

dce_release();

dce_table_destroy(dce_table);

if (!dce_server_is_ded()) {

dce_close_socket(rsocket);

}

}

}

dce_close_socket(rsocket);

dce_table_destroy(dce_table);

return(0);

}

void rpc_handle(char *func,struct table *dce_table,

int Socket)

{

if (strcmp(func,"sin1")==0)

(void)rpc_sin1(dce_table,Socket);

else (void)dce_unknown_func(func, dce_table, Socket);

}

H-файл a1_s.h виглядає наступним чином:

/*************************************

*

* Server Header for a1

* Generated by rpcmake version 3.0

* on Thursday, December 31, 1998 at 19:17:39

* **************************************/

#ifdef __cplusplus

extern "C" {

#endif

extern double sin1(double );

#ifdef __cplusplus

}

#endif

Код реалізації функції слід створити розробнику. Він повинен мати приблизно наступний вигляд:

USEUNIT("A1_s.c");

USELIB("odet30.lib");

//-----------------------------------------------------------------

double sin1(double x)

{

int ii; double xx,r,sl,f,delta=0.0001;

sl=x; ii=1; r=0; xx=x*x;

f= fabs(sl);

while (f>delta)

{

r=r+sl;

sl=-(sl*xx/(2*ii))/(2*ii+1);

f=fabs(sl);

ii=ii+1 ;

}

return(r);

}

Тестування серверу функціональності

Для тестування сервера потрібно створити для нього env-файл з описом змінних оточення:

DCE_BROKER=elmanova,16000

DCE_DEBUGLEVEL=DEBUG,DEBUG

DCE_LOG=server.log

Далі слід запустити Entera Broker( якщо він ще не запущений), створив перед цим конфігурований файл broker.env

start broker -e broker.env

Після цього слід створити і запустити командний файл для запуску сервера:

set odedir = c:\OpenEnv\Entera\TCP

start "IT IS A SERVER" a1_s -e server.env

Створення клієнтського оточення (C/C++)

Код, сгенерований утилітою rpcmake для клієнта C/C++ (a1_c.c), має наступний вигляд:

/*########################

# Client Proxy Procedure Code

# generated by rpcmake version 3.0

# on Thursday, December 31, 1998 at 19:17:39

#

# interface: a1

# */

#include <stdio.h>

#if defined __mpexl || defined _MACINTOSH_

#include "dceinc.h"

#else

#include <dceinc.h>

#endif

double sin1(double x)

{

double rv = 0; int Socket;

struct table *dce_table = NULL;

dce_checkver(2, 0);

if ((Socket = dce_findserver("a1")) >= 0) {

dce_push_double(Socket,"x",x);

dce_table = dce_submit("a1", "sin1", Socket);

}

rv = dce_pop_double(dce_table,"dce_result");

dce_table_destroy(dce_table);

return(rv);

}

H-файл для него має наступний вигляд:

**************************************/

*

* Client Header for a1

* Generated by rpcmake version 3.0

* on Thursday, December 31, 1998 at 19:17:39

* **************************************/

#ifdef __cplusplus

extern "C" {

#endif

extern double sin1(double );

#ifdef __cplusplus

}

#endif

Код клиентскої програми, в випадку С++Builder має наступний вигляд:

//-----------------------------------------

#include "dceinc.h"

#include "myserv.h"

USEUNIT("a1_c.c");

USELIB("odet30.lib");

//-----------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)

{

dce_setenv("client.env",NULL,NULL); }

//---------------------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)

{

dce_release();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn1Click(TObject *Sender)

{

int i; double x1,y;

for (i=1;i<271;i++)

{

x1=0.1*float(i);

y=sin1(x1);

Chart1->Series[0]->AddXY(x1,y,FloatToStr(x1),clWhite);

} }

//-----------------------------------------

Створимо обробник подій, який зв’язаний з натисненням кнопки CommandButton1 в документі (його прототип вже є в редакторі коду).

Private Sub CommandButton1_Click()

x = sin1#(0.25)

UserForm1.Label1.Caption = x

x = sin1#(0.5)

UserForm1.Label2.Caption = x

x = sin1#(0.75)

UserForm1.Label3.Caption = x

x = sin1#(1#)

UserForm1.Label4.Caption = x

x = sin1#(1.25)

UserForm1.Label5.Caption = x

x = sin1#(1.5)

UserForm1.Label6.Caption = x

x = sin1#(1.75)

UserForm1.Label7.Caption = x

x = sin1#(2#)

UserForm1.Label8.Caption = x

x = sin1#(2.25)

UserForm1.Label9.Caption = x

x = sin1#(2.5)

UserForm1.Label10.Caption = x

x = sin1#(2.75)

UserForm1.Label11.Caption = x

x = sin1#(3#)

UserForm1.Label12.Caption = x

UserForm1.Show

End Sub

Після обробника події додамо stub-код, що міститься у файлі a1_c, що згенерував.vb. І, нарешті, експортуємо в проект за допомогою пункту меню Файл/Експорт файлу модуль odet30.bas з комплекту постачання Entera. Створимо файл client.env у каталозі, що містить документ. Можливо, потрібно буде відредагувати приєднаний до проекту модуль, змінивши параметри процедури dce_setenv, вказавши дорогу до файлу client.env: rv = dce_setenv("client.env", "", "") Відзначимо, що бібліотека odet30.dll повинна бути доступною нашій програмі, так як із неї викликаються функції.

3

Соседние файлы в папке Вычислительные системы