Добавить в цитаты Настройки чтения

Страница 364 из 399

33   err_quit("tpi_co

34  switch (rcvbuf.type) {

35  case T_OK_ACK:

36   break;

37  case T_ERROR_ACK:

38   if (ctlbuf.len < (int)sizeof(struct T_error_ack))

39    err_quit("tpi_co

40   error_ack = (struct T_error_ack*)&rcvbuf;

41   err_quit("tpi_co

42    error_ack->TLI_error, error_ack->UNIX_error);

43  default:

44   err_quit("tpi co

45  }

46  ctlbuf.maxlen = sizeof(co

47  ctlbuf.len = 0;

48  ctlbuf.buf = (char*)&co

49  flags = 0;

50  Getmsg(fd, &ctlbuf, NULL, &flags);

51  if (ctlbuf.len < (int)sizeof(long))

52   err_quit("tpi_co

53  switch (co

54  case T_CONN_CON:

55   break;

56  case T_DISCON_IND:

57   if (ctlbuf.len < (int)sizeof(struct T_discon_ind))

58    err_quit("tpi_co

59   discon_ind = (struct T_discon_ind*)&co

60   err_quit("tpi_co

61   discon_ind->DISCON_reason);

62  default:

63   err_quit("tpi_co

64   co

65  }

66 }

18-26 В TPI определена структура T_co

struct T_co

 long PRIM_type;   /* T_CONN_REQ */

 long DEST_length; /* длина адреса получателя */

 long DEST_offset; /* смещение адреса получателя */

 long OPT_length;  /* длина параметров */

 long OPT_offset;  /* смещение параметров */

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

};

Как и в случае функции tpi_bind, мы определяем свою собственную структуру с именем co

27-45 Мы вызываем функцию getmsg, ожидая получить в ответ либо сообщение T_OK_ACK, если было начато установление соединения, либо сообщение T_ERROR_ACK (которые мы уже показывали выше). В случае ошибки мы завершаем выполнение программы. Поскольку мы не знаем, сообщение какого типа мы получим, то определяем объединение с именем T_primitives для приема всех возможных запросов и ответов и размещаем это объединение в памяти как входной буфер для управляющей информации при вызове функции getmsg.

struct T_ok_ack {

 long PRIM_type;    /* T_OK_ACK */

 long CORRECT_prim; /* корректный примитив */

};

46-65 Сообщение T_OK_ACK, полученное нами на предыдущем этапе, указывает лишь на то, что соединение успешно начало устанавливаться. Теперь нам нужно дождаться сообщения T_CONN_CON, указывающего на то, что другой конец соединения подтверждает получение запроса на соединение.

struct T_co

 long PRIM_type;  /* T_CONN_CON */

 long RES_length; /* длина адреса собеседника */

 long RES_offset; /* смещение адреса собеседника */

 long OPT_length; /* длина параметра */

 long OPT_offset; /* смещение параметра */

 /* далее следуют адрес протокола и параметры собеседника */

};

Мы снова вызываем функцию getmsg, но ожидаемое нами сообщение посылается как сообщение типа M_PROTO, а не как сообщение M_PCPROTO, поэтому мы обнуляем флаги. Если мы получаем сообщение T_CONN_CON, значит, соединение установлено, и мы возвращаемся, но если соединение не было установлено (по причине того, что процесс собеседника не запущен, истекло время ожидания или еще по какой-либо причине), то вместо этого вверх по потоку отправляется сообщение T_DISCON_IND:

struct T_discon_ind {

 long PRIM_type;     /* T_DISCON_IND */