|
Программирование >> Структура ядра и системные вызовы
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)
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |