Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

Листинг 16.7. Неблокируемая функция connect

//lib/connect_nonb.c

1 #include "unp.h"

2 int

3 connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec)

4 {

5 int flags, n, error;

6 socklen_t len;

7 fd_set rset, wset;

8 struct timeval tval;

9 flags = Fcntl(sockfd, F_GETFL, 0);

10 Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

11 error = 0;

12 if ((n = connect(sockfd, saptr, salen)) < 0)

13 if (errno != EINPROGRESS)

14 return (-1);

15 /* Пока соединение устанавливается, мы можем заняться чем-то другим */

16 if (n == 0)

17 goto done; /* функция connect завершилась немедленно */

18 FD_ZERO(&rset);

19 FDSET(sockfd, &rset);

20 wset = rset;

21 tval.tv_sec = nsec;

22 tval.tv_usec = 0;

23 if ((n = Select(sockfd + 1, &rset, &wset, NULL,

24 nsec ? &tval : NULL)) == 0) {

25 close(sockfd); /* тайм-аут */

26 errno = ETIMEDOUT;

27 return (-1);

28 }

29 if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {

30 len = sizeof(error);

31 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)

32 return (-1); /*в Solaris ошибка, ожидающая обработки */

33 } else

34 err_quit("select error: sockfd not set");

35 done:

36 Fcntl(sockfd, F_SETFL, flags); /* восстанавливаем флаги, задающие статус файла */

37 if (error) {

38 close(sockfd); /* на всякий случай */

39 errno = error;

40 return (-1);

41 }

42 return (0);

43 }

Задание неблокируемого сокета

9-10
Мы вызываем функцию
fcntl
, которая делает сокет неблокируемым.

11-14
Мы вызываем неблокируемую функцию
connect
. Ошибка, которую мы ожидаем (
EINPROGRESS
), указывает на то, что установление соединения началось, но еще не завершилось [128, с. 466]. Любая другая ошибка возвращается вызывающему процессу.

Выполнение других процессов во время установления соединения

15
На этом этапе мы можем делать все, что захотим, ожидая завершения установления соединения.

Проверка немедленного завершения

16-17
Если неблокируемая функция
connect
возвратила нуль, установление соединения завершилось. Как мы сказали, это может произойти, когда сервер находится на том же узле, что и клиент.

Вызов функции select

18-24
Мы вызываем функцию
select
и ждем, когда сокет будет готов либо для чтения, либо для записи. Мы обнуляем
rset
, включаем бит, соответствующий
sockfd
в этом наборе дескрипторов и затем копируем
rset
в
wset
. Это присваивание, возможно, является структурным присваиванием, поскольку обычно наборы дескрипторов представляются как структуры. Далее мы инициализируем структуру
timeval
и затем вызываем функцию
select
. Если вызывающий процесс задает четвертый аргумент нулевым (что соответствует использованию тайм-аута по умолчанию), следует задать в качестве последнего аргумента функции
select
пустой указатель, а не структуру
timeval
с нулевым значением (означающим, что мы не ждем вообще).

  • Читать дальше
  • 1
  • ...
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: