<% ASP на блюдечке %>. Часть 12
Чат своими силами (версия 2)
Создание и подготовка базы данных
Универсальный набор функций (файл utils.asp)
Вход в чат (файл Entrance.asp)
Mодуль добавления новых пользователей в систему (AddUser.asp)
Просмотр списка сообщений чата (файл Text.asp)
Посылка сообщения в чат (файл Chat.asp)
Показ псевдонимов (кто в чате) — файл Nicks.asp
И еще об одной немаловажной проблеме…
Введение
Как мы уже отмечали в предыдущих статьях настоящей серии, тема Интернет-общения актуальна, однако согласитесь, что созданная нами в части 9 настоящей статьи чат-система не лишена недостатков. Наиболее существенным из них является то, что система реализована на базе файловой системы сервера, что, с одной стороны, позволило нам вникнуть в подробности и детально изучить принципы и методы работы с файлами средствами ASP, а с другой — создать достаточно удобный чат-интерфейс, вполне приемлемый для организации общения ограниченного числа пользователей. Однако наверняка читатель заметит проблему, которую таит в себе такой подход, а именно: при возрастании числа пользователей такой системы (транзакционной нагрузки на сервер) обязательно возникнет ситуация, когда файловая система сервера не будет успевать обрабатывать запросы пользовательских страниц, что неизбежно приведет к остановке системы. Именно поэтому в настоящей статье мы продолжим обучение навыкам построения чат-систем и освоим процесс создания базо-основанной, а не файл-основанной чат-системы.
Однако не будем забегать вперед, а попробуем формализовать всю задачу с нуля, с тем чтобы представить себе ее решение максимально детально.
Итак, настоящая статья адресована тем читателям, которые хотели бы самостоятельно разработать с нуля собственную чат-систему.
Что же такое чат?
Настоятельно рекомендую вам задаться этим вопросом, прежде чем продолжать чтение данной статьи.
Как известно, чат — это некая область окна браузера, в которой пользователи могут просматривать текстовые сообщения других пользователей и добавлять свои. Поток сообщений общий, поэтому сообщение, введенное любым пользователем, доступно для всех (хотя существуют чат-системы с возможностью «уединенной» беседы, то есть когда часть сообщений адресована какому-то конкретному пользователю и для остальных пользователей недоступна).
Таким образом, чат представляет собой одномерный поток текстовых сообщений (в отличие от форума, который является двухмерным потоком текстовых сообщений).
Теперь, когда картина нам в общем ясна, предлагаю разобраться с функционалом чат-систем, который, как правило, состоит из следующих функциональных компонентов:
- во-первых, это система идентификации пользователей. Данная система призвана регистрировать имя (псевдоним, nickname), пароль, электронный адрес и т.д. пользователя для обеспечения его уникальности в чат-системе;
- во-вторых, это собственно система представления общего потока текстовых сообщений, позволяющая пользователям просматривать поток текстовых сообщений;
- в-третьих, это система ввода сообщений, формирующая новые сообщения и вставляющая их в общий поток;
- в-четвертых, это система самообновления сообщений с задаваемым определенным интервалом времени.
Этот список можно продолжать, однако, чтобы не усложнять изложение материала, мы не будем этого делать в настоящей статье, а ограничимся лишь наиболее типичными требованиями.
Постановка задачи
С программной точки зрения чат-система должна представлять собой совокупность модулей, каждый из которых предназначен для решения одной из вышеизложенных задач. Таким образом, в состав наиболее типичной чат-системы входят:
- Модуль идентификации пользователей.
- Модуль представления потока сообщений всех пользователей.
- Модуль представления имен (псевдонимов) всех подключенных пользователей.
- Модуль формирования и ввода новых сообщений.
Структура приложения
Однако прежде чем приступать к созданию базо-основанного чата, давайте представим себе, каким же образом будет осуществляться обмен сообщениями — ведь в качестве носителя данных у нас теперь выступают не файлы на жестком диске сервера, а база данных. Да очень просто: все текстовые сообщения, предварительно обрамленные в необходимые HTML-тэги форматирования, будут «складываться» в определенную таблицу базы данных, после чего будет генерироваться страница на основе этой таблицы, которая будет доступна всем пользователям нашего чата. Аналогичные действия необходимо проделать и со страницей псевдонимов, которая, в свою очередь, будет генерироваться на основании таблицы пользователей.
Что нам понадобится
Конечно же, предполагается, что читатель знаком с основами ASP- и SQL-программирования (первых частей настоящей статьи для этого будет вполне достаточно). Кроме того, нам потребуется Microsoft SQL Server 7.0 или 2000, какой-нибудь HTML- или текстовый редактор (рекомендую использовать Macromedia Dreamweaver UltraDev 4.0) и немного терпения.
Создание и подготовка базы данных
Создадим две таблицы: таблицу пользователей (ChatUsers) и таблицу сообщений (Chat). Представим себе их взаимосвязь так, как показано на рисунке.
Ключевыми здесь являются столбцы UserID. Их взаимосвязь, по сути, отражает взаимосвязь сообщений и их авторов. Теперь, когда база данных готова, можно переходить к созданию самого форума.
Однако прежде следует уяснить вопрос, каким именно образом будет отслеживаться состояние пользователей, находящихся в режиме онлайн? Для этого в таблице пользователей необходимо предусмотреть соответствующую галочку (поле). Таким образом, выполняя соответствующий запрос к таблице пользователей, можно будет выяснить, кто из пользователей находится в режиме онлайн.
Универсальный набор функций (файл utils.asp)
Прежде чем приступить непосредственно к разработке нашего чата, вынесем все многократно используемые типовые функции в один файл, который впоследствии по мере необходимости будем «включать» в разрабатываемые странички. Разберемся, что нам для этого понадобится. Прежде всего это функции соединения и закрытия соединения с базой данных:
<% @ LANGUAGE="VBSCRIPT" %> <% Option Explicit %> <!--#include file="cdovbs.inc"--> <% option explicit Response.Buffer = true '***** Строим строку соединения с базой данных *************************** dim Dsn, Conn, Rs, sSQL Dsn = "DSN=Chat; UID=sa;PWD=;database=Chat" '**** Подсоединяемся к базе данных форума ******************************** Sub Connect() set conn = server.createobject("adodb.connection") set rs = server.createobject("adodb.recordset") conn.open Dsn End Sub '**** Закрываем соединение с базой данных форума ************************* Sub Close() Rs.close set Rs = nothing Conn.close set Conn = nothing End Sub %>
Вход в чат (файл Entrance.asp)
Главная страница чата предназначена для выбора пользователем имени-псевдонима и пароля, указания им предпочтительного цвета имени, а также для нескольких настроек: количества одновременно отображаемых сообщений и времени обновления текстовой страницы в секундах.
<!--#include file="utils.asp"--> <SCRIPT LANGUAGE = VBScript RUNAT=Server> <!-- Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" --> </SCRIPT> <% Dim IName, Passwd, Msg, CurUser, Odd, NameNum, db, IsError, TextStr, Str Iname = Request.Form("nickname") Passwd = Request.Form("passwd") If IName = "" Then msg = "Вы не ввели логин пользователя!" IsError = True Else If Passwd = "" Then msg = "Вы не ввели пароль пользователя!" IsError = True End If If InStr(IName,"<") < 1 Then Call Connect sSQL = "SELECT * FROM ChatUsers WHERE UserNickName = '" & Iname & "' AND UserPassword = '" & Passwd & "'" Rs.open sSQL, Conn If rs.Eof Then IsError = True msg = "<font color='red'>Вы ошиблись при вводе имени пользователя и/или пароля.</font>" End If If Not IsError Then IsError = False Session("UserID") = Rs.Fields("UserID").value Session("UserName") = Iname Session("UserColor") = Request("user_color") Session("RefreshTime") = Request("RefreshTime") Session("LNum") = Request("LNum") TextStr = "<table><tr><td><B><font color='" & Session("UserColor") &"'>" & _ Session("UserName") & "</font></B>" &_ " : " & "вошел в чат - " & date & " " & time & "</td></tr></table>" Call Close() Call Connect() sSQL = "SELECT * FROM Chat" RS.Open sSQL, Conn, 3, adLockOptimistic rs.AddNew rs("UserID") = 0 rs("DateSaid") = Now() rs("Said") = TextStr rs.Update Call Close() Call Connect() sSQL = "UPDATE ChatUsers Set IsOnLine = 1, UserColor = '" & Session("UserColor") &_ "' WHERE UserNickName = '" & Iname & "' AND UserPassword = '" & Passwd & "'" Conn.Execute(sSQL) Conn.close set Conn = nothing Response.Redirect("MainFS.asp") End If IsError = false Call Close End If End If %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> </head> <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF"> <BR><BR><BR> <center> <font color="#000000" size=+2>Добро пожаловать в Чат</font> </center> <BR> <center> <p>Сейчас в чате:</p> <table align= "center" width= 400 border = 0> <tr><td align= "center"> <% CurUser = 0 Odd = 0 NameNum = 0 Call Connect sSQL = "SELECT * FROM ChatUsers WHERE IsOnline = 1" Rs.open sSQL, Conn Do While Not rs.EOF If Odd = 0 Then If NameNum = 10 Then Response.Write "</td></tr><tr><td align= 'center'>" NameNum = 0 End If Str = Rs.Fields("UserNickName").value If Str <> "" Then Response.Write "[" & Str & "] " Odd = 1 CurUser = CurUser + 1 NameNum = NameNum + 1 End If Else Odd = 0 Rs.MoveNext End If Loop If CurUser = 0 Then Response.Write "нет пользователей" Else Response.Write "</td></tr><tr><td align= 'center'>Всего " & CurUser End If Call Close %> </td></tr></table> <br> <Form name="Nickname" method="post" action="Entrance.asp"> <table width= 400 border = 1> <tr> <td>Ваш псевдоним:</td> <td><input type=text name="nickname" value="" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td> </tr> <tr> <td>Ваш пароль:</td> <td><input type=password name="passwd" value="" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td> </tr> <tr> <td></td><td><a href = "Newuser.asp">Новый пользователь?</a></td> </tr> <tr> <td valign="top">Ваш цвет:</td> <td> <FONT FACE="arial, verdana, helvetica" SIZE="2"> … Группа переключателей (радиокнопок) для выбора цвета. … </FONT> </td> </tr> <tr> <TD>Обновление чата:</TD> <TD><SELECT NAME="RefreshTime" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"> <OPTION VALUE="5">5 <OPTION VALUE="10"Selected>10 <OPTION VALUE="15">15 <OPTION VALUE="20">20 <OPTION VALUE="30">30 <OPTION VALUE="60">60 </SELECT> секунд </TD> </tr> <tr> <td>Просматриваемых сообщений:</td> <td><INPUT TYPE="text" NAME="LNum" VALUE="30" SIZE="2" MAXLENGTH="2" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td> </tr> </table> <br> <input type=submit name="okbtn" value="Войти" </Form> <BR><H6><%=msg%><br>Использование HTML-тэгов недопустимо!</h6><BR> </center> </body> </html>
Вход в чат впервые
Далее система попытается найти указанного пользователя в таблице пользователей, и если ей это не удастся, то пользователь не будет допущен в чат. Для «вновь прибывших» пользователей следует предусмотреть механизм регистрации в системе, форму регистрации с проверкой введенных значений на допустимые диапазоны и типы, а также модуль добавления новых пользователей в систему:
Форма регистрации для новых пользователей (файл NewUser.asp):
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title>чат (регистрационная форма)</title> <SCRIPT TYPE="text/javascript" SRC="script.js"> <!-- // displays only if script file not found document.write ("JavaScript library not found."); //--> </SCRIPT> <SCRIPT TYPE="text/javascript"> <!-- function checkMe() { var ok; with (document.EOForm){ if ( isBlank(Nick, 'Введите Ваш псевдоним.')) return false; if ( isBlank(Name, 'Введите Ваше имя.')) return false; if ( !PasswordCheck(Password, repPassword)) return false; if ( isBlank(Email,'Введите адрес электронной почты')) return false; if (!isEmail(Email,'Введите адрес электронной почты в правильном формате (например, somebody@domain.ru)')) return false; if (!isIntegerValue(UIN,'Введите правильно Ваш номер ICQ.')) return false; } return true; } //--> </SCRIPT> </head> <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF"> <table align = "center" width="570" border="0" cellspacing="0" cellpadding="0"><tr><td> <div align="center"> <p><b>Пожалуйста, заполните эту форму для получения доступа в чат:</b></p> <Form name = "EOForm" Method="get" Action = "AddUser.asp" onSubmit="return checkMe();"> <table width="470" border="0" cellspacing="3" cellpadding="0"> <tr><td>Ваш псевдоним (nickname) (*):</td> <td><Input Type="text" Name="Nick" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td> </tr> <tr><td>Ваше имя(*):</td> <td><Input Type="text" Name="Name" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td> </tr> <tr><td>Ваш пароль(*):</td> <td><Input Type="password" Name="Password" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td> </tr> <tr><td>Повторите пароль(*):</td> <td><Input Type="password" Name="repPassword" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td> </tr> <tr> <td>Ваш электронный адрес(*):</td> <td><Input Type="text" Name="Email" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></td> </tr> <tr> <td>Ваш URL:</td> <td><Input Type="text" Name="URL" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></Input></td> </tr> <tr> <td>Ваш номер ICQ:</td> <td><Input Type="text" Name="UIN" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></Input></td> </tr> <tr> <td>Другая информация:<BR></td> <td><textarea Type="text" Name="Info" cols="29" rows="5" Size="30" style="font: 8pt 'Verdana'; background-color: #FCFBE8;"></textarea></td> </tr> </table> <br> <Input Type="submit" style="WIDTH: 150px" Value="Подтверждаю"> <input type="reset" style="WIDTH: 150px" value="Очистить" name="Reset"> </form> </div> </td></tr> </table> </body> </html>
Проверка корректности введенных пользователем значений полей формы реализуется путем вызова ряда JavaScript-функций проверки из библиотеки script.js. Однако мы не будем останавливаться на всех этих функциях подробно, так как мы делали это в одной из предыдущих статей настоящей серии.
Mодуль добавления новых пользователей в систему (AddUser.asp)
<!--#include file="utils.asp"--> <SCRIPT LANGUAGE = VBScript RUNAT=Server> <!-- Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" --> </SCRIPT> <% Call Connect() sSQL = "SELECT * FROM ChatUsers" RS.Open sSQL, Conn, 3, adLockOptimistic rs.AddNew rs("UserNickName") = request("Nick") rs("UserName") = request("Name") rs("UserPassword") = request("Password") rs("UserMail") = request("EMail") rs("UserURL") = request("URL") rs("UserUIN") = request("UIN") rs("UserInfo") = request("Info") rs("IsOnLine") = False rs.Update Call Close() Response.Redirect "Entrance.asp" %>