Чтение онлайн

ЖАНРЫ

UNIX: разработка сетевых приложений
Шрифт:
Обработка ответа

31-33
Если ответ — это сообщение
T_BIND_ACK
, то связывание прошло успешно, и мы возвращаемся. Фактический адрес, связанный с точкой доступа, возвращается в элементе
addr
нашей структуры
bind_ack
, которую мы игнорируем.

34-39
Если ответ — это сообщение
T_ERROR_ACK
, мы проверяем, было ли сообщение получено целиком, и выводим три значения, содержащиеся в возвращенной структуре. В этой простой программе при возникновении
ошибки мы просто прекращаем выполнение и ничего не возвращаем вызывающему процессу.

Чтобы увидеть ошибки, которые могут возникнуть в результате запроса на связывание, мы слегка изменим нашу функцию

main
и попробуем связать какой- либо порт, отличный от 0. Например, если мы попробуем связать порт 1 (что требует прав привилегированного пользователя, так как это порт с номером меньше 1024), мы получим следующий результат:

solaris % tpi_daytime 127.0.0.1

T_ERROR_ACK from bind (3, 0)

В этой системе значение константы

EACCESS
равно 3. Если мы поменяем номер порта, задав значение большее 1023, но используемое в настоящий момент другой точкой доступа TCP, мы получим:

solaris % tpi_daytime 127.0.0.1

T_ERROR_ACK from bind (23, 0)

В данной системе значение константы

EADDRBUSY
равно 23.

Следующая функция показана в листинге 31.4. Это функция

tpi_connect
, устанавливающая соединение с сервером.

Листинг 31.4. Функция tpi_connect: установление соединения с сервером

//streams/tpi_connect.c

1 #include "tpi_daytime.h"

2 void

3 tpi_connect(int fd, const void *addr, size_t addrlen)

4 {

5 struct {

6 struct T_conn_req msg_hdr;

7 char addr[128];

8 } conn_req;

9 struct {

10 struct l_conn_con msg_hdr;

11 char addr[128];

12 } conn_con;

13 struct strbuf ctlbuf;

14 union T_primitives rcvbuf;

15 struct T_error_ack *error_ack;

16 struct T_discon_ind *discon_ind;

17 int flags;

18 conn_req.msg_hdr.PRIM_type = T_CONN_REQ;

19 conn_req.msg_hdr.DEST_length = addrlen;

20 conn_req.msg_hdr.DEST_offset = sizeof(struct T_conn_req);

21 conn_req.msg_hdr.OPT_length = 0;

22 conn_req.msg_hdr.OPT_offset = 0;

23 memcpy(conn_req.addr, addr, addrlen); /* sockaddr_in{} */

24 ctlbuf.len = sizeof(struct T_conn_req) + addrlen;

25 ctlbuf.buf = (char*)&conn_req;

26 Putmsg(fd, &ctlbuf, NULL, 0);

27 ctlbuf.maxlen = sizeof(union T_primitives);

28 ctlbuf.len = 0;

29 ctlbuf.buf = (char*)&rcvbuf;

30 flags = RS_HIPRI;

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

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

33 err_quit("tpi_connect: bad length from getmsg");

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_connect: bad length for T_ERROR_ACK");

40 error_ack = (struct T_error_ack*)&rcvbuf;

41 err_quit("tpi_connect: T_ERROR_ACK from conn %d, %d)",

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

43 default:

44 err_quit("tpi connect, unexpected message type: &d", rcvbuf.type);

45 }

46 ctlbuf.maxlen = sizeof(conn_con);

47 ctlbuf.len = 0;

48 ctlbuf.buf = (char*)&conn_con;

49 flags = 0;

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

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

52 err_quit("tpi_connect2: bad length from getmsg");

53 switch (conn_con.msg_hdr.PRIM_type) {

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_connect2: bad length for T_DISCON_IND");

59 discon_ind = (struct T_discon_ind*)&conn_con.msg_hdr;

60 err_quit("tpi_connect2: T_DISCON_IND from conn (%d)",

61 discon_ind->DISCON_reason);

62 default:

63 err_quit("tpi_connect2: unexpected message type. %d",

64 conn_con.msg_hdr PRIM_type);

65 }

66 }

Поделиться с друзьями: