Игра Яндекс Практикума
Игра Яндекс Практикума
Игра Яндекс Практикума

«Хочу как Дуров»: пишем простой мессенджер

Отредактировано

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

132К открытий154К показов
«Хочу как Дуров»: пишем простой мессенджер

В последнее время растёт популярность приложений для обмена сообщениями. Пользователи предпочитают мессенджеры, потому что они позволяют взаимодействовать в режиме реального времени. В этой статье мы разберём процесс создания простого приложения для обмена мгновенными сообщениями. Не будем сильно углубляться в нюансы разработки: мы напишем рабочий мессенджер, который в дальнейшем можно будет улучшить.

Статья подойдёт состоявшимся программистам и тем, кто только интересуется, как войти в IT.

Используемые технологии и инструменты

  1. Стек MEAN (Mongo, Express, Angular, Node).
  2. Сокеты для прямого обмена сообщениями.
  3. AJAX для регистрации и входа.

Подготовка

Структура будущего приложения выглядит примерно так:

«Хочу как Дуров»: пишем простой мессенджер 1

Установите Node.js и MongoDB. Кроме того, нам понадобится библиотека AngularJS, скачайте её и скопируйте в папку lib каталога Client.

Чтобы сделать пользовательский интерфейс приложения привлекательнее, вы можете воспользоваться любой CSS-библиотекой. Скачайте её и скопируйте в lib.

Примечание: созданный мессенджер можно будет интегрировать в качестве виджета в любой проект.

Серверная часть

Шаг 1. Запуск проекта

Перейдите в каталог Server и выполните команду:

			npm init
		

Она запустит новый проект.

Укажите все необходимые сведения. В результате будет создан файл package.json примерно следующего вида:

			{
  "name": "chat",
  "version": "1.0.0",
  "description": "Chat application",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Your name",
  "license": "ISC"
}
		

Шаг 2. Установка зависимостей

  • socket.io — JavaScript-библиотека, которая предоставляет двустороннюю связь клиента и сервера в режиме реального времени;
  • express — фреймворк Node.js, предоставляющий набор функций для разработки мобильных и веб-приложений. Позволяет отвечать на HTTP-запросы, используя промежуточное ПО, а также отображать HTML-страницы.

Выполнение этих команд установит необходимые зависимости и добавит их в package.json:

			npm install --save socket.io
npm install --save express
		

Выглядеть они будут примерно так:

			"dependencies": {
    "express": "^4.14.0",
    "socket.io": "^1.4.8"
}
		

Шаг 3. Создание сервера

Создадим сервер, который обслуживает порт 3000 и возвращает HTML-файл при вызове. Для инициализации нового соединения сокету нужно передать HTTP-объект. Событие connection будет прослушивать входящие сокеты, каждый сокет будет выпускать событие disconnect, которое будет вызвано при отключении клиента. Мы будем использовать следующие функции:

  • socket.on(...) — ожидает событие, и когда оно происходит, то выполняет функцию обратного вызова.
  • io.emit(...) — используется для отправки сообщения всем подключенным сокетам.

Синтаксис следующий:

			socket.on('event', function(msg){})
io.emit('event', 'message')
		

Создайте сервер с именем server.js. Он должен:

  • Выводить сообщение в консоль при подключении пользователя.
  • Слушать событие chat message и транслировать полученное сообщение на все подключенные сокеты.
  • Когда пользователь отключается, выводить сообщение в консоль.

В результате ваш сервер будет выглядеть примерно так:

			var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
  res.sendfile('index.html');
});

io.on('connection', function(socket){
  console.log('user connected');
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
  });
  socket.on('disconnect', function(){
    console.log('user disconnected');
  });
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});
		

Клиентская часть

Создайте файлы index.html в каталоге Client, style.css в каталоге CSS и app.js в каталоге js.

Client/index.html

Пусть это будет простой HTML-код, который получает и отображает наши сообщения.

Включите скрипты socket.io-client и angular.js в ваш HTML:

			<script src="/path/to/angular.js"></script>
<script src="/socket.io/socket.io.js"></script>
		

socket.io служит для нас клиентом. Он по умолчанию подключается к хосту, обслуживающему страницу.

В результате index.html должен выглядеть примерно так:

			<!doctype html>
<html ng-app="myApp">
  <head>
    <title>Socket.IO chat</title>
    <link rel="stylesheet" href="/css/style.css">
    <script src="/lib/angular/angular.js"></script>
    <script src="/socket.io/socket.io.js"></script>
    <script src="http://code.jquery.com/jquery-1.11.1.js"></script>
    <script src="/js/app.js"></script>
  </head>
  <body ng-controller="mainController">
    <ul id="messages"></ul>
    <div>
      <input id="m" ng-model="message" autocomplete="off" />
      <button ng-click="send()">Send</button>
    </div>
  </body>
</html>
		

CSS/style.css

Чтобы придать нашей странице внешний вид окна чата, добавим немного стилей. Вы можете использовать любую CSS-библиотеку. Получим следующее:

			* {
  margin: 0; 
  padding: 0; 
  box-sizing: border-box; 
}
body { 
  font: 13px Helvetica, Arial;
}
div {
  background: #000; 
  padding: 3px; 
  position: fixed; 
  bottom: 0; 
  width: 100%; 
}
div input { 
  border: 0; 
  padding: 10px; 
  width: 90%; 
  margin-right: .5%; 
}
div button { 
  width: 9%; 
  background: rgb(130, 224, 255); 
  border: none; 
  padding: 10px; 
}
#messages { 
  list-style-type: none; 
  margin: 0; 
  padding: 0; 
}
#messages li { 
  padding: 5px 10px; 
}
#messages li:nth-child(odd) { 
  background: #eee; 
}
		

js/app.js:

Создайте Angular-приложение и инициализируйте соединение сокета. Для этого нужны следующие функции:

  • socket.on(...) — слушает определенное событие, и, когда оно происходит, выполняет функцию обратного вызова.
  • socket.emit(...) — используется для отправки сообщения конкретному событию.

Синтаксис следующий:

			socket.on('event name', function(msg){});
socket.emit('event name', message);
		

Теперь, когда будет набран текст сообщения и нажата кнопка, вызовите функцию отправки сообщения. Когда сокет получит сообщение, отобразите его.

В результате app.js будет выглядеть примерно так:

			var app=angular.module('myApp',[]);

app.controller('mainController',['$scope',function($scope){
  var socket = io.connect();
  $scope.send = function(){
    socket.emit('chat message', $scope.message);
    $scope.message="";
  }
  socket.on('chat message', function(msg){
    var li=document.createElement("li");
    li.appendChild(document.createTextNode(msg));
    document.getElementById("messages").appendChild(li);
  });
}]);
		

Запуск приложения

Перейдите в папку с server.js и запустите команду:

			node server.js
		

Сервер начнет работу на порте 3000. Чтобы в этом убедиться, перейдите по ссылке в браузере:

			http://localhost:3000
		

Ваш собственный мессенджер готов!

Что можно улучшить?

Можно создать базу данных для хранения информации о пользователях и истории сообщений. Лучше, если она будет масштабируемой, потому что в дальнейшем это позволит добавить больше функций.

Установите Mongoose или MongoDB для работы с базами данных Mongo:

			npm install --save mongoose
		

или:

			npm install --save mongodb
		

Можете ознакомиться с документацией по их использованию: mongoose и mongodb.

Схема должна получиться примерно следующего вида:

			{
 "_id" : ObjectId("5809171b71e640556be904ef"),
 "name" : "Monkey proger",
 "handle" : "mkproger",
 "password" : "proger228",
 "phone" : "8888888888",
 "email" : "dontwritemepleez@gmail.com",
 "friends" : [
    {
      "name" : "habrick",
      "status" : "Friend"
    },
    {
      "name" : "javaman",
      "status" : "Friend"
    }
 ],
 "__v" : 0
}
		

Собеседникам могут быть присвоены следующие статусы:

  • Friend — собеседник является другом.
  • Pending — собеседник пока не принял запрос.
  • Blocked — собеседник заблокирован.

Предположим, что собеседник отклонил запрос на приватную беседу. В таком случае отправитель должен иметь возможность снова направить запрос.

Неплохо было бы реализовать для пользователя функционал сохранения сообщений в дополнительные коллекции. Пусть каждый её объект содержит сообщение, отправителя, получателя и время. Спроектируйте вашу базу данных в соответствии с конкретными потребностями и методами обработки сообщений.

Также вы можете создать REST API для обслуживания клиента. Например, конечную точку, отправляющую домашнюю страницу, из которой пользователи могут выполнять другие запросы.

Некоторые из возможных конечных точек API:

			app.post('/register', function(req,res){})

app.post('/login', function(req,res){})

app.post('/friend_request', function(req,res){})

app.post('/friend_request/confirmed', function(req,res){})
		

Вот какой мессенджер получился у автора статьи:

«Хочу как Дуров»: пишем простой мессенджер 2
«Хочу как Дуров»: пишем простой мессенджер 3

Исходный код приложения можно найти на GitHub.

Следите за новыми постами
Следите за новыми постами по любимым темам
132К открытий154К показов