Поток записей
Этот поток позволяет разбивать данные на записи.
Этот тип потока создается с помощью программы xdrrec_create() :
void xdrrec_create(xdr_handle, sendsize, recvsize, iohandle, readproc, writeproc)
XDR *xdr_handle; /* handle */
int sendsize,recvsize; /* размер буферов */
char *iohandle; /* идентификатор */
int (*readproc)(); /* процедура чтения */
int (*writeproc)(); /* процедура записи */
Параметры sendsize и recvsize соответствуют размеру буферов приема и передачи. Фактически, этот тип потока позволяет сохранять в буферах памяти данные, передаваемые процессом-передатчиком процессу-приемнику.
Аргумент iohandle определяет ресурс, который позволяет записывать или считывать данные XDR.
Два последних аргумента - это адреса двух процедур, которые, таким образом, должны быть определены заранее. Если буфер приемника пуст, фильтр XDR вызывает процедуру readproc() для чтения данных. Если буфер передачи полон, фильтр XDR вызывает процедуру writeproc() для записи данных. Этим процедурам передается параметр iohandle. Формат процедур :
int func(iohandle,buf,nbytes)
char *iohandle; /* идентификатор */
char *buf; /* адрес буфера */
int nbytes; /* размер буфера */
iohandle может быть FILE pointer'ом или сокетом TCP или, вообще, любым объектом, позволяющим записывать данные в буфер памяти. Функция возвращает число пересланных байтов или -1 - в случае ошибки.
В отличие от других потоков, поток записей можно использовать как для кодирования, так и для декодирования. Для этого надо соответствующим образом установить значение поля x_op в handle XDR.
Помимо фильтров, для управления потоком записей используются еще три функции библиотеки XDR :
- функция xdrrec_endofrecord()
bool_t xdrrec_endofrecord(xdr_handle,sendnow)
XDR *xdr_handle; /* handle */
bool_t sendnow; /* TRUE или FALSE */
Эта функция указывает на конец записи. Если параметр sendnow установлен в TRUE, происходит принудительная запись содержимого буфера (flush). В противном случае, содержимое буфера будет передано только тогда,когда он заполнится до конца. Значение этого параметра следует установить в TRUE, если приемнику передается последний буфер с данными.
- функция xdrrec_skiprecord() bool_t xdrrec_skiprecord(xdr_handle)
XDR *xdr_handle; /* handle */
Этот примитив используется процессом-приемником. Он необходим для чтения следующей записи. На практике, этим примитивом следует пользоваться каждый раз перед переходом к чтению новой записи, в особенности перед первой попыткой чтения.
- функция xdrrec_eofrecord() bool_t xdrrec_eofrecord(xdr_handle)
XDR *xdr_handle; /* handle */
Этот примитив используется процессом-приемником для определения того, есть ли еще данные в буфере чтения.
ПРОГРАММА 47
/*Использование потока записей для файла */
/*файл fict.h */
#include <stdio.h> #include <rpc/rpc.h> #define FIC "/tmp/ficxdr" /*пpоцедуpа XDR считывания из файла */ readp(); /*файл client.c */ writep();
/*пpоцедуpа XDR записи в файл */ #include "fict.h"
main() { XDR xdrs; /*дескpиптоp XDR */ FILE *fp; /*указатель файла */ int val1=5; /*целое */ int val2=7; /*целое */ float val3=6.89; /*с плавающей точкой */ float val4=5.678; /*с плавающей точкой */
/*откpытие файла на запись */ fp = fopen(FIC, "w"); /*создание потока записей XDR */ xdrrec_create(&xdrs, 0, 0, fp, readp, writep); /*pежим записи */ xdrs.x_op - XDR_ENCODE; /*начинаем писать пеpвую запись */ xdr_int(&xdrs, &val1); xdr_int(&xdrs, &val2); /*отмечаем конец записи, не записывая содеpжимого буфеpа */ xdrrec_endofrecord(&xdrs, FALSE); /*пишем втоpую запись */ xdr_float(&xdrs, &val3); xdr_float(&xdrs, &val4); /*запись содеpжимого буфеpа */ xdrrec_endofrecord(&xdrs, TRUE); }
/*файд serveur.c */ #include "fict.h"
main()
{ XDR xdrs; /*дескpиптоp XDR */ FILE *fp; /*указатель файла */ int val1; /*целое */ int val2; /*целое */ float val3; /*с плавающей точкой */ float val4; /*с плавающей точкой */
/*откpытие файла на чтение */ fp = fopen(FIC, "r"); /*создание потока записей XDR */ xdrrec_create(&xdrs, 0, 0, fp, readp, writep); /*pежим считывания */ xdrs.x_op - XDR_DECODE; /*пеpеходим к пеpвой записи */ xdrrec_skiprecord(&xdrs); /*считываем пеpвую запись*/ xdr_int(&xdrs, &val1); xdr_int(&xdrs, &val2); /*пеpеходим ко втоpой записи */ xdrrec_skiprecord(&xdrs); /*считываем втоpую запись */ xdr_float(&xdrs, &val3); xdr_float(&xdrs, &val4); }
/*файл cdr.c */ /*содеpжит пpоцедуpы readp() и writep() #include <stdio.h>
/*пpоцедуpа считывания из файла */ readp(fp, buf, n) FILE *fp; char *buf; unsigned int n; { int nlu; nlu = fread(buf, 1, n, fp); if (nlu == 0) nlu = -1; return nlu; } /*пpоцедуpа записи в файл */ writer(fp, buf, n) FILE *fp; char *buf; unsigned int n; { int necr; necr = fwrite(buf, 1, n, fp); if (necr == 0) necr= -1; return necr; {