Средства библиотеки MFC для работы с сокетами.
MFC поддерживает WinSock через два класса: CAsyncSocket и CSocket. CAsyncSocket - это класс, который инкапсулирует возможности работы с WinSock API. CSocket - это более высокоуровневый класс, который происходит от CAsyncSocket. И естественно обеспечивает работу более высокого уровня.
Как и для многих других объектов MFC, создание сокета состоит из двух этапов: создание объекта класса путем вызова его конструктора и создание системного сокета путем вызова функции Create.
Конструктор класса CAsyncSocket не принимает никаких параметров, поскольку просто создает новый пустой объект. Вся работа по фактической инициализации сокета выполняется функцией Create.
Функция Create принимает ряд параметров, как показано в ее прототипе: BOOL Create( UNIT nSocketPort = О, int nSocketType = SOCK_STREAM, long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT |FD_CONNECT | FD_CLOSE, LPCTSTR IpszSocketAddress = NULL ) ;
Первый параметр определяет номер порта, ассоциируемого с сокетом. По умолчанию он равен 0, т.е. система сама должна выбирать порт по своему усмотрению. Во многих случаях, особенно в приложениях типа "сервер", бывает необходимо ассоциировать с сокетом номер порта, заранее известный при разработке приложения. Приложения-клиенты используют этот порт для обмена данными с сервером.
Параметр nSocketType указывает тип сокета — сокет потока (SOCKSTREAM) или сокет дейтаграмм (SOCK_DGRAM).
Параметр lEvent определяет события, в случае которых приложение получает извещение от системы. По умолчанию генерируются сообщения для всех предусмотренных событий.
В последнем параметре указывается сетевой адрес для привязки сокета. По умолчанию он равен 0, что означает привязку сокета к адресу локального компьютера, однако можно указать и другой адрес. Для IP-реализации интерфейса WinSock это будет строка, содержащая нужный IP-адрес — например, 192.9.200.93.
Кроме того, класс CAsyncSocket автоматически выполняет распознавание машинных имен, так что можно указывать адреса наподобие ftp.racotek.com.
Для получения адреса, ассоциированного с сокетом, используется метод GetSockName класса CAsyncSocket.
Большинство методов класса CAsyncSocket возвращает true, если вызов выполнен успешно, и falsе если произошла ошибка. В последнем случае код ошибки можно получить вызовом функции CAsync Socket::GetLastError.
Отправка и прием дейтаграмм. Для сокета (объекта класса CAsyncSockets) типа SOCK_DGRAM в классе имеются специальные методы. Они могут использоваться для посылки дейтаграмм по указанному адресу без лишних операций по открытию отдельного соединения или получения дейтаграммы и адреса ее отправителя из других приложений.
Сокеты потоков в приложениях-клиентах подсоединяются к серверу путем вызова метода Connect, который может принимать два набора параметров. Первая версия метода Connect принимает в качестве параметров машинный адрес в виде ASCII-строки, например 192.9.200.93 или ftp.racotek.com, а также номер порта. Во вторую версию передается структура SOCKADDR, хранящую информацию об адрее. Функция Connect возвращает значение TRUE, если подключение прошло успешно, и FALSE, если произошла ошибка. В этом случае для получения кода ошибки вызывается функция GetLastError. По умолчанию для извещения о событиях в классе CAsyncSocket используются обратные дозвоны. В этом случае, если функция Connect не полностью выполняет подключение, она возвращает значение FALSE и при последующем вызове функции GetLastError возвращается значение WSAEWOULDBLOCK.
По завершении работы Connect независимо от того, был ли вызов успешным или нет, вызывается обработчик сообщений — функция OnConnect. Функция OnConnect может перекрываться в классах, производных от CAsyncSocket. Вот ее прототип:
virtual void OnConnect( int nErrorCode };
Если параметр nErrorCode равен 0, соединение открыто успешно и сокет готов к приему и посылке данных. Если при попытке подключения произошла ошибка, параметр nErrorCode будет содержать код этой ошибки.
После создания сокета потока на сервере путем вызова конструктора класса и метода Create сокет может приступить к ожиданию запросов на подключение. Это выполняется вызовом метода Listen класса CAsyncSocket. Он принимает в качестве параметра количество запросов на подключение, которое должно скопиться во входной очереди для удовлетворения запроса или возвращения клиентам кода WSAECONNREFUSED, обозначающего отказ в подсоединении к серверу. По умолчанию это значение равно 5,
Для удовлетворения запроса и подключения клиента используется метод Accept. Вот прототип этого метода:
virtual. BOOL Accept( CAsyncSocketSi rConnectedSocket, SOCKADDR* IpSockAddr = NULL, int* IpSockAddrLen = NULL ) ;
Первый параметр — адрес сокета, управляющего новым соединением. Это должна быть ссылка на сокет, предварительно созданный путем вызова конструктора класса CAsyncSocket, но без вызова метода Create. Кроме того, в метод передается указатель на структуру SOCKADDR и ее длину; эта структура заполняется адресом сокета клиента.
Функция Accept обычно вызывается из метода OnAccept, который может перекрываться в классах, производных от CAsyncSocket. Метод OnAccept вызывается всякий раз, когда во входной очереди сокета CAsyncSocket появляется запрос на подключение к серверу.
Таким образом, методу Accept нет нужды ожидать запросы в блокирующем режиме. В функцию OnAccept передается один параметр — код ошибки. Если это 0, все идет нормально и вызов Accept должен пройти успешно.
Посылка данных через сокет потока выполняется методом Send класса CAsyncSocket. Как и его аналог в интерфейсе WinSock С API, функция Send принимает указатель на буфер и длину буфера данных. Можно также передать в нее параметр flags со значением MSG_DOUNTROUTE для пересылки данных без маршрутизации или со значением MSG_OOB для пересылки привилегированных данных.
Если извещающая функция OnSend реализована в производном классе, она вызывается после освобождения буфера, при готовности сокета к следующей операции по пересылке данных.
Однако такое извещение обычно применяется только в приложениях с большим объемом обмена данными, а стандартная реализация этой функции в классе CAsyncSocket не делает ничего. Напротив, функция OnReceive довольно часто переопределяется в классах, производных от CAsyncSocket. Она вызывается при поступлении данных на сокет; данные будут находиться в его буфере, пока приложение не прочитает их путем вызова метода Receive класса CAsyncSocket.
Метод CAsyncSocket:: Receive принимает указатель на буфер и его длину, а также необязательный параметр flags, который может иметь значение MSG_PEEK для чтения данных без удаления их из буфера (чтобы их можно было прочитать следующими вызовами Receive) или MSG_OOB для чтения привилегированных данных. Функция Receive считывает такой объем данных, какой доступен во входной очереди сокета, но не больше, чем указано в переданном параметре длины буфера. Если соединение закрывается корректно, метод Receive возвращает 0, иначе SOCKET_ERROR; функция GetLastError в этом случае возвращает значение WSACONNRESET.
Код SOCKET_ERROR возвращается также при возникновении любой другой ошибки, код которой можно получить вызовом функции WSAGetLastError .
После завершения работы с сокетом (объектом класса CAsyncSocket) его необходимо закрыть методом Close для освобождения системных ресурсов, ассоциированных с сокетом. Метод Close автоматически вызывается из деструктора класса CAsyncSocket при явном удалении объекта или выходе его за допустимый диапазон.
Поведение функции Close определяется параметрами сокета SO_LINGER и SO_DONTLINGER. С помощью метода Disable для данного сокета класса CAsyncSocket можно заблокировать (запретить) посылку или прием данных, либо обе эти операции. Обычно это делается, только если сокет скоро должен закрыться, чтобы его нельзя было использовать повторно. Для явного освобождения системных ресурсов в этом случае также необходимо вызывать метод Close.
Источники:
http://helpsite.narod.ru/vc/mfc/268.htm
2.15. Организация работы с сокетами средствами языка C++.
Програмирование сокетов идет поэтапно:
1.Создание сокета
2.Привязка сокета к локальным именам
3.Установка связи
4.Передача данных
5.Закрытие сокета
Для работы с сокетами средствами языка C++ можно создать объект класса CAsyncSocket и использовать его члены. См. предыдущий билет.
Дата добавления: 2014-12-24; просмотров: 1268;