Socket.io или сообщения между пользователями сайта?

Наверное многие задавались вопросом — как реализовать мгновенные сообщения на сайте. Так вот, сейчас все объясню.
Делается буквально за часа два.

Первое что нам нужно сделать это установить сервер node.js. Не знаете как поставить? Не беда. Клик
Установка Node.js на Mac OSX
Mac OS X Snow Leopard

— Устанавливаем Xcode
— Устанавливаем Git
— Открываем терминал и вводим следующие команды:

git clone git://github.com/ry/node.git
cd node
./configure
make
sudo make install


Все готово. Вы можете проверить это, запустив свой первый Hello, world (см. ниже).

Но со львом дела обстоят иначе, и у меня как раз лев :)
Итак, я читал форумы, читал статьи различные на эту тему, пробовал различные решения, но в итоге я все сделал по-своему.

Mac OS X Lion

— Устанавливаем XCode (нам нужен GCC-компилятор для обработки node.js и прочих пакетов)
— Устанавливаем Homebrew (через терминал):
ruby -e "$(curl -fsSLk https://gist.github.com/raw/323731/install_homebrew.rb)"

— Идем на сайт разработчиков эпл и качаем Command Line Tools для XCode
— После установки открываем опять терминал и пишем:
brew install node


Еще нам понадобятся сами плагины
— socket.io Скачать с оф. сайта
— плагин для соединения с БД (MySQL) Скачать с GitHab
— Ну и чтобы все это установить npm (В интернете полно информации, писать не стоит)
— Еще jQuery…

А также таблица сообщений в БД
CREATE TABLE `messages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_send` int(11) NOT NULL,
  `user_get` int(11) NOT NULL,
  `text` text COLLATE utf8_unicode_ci NOT NULL,
  `date` int(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=0 ;


Также еще водички, сам скрипт будет находится в одном файле, например messages.js.
То чтобы его запустить надо в консоли ввести:
 node *messages.js 

*Путь до файла относительно корня системы.

Дальше… socket.io работает очень просто. Если нам нужно, например отправить какое-то сообщение, то мы вызываем функцию, которая будет написана в messages.js (отправка сообщений происходит, конечно, на самом сайте)

Поехали!
Первое, что мы сделаем, будет messages.js
// Включаем сервер
var http = require('http');

// Включаем mysql
var mysql      = require('mysql');

// Подключаемся к mysql
var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : 'root',
  database : 'mb',
});

// Прописываем порт для сервера
var io = require('socket.io').listen(8080); 
// Отключаем вывод полного лога - пригодится в production'е
io.set('log level', 1);

// Функия, если все ок и мы прдключились
io.sockets.on('connection', function (socket) {
	
	// Символы => html
	function escapeHtml(str) {
	  return String(str)
		  .replace(/&/g, "&")
		  .replace(/</g, "<")
		  .replace(/>/g, ">")
		  .replace(/"/g, """)
		  .replace(/'/g, "'")
		   .replace(/\//g, "⁄");
	}
	
	// Что делать, если пользователь подключился, узнаем он или нет и т.д
	socket.on('connect_user', function(username,password, idUserGet){
		var sql    = 'SELECT * FROM users WHERE username = ' + connection.escape(username) + ' AND pass = ' + connection.escape(password);
		connection.query(sql, function(err, rows) {
  			if(rows.length > 0) {
				// Кто отправил, кому отправил
				socket.userGet = idUserGet;
				socket.userSend = rows[0].id;
				
				// Лог, чисто для себя, чтобы примерно понимать что происходить
				console.log(socket.userSend+' has been logined ');
				socket.join(socket.userSend);
				
				// Мое имя.
				socket.user = rows[0].username;
			} 
		});
	});
	
	// Функция отправки сообщений
	// msg - текст сообщения
	socket.on( 'msg', function(msg) {
		// htmlencode
		msg = escapeHtml(msg); 

		// Unixtime
		milliseconds = parseInt(new Date().getTime()/1000);
		var post  = {user_send: socket.userSend, user_get: socket.userGet, text: msg, date: milliseconds};
		query = connection.query('INSERT INTO messages SET ?', post, function(err, result) {
			update = connection.query(sql);
		});
		
		console.log(' usersend id:  ' +socket.userSend +'  user get:  ' + socket.userGet);
		 socket.broadcast.to(socket.userGet).json.emit('incMsg',{'userSend': socket.userSend, 'name': socket.user, 'text': msg, 'time': time })
    });
});


Теперь нам осталось сделать messages.php
Допустим id пользователя будет передаваться в $_GET, вообщем делайте как хотите, главное нам нужно получить ID того, кому будем писать

(таблица users в mysql и все такое)

js код
// Шаблон
function tpl(t) {
	html = ' <div class="msg>';
	html += '    <div class="img"><img src="'+t.img+'" /></div>';
	html += '    <div class="info">';
	html += '         <div class="name"><a href="#">' + t.name + '</a></div>';
	html += '        <div class="text">'+t.text+'</div>';
	html += '    /div>';
	html += '</div>';
	
	return html;
}

$(window).load(function() {
	var milliseconds = parseInt(new Date().getTime()/1000);
    // Создаем соединение с сервером; websockets почему-то в Хроме не работают, используем xhr
    if (navigator.userAgent.toLowerCase().indexOf('chrome') != -1) {
        socket = io.connect('http://localhost:8080', {'transports': ['xhr-polling']});
    } else {
        socket = io.connect('http://localhost:8080');
    }
	
    socket.on('connect', function () {
		var id = '<?=$MY_FRIEND_ID;?>'; // ID друга
		
		img = $("#userGet img").attr('src');
		$("#userGet img").attr('src',img);
		
		$("#messages").scrollTop($("#messages")[0].scrollHeight+9999999);
		socket.id = id;
		socket.emit('adduser', '<?=$MY_LOGIN;?>','<?=$MY_PASS;?>',id);
		
			
		// Получаем сообщения
        socket.on('incMsg', function (msg) {
			// Проверка на принятия сообщения именно от того пользователя, с которым мы разговариваем в данный момент
			if(msg.userSend == id) {
				msg.text = msg.text.replace(/(\n(\r)?)/g, ' <br/>'); // Обрабатываем теккст
				
				// Получаем аватарку
				// Получаем сообщения
				if(msg.userSend == '<?=$MY_LOGIN;?>') msg.img = '/img/users/<?=$MY_AVATAR;?>'; else msg.img = '/img/users/<?=$MY_FRIEND_AVATAR;?>';
				// Шаблончик
				html = tpl(msg);
			
				// Добавляем сообщение
				$('#messages').append(html);
				$("#messages").scrollTop($("#messages")[0].scrollHeight+9999999);
			}
        });
		
        // При нажатии <Enter>
       $('#input').keydown(function(event) {
			event = event || window.event;
            if(event.keyCode == 13 && !(event.shiftKey) ) {
                // Отправляем содержимое input'а, закодированное в escape-последовательность
				input = $(this).val();
				
				// дата
				var newDate = new Date();
				if(newDate.getMinutes() < 10) getMinute = '0'+newDate.getMinutes(); else getMinute = newDate.getMinutes();
				dateString = newDate.getHours() + ":";
				dateString += getMinute + ":";
				dateString += newDate.getSeconds();
				
				// Шаблон
				var msg = {
				  name:  '<?=$MY_LOGIN;?>', // Выводим логин пользователя
				  text: input.replace(/(\n(\r)?)/g, ' <br/>'), // Текст сообщения
				  time: dateString,
				  img: '/img/users/<?=$MY_AVATAr;?>' // Выводим аватар пользователя
				};
				
				// Загружаем "шаблончик" нашего сообщения
				html = tpl(msg);
				// Добавляем его
				$('#messages').append(html);
				$("#messages").scrollTop($("#messages")[0].scrollHeight+9999999);
				
				// Отправляем
                socket.emit( 'msg', input);
                $(this).val('');
				
				event.preventDefault();
            }
        });
		
    });
});


HTML код (Вставляем ниже js)
<div id="messages" ></div>  
<textarea id="input" name="textarea" placeholder="Введите сообщение.." rows="3" cols="54"></textarea>


Вообщем все, сообщения готовы, пробуйте!
ps Если надо, могу написать, как реализовать удаление и просмотр сообщений
Tags:
php, socket.io, node.js, mysql, мгновенные сообщения

You can't comment this post because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author's username will be hidden by an alias.