Эффективное программирование TCP-IP




Использование select - часть 3


В UNIX, если соединение установлено, сокет доступен для записи. Если же произошла ошибка, то сокет будет доступен одновременно для записи и для чте­ния. Однако на это нельзя полагаться при проверке успешности соединения, по­скольку можно возвратиться из connect и получить первые данные еще до обращения к select. В таком случае сокет будет доступен и для чтения, и для записи -в точности, как при возникновении ошибки.

Листинг 3.26. UNIX-версия функции isconnected

1    int isconnected( SOCKET s, fd_set *rd, fd_set *wr, fd_set *ex )

2    {

3    int err;

4    int len = sizeoff err );

5    errno =0; /* Предполагаем, что ошибки нет. */

6    if ( !FD_ISSET( s, rd ) && !FD_ISSET( s, wr ) )

7      return 0;

8    if (getsockopt( s, SOL_SOCKET, SO_ERROR, &err, &len ) < 0)

9      return 0;

10   errno = err; /* Если мы не соединились. */

11   return err == 0;

12   }

5-7 Если сокет не доступен ни для чтения, ни для записи, значит, соединение не установлено, и возвращается нуль. Значение errno заранее установлено в нуль, чтобы вызывающая программа могла определить, что сокет действительно, не готов (разбираемый случай) или имеет Metro ошибка.

8-11 Вызываем getsockopt для получения статуса сокета. В некоторых версиях UNIX getsockopt возвращает в случае ошибки -1. В таком случае записываем в errno код ошибки. В других версиях система просто возвращает статус, оставляя его проверку пользователю. Идея кода, который корректно работает в обоих случаях, позаимствована из книги [Stevens 1998].

Согласно спецификации Winsock, ошибки, которые возвращает connect через неблокирующий сокет, индицируются путем возбуждения события исключения в select. Следует заметить, что в UNIX событие исключения всегда свидетельствует о поступлении срочных данных. Версия функции isconnected для;Windows показана в листинге 3.27.

Листинг 3.27. Windows-версия функции isconnected

1    int isconnected( SOCKET s, fd_set *rd, fd_set *wr, fd_set *ex)

2    {

3    WSASetLastError ( 0 );

4    if ( !FD_ISSET( s, rd ) && !FD_ISSET(s, wr ) )

5      return 0;

6    if ( FD_ISSET( s, ex ) )

7      return 0;

8    return 1;

9    }

3-5 Так же, как и в версии для UNIX, проверяем, соединен ли сокет. Если нет, устанавливаем последнюю ошибку в нуль и возвращаем нуль.

6-8 Если для сокета есть событие исключения, возвращается нуль, в про­тивном случае - единица.




Содержание  Назад  Вперед