Гостевая
Форум
Разделы
Главная страница
Js скрипты
Php скрипты
Html шаблоны
Книги по Web дизайну
Статьи


Главная страница статей --> Советы по фотошопу, графике и хитрости в построении php кода

Пишем свой чат

Источник: realcoding.net

Чат


Написание чата ничем особенным не отличается. Та же запись в файлы, чтение из них информации и вывод ее на экран. Однако есть кое-какие тонкости. Сообщения в чат поступают в режиме реального времени, поэтому для поддержания этого режима необходимо периодически обновлять содержимое html-страницы. Это осуществляется с помощью мета-инструкции <meta http-equiv="Refresh" content="10"> .В данном случае будем обновлять страницу с интервалом в 10 секунд, этого вполне достаточно. Итак, приступим непосредственно к чату.

Вход в чат


Сгенерируем форму для входа в чат.

<html><style>
BODY {background-color:#e6e8fa;font-family:arial;font-size:10pt;color:#000080;}
</style>

<body>
<h3 align=center><font color="ff0000">Вход в чат.</font></h3>
<form action="chat.cgi" method="GET">
<table align=center>
<tr><td>Введите ваш ник:<td><input type="text" name="nick" size=20>

<tr><td>Выберите цвет сообщений:<td><select name="color">
<option>black</option>
<option>red</option>
<option>blue</option>

<option>green</option>
<option>darkred</option>
<option>yellow</option>
</select>
<tr><td colspan=2><input type="hidden" name="enter" value="1">

<tr><td colspan=2><input type="hidden" name="action" value="login">
<tr><td colspan=2><input type="submit" value="Enter">
</table></form></html>

Посетитель выбирает себе ник и цвет, под которым будут выводиться его сообщения. Далее,скрипт получает эти данные и обрабатывает их.

#!/usr/local/bin/perl
$request=$ENV{REQUEST_METHOD};
$content=$ENV{CONTENT_LENGTH};

$file="chat.txt";                       <span class="comment"># Файл для записи сообщений</span>

$syslog="log.txt";                      <span class="comment"># Cистемный журнал</span>
$online="online.txt";                   <span class="comment"># Файл для записи онлайновых посетителей.</span>
$dir="f:/usr/local/apache/cgi-bin";
$path="f:/usr/local/apache/cgi-bin/images/";
<span class="comment"># Путь к папке с картинками (смайликами)</span>

<span class="comment"># Назначаем переменные для смайликов.</span>
@images=("smile.gif","frown.gif","redface.gif","biggrin.gif","wink.gif",
"tongue.gif","cool.gif","rolleyes.gif",
"mad.gif","eek.gif","confused.gif");

$img0=$images[0];
$src0="$path$img0";
$img1=$images[1];
$src1="$path$img1";
$img2=$images[2];
$src2="$path$img2";
$img3=$images[3];
$src3="$path$img3";
$img4=$images[4];
$src4="$path$img4";
$img5=$images[5];
$src5="$path$img5";
$img6=$images[6];
$src6="$path$img6";
$img7=$images[7];
$src7="$path$img7";
$img8=$images[8];
$src8="$path$img8";
$img9=$images[9];
$src9="$path$img9";
$img10=$images[10];
$src10="$path$img10";

if ($request eq GET) {
$query=$ENV{QUERY_STRING};
} else {
sysread(STDIN,$query,$content);
}

<span class="comment"># Функция для декодирования полей форм.</span>
@pairs = split(/&/, $query);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$name =~ s/<!--(.n)*-->//g;
$name =~ s/<([^>]n)*>//g;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s/<!--(.n)*-->//g;
$value =~ s/</</g;
$value =~ s/>/>/g;
$value =~ s/n//g;
$value =~ s/cM/ /g;
$value =~ s// /g;
$value =~ tr/ / /s;
$value =~ s/<([^>]n)*>//g;
$value =~ s/"/"/g;
$value=~s/:)/<img src=$src0>/g;
$value=~s/:(/<img src=$src1>/g;
$value=~s/:o/<img src=$src2>/g;
$value=~s/:D/<img src=$src3>/g;
$value=~s/;)/<img src=$src4>/g;
$value=~s/:p/<img src=$src5>/g;
$value=~s/:cool:/<img src=$src6>/g;
$value=~s/:rolleyes:/<img src=$src7>/g;
$value=~s/:mad:/<img src=$src8>/g;
$value=~s/:eek:/<img src=$src9>/g;
$value=~s/:confused:/<img src=$src10>/g;
$input{$name} = $value;
}


<span class="comment">#####################Вход в чат#########################
</span>
($action eq "login") && do {

<span class="comment"># Получаем переменные</span>

$enter=$input {enter};
$color=$input {color};
$nick=$input {nick};
$time=scalar localtime;

if ($enter eq "1") {

<span class="comment"># Проверяем,ввел ли посетитель ник и если да то записываем в системный
# журнал имя и время входа.</span>

if ($nick ne "") {
open (LOG,">>$syslog");
$string="Системное сообщение:$nick вошел в чат $time";
print LOG "$stringn";
close (LOG);

<span class="comment"># Добавляем имя посетителя также в файл для показа онлайна.</span>
open (NET,">>$online");
print NET "$nickn";
close (NET);


<span class="comment"># Установим количество записей в журнале.Я выбрал их равным 10.</span>

open (LOG,"$syslog");
@strings=<LOG>;
$count=@strings;
close (LOG);

<span class="comment"># Если их количество больше 10,удаляем
самую первую запись и перезаписываем журнал.
</span>
if ($count>10) {
shift (@strings);
}

open (LOG,">$syslog");
print LOG @strings;
close (LOG);

<span class="comment"># Теперь посетитель находится в чате и может добавлять сообщения.
# Генерируем форму.</span>

print "Content-type:text/htmlnn";
print <<HTML;
<html><style>

BODY {background-color:#e6e8fa;font-family:arial;font-size:10pt;color:#000080;}
</style>
<body>
<center><h3>Здравствуйте,<font color="$color">$nick!</font></h3>
Вы успешно вошли в чат.
<br>Вы можете добавлять ваши сообщения.Ваш цвет-<font
color="$color">$color</font>.</center>

<form action="chat.cgi" method="GET">
<input type="hidden" name="action" value="add">
<input type="hidden" name="nick" value="$nick">
<input type="hidden" name="color" value="$color">
<input type="hidden" name="send" value="1">
<table align=center>
<tr><td><textarea name="message" wrap="virtual" rows=5 cols=40></textarea>

<td><input type="submit" value="Отправить"></form><p>
<form action="chat.cgi" method="GET">
<input type="hidden" name="action" value="add">
<input type="hidden" name="nick" value="$nick">
<input type="submit" value="<<Выход>>">
</form>

</table>
HTML
}

<span class="comment"># Если посетитель не ввел ник,выдается ошибка.</span>
else {
print "Content-type:text/htmlnn";
print <<HTML;
<html><style>
BODY {background-color:#e6e8fa;font-family:arial;font-size:10pt;color:#000080;}
</style>
<body>
<h3 align=center>Вы не ввели ник!</h3>

Пожалуйста,вернитесь и введите ник.
<p><center><a href="chat.cgi?action=login">Назад</a></center>
HTML
}
}

Как видите, форма имеет 2 кнопки, предусмотрена кнопка выхода из чата, а также кнопка для отправки сообщения в чат. Это будет рассмотрено далее.

Добавление сообщения в чат


После того, как посетитель ввел сообщение и нажал кнопку Отправить, сообщение записывается в файл. Ник посетителя и цвет сообщений передаются в скрытых полях формы.

<span class="comment">#########################Добавление сообщения#########################
</span>
($action eq "add") && do {
$time=time;                   <span class="comment"># Получаем текущее время в секундах.</span>
$time1=scalar localtime;      <span class="comment"># Время в нормальном формате.</span>
$nick=$input {nick};
$color=$input {color};
$send=$input {send};
$exit=$input {exit};
$message=$input {message};

<span class="comment"># Если посетитель нажал кнопку "Отправить".</span>
if ($send eq "1") {

<span class="comment"># Проверяем,чтобы поле сообщения не было пустым.</span>

if ($message ne "") {

<span class="comment"># Если все ОК открываем файл на добавление и записываем данные.</span>
open (FILE,">>$file");
$string=join (&,$nick,$time,$color,$message);
print FILE "$stringn";
close (FILE);

<span class="comment"># Читаем файл в массив и подсчитываем количество сообщений.</span>
open (FILE,"$file");
@lines=<FILE>;
$count=@lines;
close (FILE);

<span class="comment"># Устанавливаем количество сохраняемых сообщений равным 20.
# Если этот лимит превышен,первое сообщение удаляется и т.д.</span>
if ($count>20) {
shift (@lines);
}

<span class="comment"># Перезаписываем измененный файл.</span>

open (FILE,">$file");
print FILE @lines;
close (FILE);

<span class="comment"># Сообщение записано и через 10 секунд появится на экране.
# Снова выводим форму для отправки сообщения.</span>

print "Content-type:text/htmlnn";
print <<HTML;
<html><style>
BODY {background-color:#e6e8fa;font-family:arial;font-size:10pt;color:#000080;}
</style>
<body>
<center><h3>Новое сообщение.lt;/h3>

Вы уже в чате.Добавьте новое сообщение.
<вr>Ващ ник-<font color="$color">$nick</font>,цвет-<font color="$color">
$color</font>.</center>
<form action="chat.cgi" method="GET">
<input type="hidden" name="action" value="add">

<input type="hidden" name="nick" value="$nick">
<input type="hidden" name="color" value="$color">
<input type="hidden" name="send" value="1">
<table align=center>
<tr><td><textarea name="message" wrap="virtual" rows=5 cols=40></textarea>
<td><input type="submit" value="Отправить"></form><p>

<form action="chat.cgi" method="GET">
<input type="hidden" name="action" value="add">
<input type="hidden" name="nick" value="$nick">
<input type="submit" value="<<Выход>>">
</form>
</table>
HTML
}

<span class="comment"># Если посетитель не ввел сообщение.</span>

else {
print "Content-type:text/htmlnn";
print <<HTML;
<html><style>
BODY {background-color:#e6e8fa;font-family:arial;font-size:10pt;color:#000080;}
</style>
<body>
<center><h3>Ошибка!</h3>
Поле сообщения не должно быть пустым.

<br>Ваш ник-<font color="$color">$nick</font>,цвет-<font
color="$color">$color</font>.
<form action="chat.cgi" method="GET">
<input type="hidden" name="action" value="add">
<input type="hidden" name="nick" value="$nick">
<input type="hidden" name="color" value="$color">

<input type="hidden" name="send" value="1">
<table align=center>
<tr><td><textarea name="message" wrap="virtual" rows=5 cols=40></textarea>
<td><input type="submit" value="Отправить"></form><p>
<form action="chat.cgi" method="GET">
<input type="hidden" name="action" value="add">

<input type="hidden" name="nick" value="$nick">
<input type="submit" value="<<Выход>>">
</form>
</table>
HTML
}

Выход из чата


Если посетитель нажал кнопку Выход.

<span class="comment">#######################Выход из чата#########################
</span>

} else {

<span class="comment"># Записываем сообщение в системный журнал.</span>
open (LOG,">>$syslog");
$string="Системное сообщение:$nick вышел из чата $time1";
print LOG "$stringn";
close (LOG);

<span class="comment"># Снова удаляем лишние сообщения.</span>
open (LOG,"$syslog");
@strings=<LOG>;
$count=@strings;
close (LOG);
if ($count>10) {
shift (@strings);
}

<span class="comment"># Перезаписываем файл.</span>
open (LOG,">$syslog");
print LOG @strings;
close (LOG);

<span class="comment"># Говорим посетителю до свидания :)</span>

print "Content-type:text/htmlnn";
print <<HTML;
<html><style>
BODY {background-color:#e6e8fa;font-family:arial;font-size:10pt;color:#000080;}
</style>
<body>
<h3 align=center>Спасибо за посещение нашего чата,
<font color="0000ff">$nick</font>!</h3>

Заходите еще!
<p><center><a href="chat.cgi?action=login">Войти в чат</a></center>
HTML

<span class="comment"># Удаляем посетителя из онлайна.Для этого обновляем файл online.txt</span>
open (NET,"$online");
@users=<NET>;          <span class="comment"># Читаем содержимое</span>
foreach $user (@users) {
if ($user !~ /$nick/) {   <span class="comment"># Сравниваем ник посетителя,выщедшего из чата с каждым
# ником в файле и если они не равны помещаем их в массив.</span>

push (@online,$user);
}
}
close (NET);

<span class="comment"># Перезаписываем файл уже без ушедшего посетителя.</span>
open (NET,">$online");
print NET @online;
close (NET);
}

<span class="comment">#Таким образом поддерживается самая свежая информация
о посетителях, или я не прав? :)))
</span>

Показ посетителей,в данный момент находящихся в чате


<span class="comment">###################### ##Кто в онлайне#########################
</span>
($action eq "online") && do {

<span class="comment"># Эта страница также будет обновляться каждые 10 секунд.</span>
print "Content-type:text/htmlnn";
print <<HTML;

<html><meta http-equiv="Refresh" content="10">
<style>
BODY {background-color:lightsteelblue;font-family:arial;font-size:10pt;}
</style>
<body>

<span class="comment"># Выводим на экран табличку со смайликами.</span>
<p><h5 align=center><font color="000080">Смайлики</font></h5>

<p><table align=center width=100>
<tr><td><img src="$path$img0"><td><font color="000000">:)</font>
<tr><td><img src="$path$img1"><td><font color="000000">:(</font>

<tr><td><img src="$path$img2"><td><font color="000000">:o</font>
<tr><td><img src="$path$img3"><td><font color="000000">:D</font>
<tr><td><img src="$path$img4"><td><font color="000000">;)</font>

<tr><td><img src="$path$img5"><td><font color="000000">:p</font>
<tr><td><img src="$path$img6"><td><font color="000000">:cool:</font>
<tr><td><img src="$path$img7"><td><font color="000000">:rolleyes:</font>

<tr><td><img src="$path$img8"><td><font color="000000">:mad:</font>
<tr><td><img src="$path$img9"><td><font color="000000">:eek:</font>
<tr><td><img src="$path$img10"><td><font color="000000">:confused:</font>

</table>

<span class="comment"># Отображаем список посетителей.</span>
<h5 align=center><font color="000080">Кто в онлайне.</font></h5>
HTML

<span class="comment"># Здесь я предусмотрел очистку файла
online.txt через 3 минуты после бездействия чата.
# Ни к чему хранить давние сообщения. Системный журнал и файл
с сообщениями также очищаются
# после 3 минут бездействия, как вы увидите дальше.</span>

<span class="comment"># Сравниваем время модификации файла с текущим временем.</span>

$cur_time=time;
$stat3=(stat ("$online"))[9];
$diff3=$cur_time-$stat3;        <span class="comment"># Вычисляем разность</span>

<span class="comment"># Если разность более 180 секунд, перезаписываем файл пустым значением.</span>
if ($diff3>180) {
open (NET,">$online");
print NET "";
close (NET);
}

<span class="comment"># Дальше выводим собственно список.</span>
open (NET,"$online");
@lines=<NET>;
$count=@lines;
if ($count!=0) {
print "<table bgcolor="e6e8fa" align=center width=80 cellspacing=0
border=1 bordercolor="000000"><tr><td>n";
foreach $line (@lines) {
print "<font face="serif" size=2 color="0000ff">",$line,"</font><br>";
}
}
close (NET);
print <<HTML;

</table>
<p>

<center><a href="chat.cgi?action=login" target="second">Войти в чат</a></center>
HTML

Вывод системного журнала


В системный журнал пишутся сообщения о входе в чат и выходе из него. Он постоянно динамически обновляется. Для вывода его на экран читаем файл syslog.txt

<span class="comment">##############Вывод системного журнала###############</span>

($action eq "log") && do {

<span class="comment"># Здесь,в принципе все просто. Открываем файл, читаем и выводим на экран.</span>

print "Content-type:text/htmlnn";
print <<HTML;
<html><meta http-equiv="Refresh" content="10">
<body bgcolor="0000ff" text="ffffff">
HTML

<span class="comment"># Снова проверяем время модификации файла, и если оно больше 180 секунд очищаем его.</span>
$cur_time=time;
$stat2=(stat ("$syslog"))[9];
$diff2=$cur_time-$stat2;

if ($diff2>180) {
open (LOG,">$syslog");
print LOG "";
close (LOG);
}


<span class="comment"># Выводим сообщения на экран,начиная с последнего.</span>

open (LOG,"$syslog");
@lines=<LOG>;
@strings=reverse @lines;
foreach $string (@strings) {
print $string,"<br>";
}
close (LOG);
};

Вывод сообщений


Здесь тоже ничего особенного.Просто выводим сообщения на экран,каждые 10 секунд обновляя его.

<span class="comment">###################Чтение сообщений########################
</span>
($action eq "read") && do {
print "Content-type:text/htmlnn";
print <<HTML;

<html><meta http-equiv="Refresh" content="10">
<style>
BODY {background-color:#e6e8fa;font-family:arial;font-size:10pt;}
</style>
<body>
HTML

<span class="comment"># Файл с сообщениями также очищается после 180 секунд бездействия.</span>
$cur_time=time;
$stat1=(stat ("$file"))[9];
$diff1=$cur_time-$stat1;

if ($diff1>180) {
open (FILE,">$file");
print FILE "";
close (FILE);
}

<span class="comment"># Читаем сообщения и выводим на экран, начиная с последнего.</span>

open (FILE,"$file");
@lines=<FILE>;
@items=reverse (@lines);
foreach $item (@items) {
@string=split (/&/,$item);
$time=localtime ($string[1]);
print <<HTML;
<font color="$string[2]">$string[0]</font> $time <br>
<font color="$string[2]">$string[3]</font>
<center><hr width=80% noshade size=1></center>

HTML
}
close (FILE);

Главная страница


Вот мы и добрались до главной страницы, на которой, собственно, и происходит все это. Она представляет собой набор фреймов, в каждом из которых производятся совершенно независимые действия.

<span class="comment">########################Главная страница#########################
</span>
if ($query eq "") {
print "Content-type:text/htmlnn";
print <<HTML;
<html><head></head>
<style>
A:link {text-decoration:none;font-family:arial;font-size:10pt;color:#000080; }
A:hover {text-decoration:none;font-family:arial;font-size:10pt;color:#ff0000; }
A:visited {text-decoration:none;font-family:arial;font-size:10pt;color:#000080; }
</style>

<frameset cols=20%,*>
<frame name="left" src="chat.cgi?action=online">
<frameset rows=50%,10%,*>
<frame name="first" src="chat.cgi?action=read">
<frame name="2" src="chat.cgi?action=log">
<frame name="second" src="chat.cgi?action=login">
</frameset>
</frameset>
HTML
}



Похожие статьи:
- Свой счётчик
- Работа с FTP средствами PHP
- Net-SMTP
- Секреты кэширования
- Гостевая книга на Perl
- Счетчик нажатий на ссылку на Perl
- Поиск в Google из Python
- Интерполяция строк
- Брандмауэры
- Раскрутка сайта - с чего начать?
- О правильном и полезном линкообмене
- Обмен ссылками: миф или реальность?
- Уроки ASP-технологий


Оглавление | Обсудить на форуме | Главная страница сайта | Карта сайта |
[0.001]