Программирование >>  Структура ядра и системные вызовы 

1 ... 65 66 67 [ 68 ] 69 70 71 ... 98


if ((bind= (struct t bind*)t alloc(tid, T BIND, T ALL))==0)

t error( t alloc for t bind ); return -1;

bind->qlen =1; /* максимальное количество

запросов на соединение */ if (nconf) { Internet-адрес

bind->addr = *(addr->n addrs); ) else { локальный адрес

bind->addr.len = sizeof(int);

*(int*)bind->addr.buf = local addr;

if ((rc = t bind(tid, bind, bind)) < 0)

t error( t bind ); else /* отобразить фактически назначенный адрес */

cerr bind: (*(int*)bind->addr.buf) endl; return rc;

/* ждать запроса на соединение от клиентской конечной

точки транспортировки */ int listen ( struct tcall*& call ) {

if (Icall && (call = (struct t call*)t alloc(tid, T CALL, T ALL))==0)

t error( t alloc ); return -1;

if ((rG=t listen(tid,call)) < 0) t error( t listen ); return rc;

/* принять запрос на соединение от клиентской конечной

точки транспортировки */ int accept ( struct t call * call ) {

/* создать новую конечную точку для связи с клиентом */ int resfd; .

if (nconf) Internet IPC

resfd = t open( nconf->nc device, 0 RDWR, 0); else Local IPC, must be connection-based

resfd = t open(TCP TRANS, 0 RDWR, 0); if (resfd < 0) {

t error( t open for resfd );

return -1;

/* присвоить новой конечной точке произвольное имя */

if (t bind(resfd,0,0) < 0)

t error( t bind for resfd ) return -2;

/* соединить новую конечную точку с клиентом */

if (t accept(tid, resfd, call) < 0)

if {t errno == TLOOK) {

if (t rcvdis(tid, 0) < 0)

t error( t rcvdis ); return -4;

if (t close(resfd) < 0) (

t error{ t close ); return -5;

return DISCONNECT;

t error( t acept ); return -6;

return resfd;

/* инициализировать запрос на соединение с серверной

конечной точкой транспортировки */ int connect О {

struct t call *call;

if ((call = (struct t call*)t alloc{tid, T CALL, TALL))==0)

t error( t alloc ); return -1;

if (nconf)

call->addr = *(addr->n addrs); else (

call->addr.len = sizeof(int);

*{int*)call->addr.buf = local addr;

cerr client: connect to addr=

(*(int*)call->addr.buf) endl;

if ({rc=t connect(tid,call,0)) < 0) {

t error( client: t connect ); return -2;

return rc;



/* передать сообщение в удаленную конечную точку

транспортировки, с которой установлено соединение */ int write ( char* buf, int len, int nsicl=-l )

if ((rc<=t snd(nsid==-l ? tid : nsid, buf, len, 0)) < 0)

t error( t snd ) ; return rc;

/* прочитать сообщение, поступившее из удаленной точки

транспортировки, с которой установлено соединение */ int read( char* buf, int len, ints flags, int nsid=-l ) {

if ((rc=t rcv(nsid==-l ? tid : nsid, buf, len, Sflags)) < 0)

t error( t snd ); return rc; );

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

int writeto( char* buf, Int len, int flag,

char* service, char* host, int nsid=-l )

struct t unitdata* ud = alloc ud(nsid, service, host); ud->udata . len = lerj; ud->udata.buf = buf;

if ((rc=t sndudata(nsid==-l ? tid : nsid, ud)) < 0)

t error ( t sndudata ) ; return rc;

/* передать дейтаграммное сообщение в конечную точку,

расположенную на этой же машине */ int writeto( char* buf, int len, int flag, int port no, int nsid=-l )

struct t unitdata* ud = alloc ud(nsid,port no); ud->udata.len = len;

ud->udata.buf = buf; ,

if ((rc=t sndudata(nsid==-l ? tid : nsid, ud)) < 0)

t error( t sndudata ); return rc;

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

точку, адрес которой определен в ud */ int writeto( char* buf, int len, int flag,

struct t unitdata* ud, int nsidf=-l )

ud->udata. len = len; . - v. ,(j

ud->udata.buf = buf;

if ((rc=t sndudata(nsid==-l ? tid : nsid, ud) < 0) t error ( t sndudata ) ;

return rc;

/* диагностическое сообщение об ошибке приема */

void report uderr( int nsid )

if ((t errno) == (TLOOK)) ( struct t uderr *uderr;

if ((uderr=(struct t uderr*)talloc(nsid==-l ? tid : nsid, T UDERROR, T ALL))==0)

t error( t alloc of t uderr ); return;

if {(rc=t rcvuderr(nsid==-l ? tid : nsid, uderr)) < 0)

t error( t rcvuderr ) ; else cerr bad datagram, error* uderr->error endl;

t f ree((char*)uderr,T UDERROR) ;

else t error( t rcvudata );

>J* принять дейтаграммное сообщение из удаленной конечной точки

:f,;,--

транспортировки */

int readfrom( char* buf, int len, ints flags,

struct t unitdata*S ud, int nsid =-1)

if (!ud ss (ud=(struct t unitdata*)t alloc(neid==-l ? tid : nsid, T UNITDATA, T ALL))-0)

{ . , -Mi

t error( t alloc of t unitdata ); return

ud->udata.len = len; ud->udata.buf = buf;

if ((rc=t rcvudata(nsid==-l ? tid : nsid, ud, Sflags)) < 0)

report uderr(nsid); return rc;

/* закрыть соединение путем отправки уведомления

о преждевременном разъединении */ int shutdown( int nsid = -1 )

return t snddis( nsid==-l ? tid :.nsid, 0 );

}; /* class TLI */

#endif

Открытые функции-члены класса TLI почти однозначно соответствуют открытым функциям-членам класса sock. Это обусловлено однозначным соответствием между API TLI и API гнезд.

Основное различие между классом TLI и классом sock состоит в правилах именования, установленных для каждого типа объекта. В частности, имя объекта sock может быть путевым UNIX-именем (для гнезда домена UNIX)



или комбинацией хост-имени и имени порта (для гнезда домена Internet). Имя объекта ТЫ может быть целым числом (для локального соединения) или комбинацией хост-имени и имени сервиса (для соединения, осуществляемого через Internet).

Еще одно различие между классом ТЫ и классом sock касается функции listen. В то время как функция sockr.listen лишь устанавливает максимально допустимое для объекта sock количество запросов на соединение, функция TLIr.listen используется для перехода в режим ожидания поступления клиентского запроса на соединение. Функция sock:-.accept, по сути дела, объединяет функции TLI::listen и TLI::accept.

Класс TLI не поддерживает неблокирующий режим, но пользователи могут, модифицировав его, получить такую поддержку. В следующих двух разделах описаны приложения IPC, в которых используется класс ТЫ.

11.6. Пример передачи сообщений по схеме клиент/сервер

Первый пример использования класса ТЫ - это новая версия приложения, представленного в разделе 10.3.7 (передача сообщений между клиентами и сервером). В этой версии используются конечные точки транспортировки с установлением соединения, с помощью которых формируется канал связи между сервером сообщений и клиентскими процессами. Поскольку сервер устанавливает связь непосредственно с каждым клиентским процессом, любое посылаемое от клиента сообщение должно представлять собой сервисную команду (например, LOCAL TIME, UTC TIME, QUIT CMD и т.д.), введенную в виде строки символов. Сервер посылает свой ответ клиенту также в виде строки символов.

Ниже приведена программа сервера сообщений, имя которой tli msg srv. С.

tinclude tli.h finclude <sys/times.h> ♦include <sys/types.h>

♦define MSGl Invalid cmd to message server

typedef enum { LOCAL TIME, GMT TIME, QUIT CMD, ILLEGAL CMD ) CMDS;

/* обработать команды клиента */ void process cmd (tli* sp, int fd )

char buf[80]; time t tim; char* cptr; int flags;

switch (forkO) {

case -1: perror( fork ); return; case 0: break;

default: return; . родительский процесс

/* читать команды клиента до поступления символа EOF

или QUIT CMD */ while (sp->read(buf, sizeof buf, flags, fd) > 0) (

cerr server: read cmd: buf Xn ; int cmd = ILLEGAL CMD;

(void)sscanf(buf, %d . scmd); switch (cmd) (

case LOCAL TIME:

tim = time(0);

cptr = ctime(stim);

sp->write(cptr, strlen(cptr)+1, fd);

break; case GMT TIME:

tim = time(0);

cptr = asctime(gmtime(itim));

sp->write(cptr, strlen(cptr)+1, fd);

break; case QUIT CMD:

sp->shutdown(fd);

exit(O); default:

sp->write(MSGI, sizeof MSGl, fd);

exit(O);

int main( int argc, char* argv[])

char buf[80]. socknm[80]; int port=-l, nsid, rc;.,j fd set select set;

struct timeval timeReci

M .

if (argc < 2) (

returnM f m.<serviceno> [<host> ]\n ;

/* проверить, указан ли номер порта */ (void)sscanf(argv[l], %d .sport);

tli°*sp установлением соединения */

if (port==-l)



1 ... 65 66 67 [ 68 ] 69 70 71 ... 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика