|
Программирование >> Программный интерфейс приложений
Рассмотрим нашу программу clientl. Как можно узнать, было или нет сделано подключение к серверу? Журнал регистрации подключений позволяет судить об этом по событиям подключение и выход , произошедших примерно в это время, когда был сделан запуск программы: 990516 21:52:14 20 Connect paulglocalhost on 20 Quit В противном случае можно увидеть сообщение об отказе соединения: 990516 22:01:47 21 Connect Access denied for user: paulglocalhost (Using password: NO) Такое сообщение свидетельствует о том, что соединение не состоялось. К сожалению, сама программа clientl не информирует, какой из этих двух исходов операции произошел. В любом случае сложилась ненормальная ситуация: чтобы узнать о том, как отработала программа, приходится обращаться к системному журналу! Давайте исправим эту ситуацию. Функции клиентской библиотеки MySQL, возвращающие значения, обычно отображают успешное или неуспешное завершение операции одним из двух способов. ш Функции, получающие в качестве параметра указатель на значение, возвращают ненулевое значение в случае успешного завершения операции и null в случае ошибки. (В этом контексте null означает пустой указатель , а не пустое значение столбца СУБД MySQL.) Все клиентские функции, которыми мы пользовались до сих пор, будь то mysql initO или mysql real connect {) , в случае успешного завершения операции возвращают указатель на дескриптор соединения и null в случае неудачного завершения операции. Функции, получающие в качестве параметра целые числа, возвращают значение О, в случае успешного завершения операции и значение, отличное от нуля в случае ошибки. При этом важно понимать, что в случае ошибки не следует проверять на конкретные ненулевые значения. Такая функция может не возвратить никакого значения в случае неуспешного завершения операции. Ниже приведен код, который неправильно обрабатывает возвращаемое значение: if {mysql XXX() == -1)/* это пример неправильной проверки */ fprintf (stderr, случилось что-то страшноеХп ); Такая проверка может сработать, а может и не сработать. Интерфейс MySQL API не определяет никакого конкретного ненулевого значения, возвращаемого в качестве ошибки за исключением того, что оно должно быть ненулевым. Проверку на ошибочное завершение операции следует переписать следующим образом; if (mysql XXX{)) /* это правильная проверка */ fprintf (stderr, случилось что-то страшное\п ); ИЛИ вот так; if {mysql XXX() != 0) /* это правильная проверка */ fprintf (stderr, случилось что-то страшное\п ); Это две равноценные проверки. И если просмотреть исходные тексты самой MySQL, можно увидеть, что чаще всего используется проверка первого типа, так как она короче. Но далеко не каждый интерфейс возвращает значение. К числу таких можно причислить другую функцию, которая была использована при написании клиентской программы - mysqlclose (). (Как она может не сработать? И если это произошло, что из того? В любом случае соединение обрывается.) Для выяснения причин сбоя можно воспользоваться вызовом двух функций. Это функция inysql error {), возвращающая строку, содержащую сообщение об ошибке, и функция mysqlerrno (), возвращающая цифро-юй код ошибки. Их надо вызывать сразу же после обнаружения ошибки потому, что если это сделать после отработки какой-либо другой функции, она вернет уже какой-то свой статус, и вся информация, которая будет получена функциями mysql error () или mysql errno (), будет относиться к функции, вызванной позже. В общем случае пользователю программ значительно удобнее получать строку, содержащую информацию об ошибке, чем числоюй код. Для целостности картины воспользуемся обеими функциями. Принимая во внимание все вышесказанное, напишем вторую клиентскую программу client2. Эта профамма аналогична clienti, но добавлена соответствующая обработка ошибок. Исходный текст client2.c имеет следующий вид; /* client2.c */ ♦include <stdio.h> ♦include <mysql.h> ♦define def host name NULL /* узел, к которому производится подключение (умолчание = localhost) */ ♦define def user name NULL /* имя пользователя (умолчание = ваше имя регистрации в системе) */ ♦define def password NULL /* пароль (умолчание = отсутствует) */ ♦define def db name NULL /*база данных(умолчание = отсутствует)*/ MYSQL *conn; /* указатель на дескриптор соединения */ main (int argc, char *argv[]) { conn = mysql init (NULL); if (conn == NULL) {fprintf (stderr, mysql init () ошибка (вероятно, не хватает памяти)\n ); exit (1); if (mysql real connect ( conn, /* указатель на дескриптор соединения */ def host name, /* узел, к которому осуществляется подключение*/ def user name, /* имя пользователя */ def password, /* пароль */ def db name, /* используемая база данных */ О, /* порт (используется значение по умолчанию) */ NULL, /* разъем (используется значение по умолчанию) */ 0); /* флаги (отсутствуют) */ == NULL) { fprintf (stderr, ошибка mysql real connect():\nError %u (%s)\n , mysql errno (conn), mysql error (conn)); exit (1); mysql close (conn); exit (0) ; Логика проверки на ошибку заключается в том, что в случае ошибочного завершения функции mysql init () и mysql real connectО возвращают значение null . Обратите внимание, что несмотря на то, что программа анализирует значение, возвращаемое функцией mysqlinit (), в случае его сбоя функция диагностики ошибок не вызывается. Это происходит потому, что в случае сбоя функции mysqlinit () дескриптор соединения не может содержать информации, достойной внимания. Однако при сбое функции mysql real connect {) дескриптор соединения не отражает реального соединения, содержит информацию об ошибке, которую можно передать функции диагностики ошибок. (Но не передавайте дескриптор другим клиентским профаммам! Это недопустимо потому, что они предполагают успешное соединение, что, в свою очередь, может стать причиной сбоя профаммы.) Откомпилируйте и офедактируйте связи client2, а затем запустите профамму: % client2 Если client2 не дает никаких сообщений (как показано выше), соединение было успешным. При возникновении сбоя мы увидим следующее: % client2 mysql real connectо ошибка [вероятно, не хватает памяти): Error 1045 (Access denied for user: paul(?localhost (Using password: NO)) Это свидетельствует о том, что соединение не было установлено и причину, по которой это произошло. Это также означает, что наша первая профамма, clientl, никогда успешно не подключалась к серверу.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |