Перейти к содержанию

Что такое tcp а что iphone

Время на прочтение
12 мин

Количество просмотров 14K


Picture created by rawpixel.com

В этой публикации мы опустимся на уровень TCP, изучим сокеты и средства Core Foundation на примере разработки приложения для чата.

Приблизительное время чтения публикации: 25 минут.

Почему сокеты?

Вы можете удивиться: «А зачем мне идти на уровень ниже, чем URLSession?» Если вы достаточно сообразительны и не задаётесь этим вопросом, переходите сразу к следующему разделу.

Ответ для не столь сообразительных

Отличный вопрос! Дело в том, что использование URLSession основано на протоколе HTTP, то есть связь происходит в стиле запрос-отклик, примерно следующим образом:

  • запросить с сервера какие-то данные в формате JSON
  • получить эти данные, обработать, отобразить, etc.

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

Конечно, мы можем непрерывно дергать сервер и смотреть, если там данные для нас (aka polling). Или мы можем быть более изощренными и использовать long-polling. Но все эти костыли слегка неуместны в данном случае.

В конце концов, зачем ограничивать себя парадигмой request-response, если она подходит к нашей задаче чуть меньше, чем никак?

В этом руководстве вы научитесь, как погрузиться на более низкий уровень абстракции и напрямую использовать СОКЕТЫ в приложении для чата.

Вместо того, чтобы проверять сервер на наличие новых сообщений, наше приложение будет использовать потоки (streams), остающиеся открытыми на протяжении чат-сессии.

Начинаем

Загрузите исходные материалы. Там есть макет приложения-клиента и простой сервер, написанный на Go.

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

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

В исходных материалах есть как скомпилированное приложение, так и исходник. Если у вас здоровая паранойя и вы не доверяете чужому откомпилированному коду, вы можете самостоятельно скомпилировать исходники.

Если же вы отважны, то откройте Terminal, перейдите в каталог с загруженными материалами и выполните команду:

sudo ./server

Когда появится запрос, введите пароль. После этого вы должны увидеть сообщение

Listening on 127.0.0.1:80.

Замечание: серверное приложение запускается в привилегированном режиме (команда «sudo»), потому что прослушивает порт 80. Все порты с номерами меньше, чем 1024, требуют специального доступа.

Ваш чат-сервер готов! Можете перейти к следующему разделу.

Если же вы хотите самостоятельно скомпилировать исходники сервера,

то в этом случае вам необходимо при помощи Homebrew установить Go.

Если у вас нет и Homebrew, то нужно установить вначале его. Откройте Terminal и вставьте туда следующую строку:

/usr/bin/ruby -e
"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Затем используйте эту команду для установки Go:

brew install go

По окончании перейдите в каталог с загруженными исходными материалами и скомпилируйте исходники серверного приложения:

go build server.go

Наконец, можно запустить сервер командой, приведенной в начале этого раздела.

Смотрим, что у нас в клиенте

Теперь откройте проект DogeChat, откомпилируйте его и посмотрите, что там есть.

Как видим, DogeChat сейчас позволяет ввести имя пользователя и перейти в раздел собственно чата.

Похоже, что разработчик, занимавшийся этим проектом, понятия не имел, как сделать чат. Так что всё, что у нас есть — это базовый UI и навигация. Сетевой слой будем писать мы. Ура!

Создаём комнату для чата

Чтобы перейти непосредственно к разработке, перейдите к ChatRoomViewController.swift. Это вьюконтроллер, который может получать введенный пользователем текст и отображать получаемые сообщения в тейблвью.

Так как у нас есть ChatRoomViewController, есть смысл разработать класс ChatRoom, который будет заниматься всей черновой работой.

Давайте подумаем о том, что будет обеспечивать новый класс:

  • открытие соединения с приложением-сервером;
  • подключение пользователя с заданным им именем к чату;
  • передачу и получение сообщений;
  • закрытие соединения по окончании.

Теперь, когда мы знаем, чего хотим от этого класса, жмём Command-N, выбираем Swift File и обзываем его ChatRoom.

Создаём потоки ввода/вывода

Заменим содержимое ChatRoom.swift вот этим:

import UIKit
class ChatRoom: NSObject {
  //1
  var inputStream: InputStream!
  var outputStream: OutputStream!

  //2
  var username = ""

  //3
  let maxReadLength = 4096
}

Тут мы определяем класс ChatRoom и объявляем нужные нам свойства.

  1. Сначала мы определяем потоки ввода/вывода. Использование их парой позволит нам создать соединение на сокете между приложением и чат-сервером. Разумеется, мы будем отправлять сообщения, используя поток вывода, а получать — при помощи потока ввода.
  2. Далее мы определяем имя пользователя.
  3. И, наконец, мы определяем переменную maxReadLength, которой ограничиваем максимальную длину отдельного сообщения.

Теперь перейдите к файлу ChatRoomViewController.swift и добавьте эту строчку к списку его свойств:

let chatRoom = ChatRoom()

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

Открываем соединение

Возвращаемся к ChatRoom.swift и за определениями свойств добавляем этот метод:

func setupNetworkCommunication() {
  // 1
  var readStream: Unmanaged<CFReadStream>?
  var writeStream: Unmanaged<CFWriteStream>?

  // 2
  CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
                                     "localhost" as CFString,
                                     80,
                                     &readStream,
                                     &writeStream)
}

Вот что мы тут делаем:

  1. сначала мы определяем две переменных для потоков сокета без использования автоматического управления памятью
  2. затем мы, используя эти самые переменные, создаем непосредственно потоки, привязанные к хосту и номеру порта.

У функции четыре аргумента. Первый — это тип распределителя памяти, который мы будем использовать при инициализации потоков. Вы должны использовать kCFAllocatorDefault, хотя есть и другие возможные варианты, в случае, если вы хотите изменить поведение потоков.

Примечание переводчика

Документация к функции CFStreamCreatePairWithSocketToHost говорит: используйте NULL или kCFAllocatorDefault. А описание kCFAllocatorDefault говорит, что это синоним NULL. Круг замкнулся!

Затем мы задаем имя хоста. В нашем случае мы подключаемся к локальному серверу. Если у вас сервер расположен в другом месте, то тут можно задать его IP адрес.

Затем номер порта, которые прослушивает сервер.

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

Теперь, когда у нас есть инициализированные потоки, мы можем сохранить ссылки на них, добавив эти строки в конце метода setupNetworkCommunication():

inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()

Использование takeRetainedValue() применительно к неуправляемому объекту позволяет нам сохранить ссылку на него, и, одновременно, избежать в дальнейшем утечек памяти. Теперь мы можем использовать наши потоки где захотим.

Теперь нам нужно добавить эти потоки к циклу выполнения (run loop), чтобы наше приложение корректно отрабатывало сетевые события. Для этого добавим эти две строчки в конце setupNetworkCommunication():

inputStream.schedule(in: .current, forMode: .common)
outputStream.schedule(in: .current, forMode: .common)

Наконец пора поднять паруса! Чтобы начать, добавьте это в самом конце метода setupNetworkCommunication():

inputStream.open()
outputStream.open()

Теперь у нас есть открытое соединение между нашим клиентом и серверным приложением.

Мы можем скомпилировать и запустить наше приложение, но никаких изменений вы пока не увидите, потому что пока мы ничего не делаем с нашим соединением клиент-сервер.

Подключаемся к чату

Теперь, когда у нас есть установленное соединение с сервером, самое время начать с этим что-то делать! В случае чата, вам нужно сначала представиться, а затем вы сможете слать собеседникам сообщения.

Это приводит нас к важному выводу: так как у нас два типа сообщений, нам нужно как-то их различать.

Протокол чата

Одно из преимуществ использования уровня TCP состоит в том, что мы можем определить свой собственный «протокол» для взаимодействия.

Если бы мы использовали HTTP, то нам нужно было бы использовать эти разные словечки GET, PUT, PATCH. Нам нужно было бы формировать URL’ы и использовать для них правильные хедеры и все такое.

У нас же всего два типа сообщений. Мы будем слать

iam:Luke

чтобы войти в чат и представиться.

И мы будем слать

msg:Hey, how goes it, man?

чтобы отправить сообщение всем респондентам в чате.

Это очень просто, но абсолютно несекюрно, поэтому не используйте подобный способ в критически важных проектах.

Теперь мы знаем, чего ожидает наш сервер и можем написать метод в классе ChatRoom, который позволит пользователю подключиться к чату. Единственный аргумент — это «ник» пользователя.

Добавьте этот метод внутри ChatRoom.swift:

func joinChat(username: String) {
  //1
  let data = "iam:(username)".data(using: .utf8)!
  
  //2
  self.username = username

  //3
  _ = data.withUnsafeBytes {
    guard let pointer = $0.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
      print("Error joining chat")
      return
    }
    //4
    outputStream.write(pointer, maxLength: data.count)
  }
}

  1. Сначала мы формируем наше сообщение, используя наш собственный «протокол»
  2. Сохраняем имя для дальнейшего использования.
  3. withUnsafeBytes(_:) обеспечивает удобный способ работы с небезопасным указателем внутри замыкания.
  4. Наконец мы отправляем наше сообщение в выходной поток. Это может выглядеть сложнее, чем можно было бы предположить, однако write(_:maxLength:) использует небезопасный указатель, созданный на предыдущем этапе.

Теперь наш метод готов, откроем ChatRoomViewController.swift и добавим вызов этого метода в конце viewWillAppear(_:).

chatRoom.joinChat(username: username)

Теперь откомпилируйте и запустите приложение. Введите ваш ник и тапните на return чтобы увидеть…

что опять ничего не изменилось!

Постойте, все в порядке! Перейдите к окну терминала. Там вы увидите сообщение Вася has joined или что-то в этом роде, если ваше имя не Вася.

Это здорово, но хорошо бы иметь индикацию успешного подключения на экране своего телефона.

Реагирование на входящие сообщения

Сервер рассылает сообщения о присоединении клиента всем, кто есть в чате, в том числе и вам. К счастью, в нашем приложении уже есть все для отображения любых входящих сообщений в виде ячеек в таблице сообщений в ChatRoomViewController.

Всё, что вам нужно сделать — использовать inputStream, чтобы «отловить» эти сообщения, преобразовать их в экземпляры класса Message, и передать их таблице для отображения.

Чтобы иметь возможность реагировать на входящие сообщения, вам необходимо, чтобы ChatRoom соответствовал протоколу StreamDelegate.

Для этого внизу файла ChatRoom.swift добавьте это расширение:

extension ChatRoom: StreamDelegate {
}

Теперь объявим того, кто станет делегатом inputStream‘а.

Добавьте эту строчку в метод setupNetworkCommunication() прямо перед вызовами schedule(in:forMode:):

inputStream.delegate = self

Теперь добавим в расширение реализацию метода stream(_:handle:):

func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
    switch eventCode {
    case .hasBytesAvailable:
      print("new message received")
    case .endEncountered:
      print("The end of the stream has been reached.")
    case .errorOccurred:
      print("error occurred")
    case .hasSpaceAvailable:
      print("has space available")
    default:
      print("some other event...")
    }
}

Обрабатываем входящие сообщения

Итак, мы готовы приступить к обработке входящих сообщений. Событие, которое нас интересует — .hasBytesAvailable, которое показывает, что поступило входящее сообщение.

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

private func readAvailableBytes(stream: InputStream) {
  //1
  let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: maxReadLength)

  //2
  while stream.hasBytesAvailable {
    //3
    let numberOfBytesRead = inputStream.read(buffer, maxLength: maxReadLength)

    //4
    if numberOfBytesRead < 0, let error = stream.streamError {
      print(error)
      break
    }

    // Construct the Message object
  }
}

  1. Устанавливаем буфер, в который будем читать поступающие байты.
  2. Крутимся в цикле, пока во входящем потоке есть, что читать.
  3. Вызываем read(_:maxLength:), который считывает байты из потока и помещает их в буфер.
  4. Если вызов вернул отрицательное значение — возвращаем ошибку и выходим из цикла.

Нам нужно вызывать этот метод как только у нас во входящем потоке есть данные, так что идем к оператору switch внутри метода stream(_:handle:), находим переключатель .hasBytesAvailable и вызываем этот метод сразу после оператора print:

readAvailableBytes(stream: aStream as! InputStream)

В этом месте у нас готовенький буфер полученных данных!

Но нам еще нужно превратить этот буфер в содержимое таблицы сообщений.

Разместим этот метод за readAvailableBytes(stream:).

private func processedMessageString(buffer: UnsafeMutablePointer<UInt8>,
                                    length: Int) -> Message? {
  //1
  guard 
    let stringArray = String(
      bytesNoCopy: buffer,
      length: length,
      encoding: .utf8,
      freeWhenDone: true)?.components(separatedBy: ":"),
    let name = stringArray.first,
    let message = stringArray.last 
    else {
      return nil
  }
  //2
  let messageSender: MessageSender = 
    (name == self.username) ? .ourself : .someoneElse
  //3
  return Message(message: message, messageSender: messageSender, username: name)
}

Сначала мы инициализируем String, используя буфер и размер, которые передаем в этот метод.

Текст будет в UTF-8, по окончании освобождаем буфер, и делим сообщение по символу ‘:’, чтобы разделить имя отправителя и собственно сообщение.

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

Наконец, их всего этого хозяйства мы формируем экземпляр Message и возвращаем его.

Для использования этого метода добавьте следующий if-let в конце цикла while в методе readAvailableBytes(stream:), сразу после последнего комментария:

if let message = 
    processedMessageString(buffer: buffer, length: numberOfBytesRead) {
  // Notify interested parties
}

Сейчас всё готово для того, чтобы передать кому-то Message… Но кому же?

Создаём протокол ChatRoomDelegate

Итак, нам нужно проинформировать ChatRoomViewController.swift о новом сообщении, но у нас нет ссылки на него. Так как он содержит сильную ссылку на ChatRoom, мы можем попасть в ловушку цикла сильных ссылок.

Это идеальное место для создания протокола-делегата. ChatRoom всё равно, кому нужно знать про новые сообщения.

Вверху ChatRoom.swift добавим новое определение протокола:

protocol ChatRoomDelegate: class {
  func received(message: Message)
}

Теперь внутри класса ChatRoom добавим слабую ссылку для хранения того, кто станет делегатом:

weak var delegate: ChatRoomDelegate?

Теперь допишем метод readAvailableBytes(stream:), добавив следующую строчку внутри конструкции if-let, под последним комментарием в методе:

delegate?.received(message: message)

Возвращаемся к ChatRoomViewController.swift и добавляем следующее расширение класса, которое обеспечивает соответствие протоколу ChatRoomDelegate, сразу после MessageInputDelegate:

extension ChatRoomViewController: ChatRoomDelegate {
  func received(message: Message) {
    insertNewMessageCell(message)
  }
}

Исходный проект уже содержит необходимое, так что insertNewMessageCell(_:) примет ваше сообщение и отобразит в тейблвью правильную ячейку.

Теперь назначим вьюконтроллер делегатом, добавив это во viewWillAppear(_:) сразу после вызова super.viewWillAppear()

chatRoom.delegate = self

Теперь откомпилируйте и запустите приложение. Введите имя и тапните return.

Вы увидите ячейку о вашем подключении к чату. Ура, вы успешно послали сообщение серверу и получили от него ответ!

Отправление сообщений

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

В ChatRoom.swift добавьте следующий метод в конце определения класса:

func send(message: String) {
  let data = "msg:(message)".data(using: .utf8)!

  _ = data.withUnsafeBytes {
    guard let pointer = $0.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
      print("Error joining chat")
      return
    }
    outputStream.write(pointer, maxLength: data.count)
  }
}

Этот метод похож на joinChat(username:), который мы написали раньше, за исключением того, что у него префикс msg перед текстом (для обозначения того, что это реальное сообщение в чат).

Так как мы хотим отсылать сообщения по кнопке Send, возвращаемся к ChatRoomViewController.swift и находим там MessageInputDelegate.

Здесь мы видим пустой метод sendWasTapped(message:). Чтобы послать сообщение передайте его chatRoom:

chatRoom.send(message: message)

Собственно, это всё! Так как сервер получит сообщение и перешлёт его всем и каждому, ChatRoom будет уведомлен о новом сообщение тем же образом, как и при присоединении к чату.

Скомпилируйте и запустите приложение.

Если вам не с кем сейчас початиться, запустите новое окно Терминала и введите:

nc localhost 80

Это подключит вас к серверу. Теперь вы можете подключиться к чату, используя тот же «протокол»:

iam:gregg

А так — послать сообщение:

msg:Ay mang, wut's good?

Поздравляю, вы написали клиента для чата!

Подчищаем за собой

Если вы занимались когда-либо разработкой приложений, которые активно читают/пишут в файлы, то вы должны знать, что хорошие разработчики закрывают файлы по окончании работы с ними. Дело в том, что соединение через сокет обеспечивается дескриптором файла. Это означает, что по окончании работы нужно его закрыть, как любой другой файл.

Для этого добавьте в ChatRoom.swift следующий метод после определения send(message:):

func stopChatSession() {
  inputStream.close()
  outputStream.close()
}

Как вы наверняка догадываетесь, этот метод закрывает потоки, так что вы больше не сможете получать и отправлять сообщения. Кроме того, потоки удаляются из цикла выполнения (run loop), в который мы ранее их помещали.

Добавьте вызов этого метода в секцию .endEncountered в операторе switch внутри stream(_:handle:):

stopChatSession()

Затем вернитесь к ChatRoomViewController.swift и сделайте то же самое во viewWillDisappear(_:):

chatRoom.stopChatSession()

Всё! Теперь точно всё!

Заключение

Теперь, когда вы овладели основами сетевого взаимодействия при помощи сокетов, вы можете углубить свои познания.

UDP Sockets

Это приложение — пример сетевого взаимодействия при помощи TCP, которое гарантирует доставку пакетов по назначению.

Однако можно использовать и UDP сокеты. Этот тип соединения не гарантирует доставки пакетов по назначению, однако он значительно быстрее.

Особенно полезно это в играх. Когда-нибудь испытывали лаг? Это означало, что у вас было плохое соединение и множество UDP пакетов было потеряно.

WebSockets

Другая альтернатива HTTP в приложениях — технология, называемая вебсокеты.

В отличие от обычных TCP сокетов, вебсокеты для установления взаимодействия используют HTTP. С их помощью можно достичь того же, что и с обычными сокетами, но с комфортом и безопасностью, как в браузере.

TCP/IP (Transmission Control Protocol/Internet Protocol) – это модель передачи цифровых данных. Протокол передачи TCP/IP описывает правила передачи данных, стандарты связи между компьютерами, а также содержит соглашения о маршрутизации и межсетевом взаимодействии.

Что такое протокол и для чего он нужен? Протокол – это набор правил, благодаря которым устройства обмениваются данными через интернет. Эти правила сообщают устройствам о том:

  • Как начинать общение и приветствовать другую сторону.
  • Как договориться с другим устройством о параметрах передачи данных.
  • Что делать при ошибках.
  • Как узнать, что передача данных закончена.

Сетевые протоколы TCP/IP обеспечивает связь между устройствами, работающими через интернет. Обычно эти устройства называют хостами. Хотя существуют и другие протоколы передачи данных, TCP/IP выделяется тем, что при его работе обеспечивается аппаратная независимость.

Это значит, что работа протокола не зависит от особенностей аппаратного обеспечения, он позволяет организовать обмен данными между любыми устройствами с различной технологией передачи данных. Кроме этого, сетевая модель TCP/IP определяет стандарты для множества различных служб связи конечных пользователей.

Благодаря TCP/IP возможны такие действия:

  • Передача данных в другую систему.
  • Вход в удаленную систему.
  • Управление сетью.
  • Отправка сообщений удаленным пользователям.
  • Выполнение удаленных команд.
  • Печать файлов из удаленной системы.

Как работает TCP/IP

TCP и IP два отдельных протокола, работающие вместе. Они образуют стек протоколов надежной передачи данных. Стек протоколов TCP/IP различают два типа сокетов TCP (потоковые) и UDP (датаграммные). Подробнее о сокетах расскажем далее.

UDP – простой протокол с минимальной дополнительной нагрузкой, он подходит для отправки небольших сообщений, когда не важна надежность при передаче данных. Протокол TCP – выполняет проверку доставки всех файлов адресату и проверяет не было ли ошибки при передаче информации. TCP может повторно запросить данные, если они были потеряны и регулировать загрузку сети.

Стек протоколов TCP/IP позволяет обеспечивать доставку информации в необходимое место назначения. IP определяет адрес доставки, а TCP отвечает за процесс передачи и доставки данных. Для более наглядного примера предположим, что IP – это адрес электронной почты, а TCP — это почтовый клиент, с помощью которого происходит отправка сообщений.

Протоколы используются вместе, чтобы информация имела место назначения, а сам процесс происходил безопасно.

Для работы протоколов необходима установка TCP/IP – специального программного обеспечение. Обычно, оно устанавливается с операционной системой и не требует скачивания дополнительных программ.

Как настроить TCP/IP

Настройка TCP/IP происходит в разделе основных настроек компьютера.

Windows

  1. В меню Пуск выберите Сеть и интернет.
  2. Далее перейдите в раздел Ethernet.
  3. В открывшемся окне найдите пункт Настройка параметров адаптера.
  4. Затем снова выберите пункт Ethernet, нажав на него правой кнопкой мыши, и выберите раздел свойства.
  5. В открывшемся окне двойным щелчком по левой кнопке мыши выберите пункт IP версии 4 (TCP/IPv4).
  6. В новом окне отметьте точками: Получить IP-адрес автоматически и Получить адрес DNS-сервера автоматически.
  7. На вкладке Альтернативная конфигурация отметьте точку Автоматический частный IP-адрес.
  8. Нажмите ОК, чтобы сохранить настройки.

MacOS

  1. Выберите меню Apple и перейдите в Системные настройки.
  2. Зайдите в раздел Сеть.
  3. Слева выберите сетевую службу, которую используете.
  4. Далее нажмите Подробнее.
  5. Выберите раздел TCP/IP.
  6. Для адреса IPv4, кликните всплывающее меню «Конфигурация IPv4».
  7. Выберите здесь один из вариантов, потом введите адрес IPv4, маску подсети и адрес маршрутизатора.
  8. Для адреса IPv6, кликните всплывающее меню «Конфигурация IPv6»
  9. Выберите один из вариантов, потом введите адрес маршрутизатора, адрес IPv6 и длину префикса.
  10. Если у вас есть ID клиента DHCP, укажите его.
  11. Нажмите ОК.

Что такое сокеты

Сокет — это программный механизм, который обеспечивает сетевое взаимодействие, помогает осуществлять передачу информации от одного компьютера к другому. Он представляет собой конструкцию, состоящую из IP-адреса и номера порта.

Сокет был придуман для того, чтобы облегчить программистам процесс написания кодов. При работе с сокетами программистам не надо разбираться с IP и портами, при программировании он указывает, что хочет создать сокет и обозначает для него IP-адрес. Программа, в которой работает специалист, создает сокет. Далее информация отправляется и принимается в сокете, а программа отвечает за ее передачу.

Основное назначение сокетов – передача данных через сеть и обеспечение связи между различными приложениями.

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

Чтобы к серверу можно было одновременно подключиться нескольким приложениям, сервер делает копии сокетов.

Для чего нужны порты

Сетевые порты представляют собой 16-ти битное число от 1 до 65535, которое определяет назначение пакетов данных в пределах одного хоста. Они необходимы, чтобы осуществлять передачу информации определенного вида. Все хосты передают данные при помощи IP-адресов, когда происходит подключение к сети, порты определяют к какой программе относятся передаваемые файлы. Основные программы это:

  • Web-сервер, для трансляции с веб-сайтов.
  • Почтовый сервер, для обмена электронными письмами.
  • FTP-сервер, для передачи информации.

Например, пользователь на своем ноутбуке открывает браузер и вбивает поисковый запрос, веб-сервер при этом автоматически отправляет данные по протоколу TCP/IP в порт 80.

При работе с почтовым клиентом Outlook используется два стандартизированных порта: порт 110 – для получения электронных сообщений и порт 25 – для отправки писем к адресату.

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

Что можно делать с портом

  • Открыть. Чтобы знать куда направлять данные, которые пришли по адресу порта.
  • Закрыть. Чтобы прекратить передачу данных.
  • Пробросить. Если запрос пришел на порт 1020, отправить его на порт 2020.
  • Просканировать. То есть проверить числа от 0 до 65535 на предмет ответа от кого-то из них. Если ответ найден, то это будет означать, что на этом порту работает какая-то программа. Это поможет найти уязвимости и вредоносные программы.
  • Заблокировать. Например, для того, чтобы не допустить посторонних к открытому порту.
  • Задать. Если для работы программы требуется порт, который у вас заблокирован, ей можно создать другой порт и проводить обмен данными через него.

Уровни протоколов TCP/IP

Одной из основных и первых моделей передачи данных была OSI (The Open Systems Interconnection model). В соответствии с ней происходит работа сетевых протоколов, так как она устанавливает основные требования и правила. Модель OSI состоит из семи уровней, каждый из них определяет нормы сотрудничества систем между собой:

  • Прикладной уровень
  • Сеансовый уровень
  • Уровень представления
  • Транспортный уровень
  • Сетевой уровень
  • Канальный уровень
  • Физический уровень

Несколько протоколов, работающих по определенным уровням, называют стеком протоколов. Современный интернет работает на стеке протоколов TCP/IP. Различают следующие уровни стека TCP/IP:

  1. Прикладной уровень TCP/IP

Регулирует работу сетевых приложений, например, браузеры, программы для загрузки файлов по ftp, почтовые клиенты, SSH. Эти программы могут использовать свои протоколы обмена данными.

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

Комбинация IP-адреса и номера порта передачи данных называется сокетом. Определенные порты используют для упрощения стандартов, каждый порт соответствует функциональному назначению приложения (Например, почтовый SMTP-сервер использует 25 порт).

  1. Транспортный уровень TCP/IP

Работу этого уровня определяют протоколы TCP (Transmission Control Protocol) и UDP (User Datagram Protocol). Протокол TCP анализирует переданные пакеты информации и, в случае ошибки, повторно запрашивает пакеты. Также он следит за верной последовательностью переданных пакетов. UDP – протокол без установки соединения, он выполняет небольшую проверку и считается ненадежным. Отправка информации с помощью UDP выполняется быстрее по сравнению с TCP.

Передача данных начинается с установки соединения: хост-клиент отправляет фрагмент данных с номером последовательности и флагом SYN (служит для обозначения начала установки соединения). Сервер выделяет память для обработки задачи и назад отправляет фрагмент с номером последовательности и флагами SYN и ACK (служит для обозначения получения подтверждения).

Получив флаг SYN, хост-клиент отправляет сегмент с флагом ACK, в том случае, когда этот флаг узел уже получил, включается режим ESTABLISHED ( или активное соединение). Если, повторив свой запрос, хост не получает ответа, то через некоторое время включается режим CLOSED (или завершение сеанса связи):

  • Хост-получатель шлет хосту-отправителю флаг FIN (конец передачи данных).
  • Узел возвращает флаги ответа ACK, FIN о завершении связи.
  • Хост-клиент устанавливает соединение, и шлет хосту сигнал о завершении сессии в виде флага ACK (получение подтверждения).
  1. Межсетевой или сетевой уровень TCP/IP

Так как глобальная сеть объединяет в себе множество локальных сетей, то сетевой уровень нужен для регламентирования передачи данных и взаимодействия локальных сетей.

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

IP (Internet Protocol) – основной протокол межсетевого уровня. Он отвечает за перемещение пакетов между подсетями – от одного пограничного маршрутизатора до другого, пока данные не достигнут сети назначения.

  1. Канальный уровень TCP/IP

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

Чаще всего на этом уровне используют протокол Ethernet, он определяет проводные соединения и электросигналы на физическом уровне. Когда хост собирается передать пакет информации, он проверяет свободен ли канал в этот момент (по наличию несущей частоты в кабеле). Если частота не найдена, то начинается передача данных. Передача информации ограничивается по времени, она не может превышать, а также быть меньше заданной величины. Это необходимо для предотвращения единоличного использования сети одним компьютером и доступом к сети другим пользователям.

Зачем нужны уровни сетевой модели TCP/IP? Передача файлов между двумя хостами напрямую невозможна. Сначала пакеты данных попадают на сетевой уровень, чтобы получить IP-адрес. На транспортном уровне, с помощью протокола TCP, отдельные части данных передаются хосту. На каждом уровне к передаваемым файлов добавляется служебная информация: например, указание порта, чтобы распознать приложение. Кроме того, информацию могут добавлять протоколы Ethernet, IP, TCP и другие.

Такое наслоение правил и дополнительной информации называется стеком. Таким образом, стек – набор сетевых протоколов с иерархической структурой. Главная задача стека – достаточный набор правил, который обеспечивает взаимодействие устройств в интернете.

Чтобы все протоколы могли работать одновременно и не конфликтовали между собой, были выделены уровни стека протоколов TCP/IP. Каждый уровень решает свою определенную задачу, что снижает возникновение сбоев и незавершенных операций.

Заключение

Протокол интернета TCP/IP популярен своей возможностью реализовать широкий набор функций: совместное использование файлов, принтеров, удаленный доступ к системам и серверам. Стек TCP/IP – надежный набор протоколов, благодаря которым легко налаживаться работа приложений, а управление маршрутизацией удобно настраивается.

#статьи

  • 26 апр 2023

  • 0

Рассказываем о главной «курьерской службе» интернета: как данные летают по Сети, зачем их фасуют по пакетам и кто за всем этим следит.

Фото: Britta Pedersen / Getty Images

Дмитрий Зверев

Любитель научной фантастики и технологического прогресса. Хорошо сочетает в себе заумного технаря и утончённого гуманитария. Пишет про IT и радуется этому.

Вы когда-нибудь задумывались, как мемы, сериалы и гифки с котиками перелетают континенты, чтобы оказаться у вас на компьютере? Отвечаем: для этого в интернете есть протоколы TCP и IP — они помогают устройствам безошибочно передавать данные на большие расстояния. Как у них это получается — рассказываем в статье.

Модель TCP/IP — это стек протоколов, которые задают правила передачи данных по Сети. Так как бал здесь правят протоколы TCP и IP, в честь них и назвали всю модель.

TCP (Transmission Control Protocol) отвечает за обмен данными. Он управляет их отправкой и следит за тем, чтобы они дошли до получателя в целости. У TCP есть свои гарантии, что всё пройдёт успешно, — о них чуть позже.

IP (Internet Protocol) отвечает за адресацию. Его задача — связывать друг с другом устройства и нарезать данные на пакеты для удобной отправки. Чтобы протокол мог быстро найти дорогу от одного компьютера к другому, придумали IP-адреса — уникальные идентификаторы, которые есть у каждого устройства в Сети.

Эти два протокола работают в связке: IP строит маршрут, а TCP контролирует, чтобы всё передавалось правильно. Условно их можно сравнить с тандемом Шерлока и Ватсона в бессмертной классике Дойля: первый решает проблему, а второй следит, чтобы тот не наделал глупостей и случайно не упал в Рейхенбахский водопад.

Минутка истории. Оба протокола, и TCP, и IP, на самом деле стары как мир. Их придумала ещё в семидесятых группа разработчиков под началом «отца интернета» Винта Сёрфа. То есть все наши смартфоны и умные часы общаются по правилам, которые заложили ещё во времена расцвета диско и космической миссии «Союз — Аполлон».

Но протоколами TCP и IP модель не ограничивается — например, есть ещё HTTP, FTP, UDP и сотни других. Все они заточены под определённые задачи. Так, HTTP помогает браузеру формировать запросы к серверу, FTP — скачивать файлы, а UDP — быстро передавать видео, музыку и игры, но с возможными потерями по пути.

Настало время посмотреть, как модель TCP/IP работает в жизни. Допустим, вы заходите в интернет, чтобы почитать статью о том, как нейросети рисуют котиков. Запускаете браузер, открываете сайт Skillbox Media, нажимаете на заголовок статьи. А дальше начинается магия.

Как только вы кликнули на ссылку, браузер отправляет запрос на сервер, где лежит страница. Для этого он создаёт HTTP-запрос, в котором описывает всё, что сервер должен ему передать: «Я слышал, у тебя есть статья про генеративные нейронки. Дай, пожалуйста». Сервер отвечает: «Нет проблем» — и отправляет браузеру HTTP-ответ с нужными данными. И так они будут общаться до тех пор, пока вы не закроете сайт.

Браузер отправляет запрос, сервер возвращает ответ
Иллюстрация: Оля Ежак для Skillbox Media

Но сами по себе HTTP-запросы — это просто текстовые сообщения: они не знают, как найти сервер с нужной информацией, а тем более — как её оттуда достать. Для этих задач нам как раз и понадобятся протоколы TCP и IP.

Сначала IP определяет расположение сервера — или, точнее сказать, его IP-адрес. Чтобы найти нужный «айпишник», протокол использует систему DNS. Это такая глобальная база данных, где доменные имена сайтов лежат напротив их IP-адресов — например, сайту skillbox.ru соответствует IP-адрес 178.248.237.96.

Когда IP найдёт сервер и получит от него нужную страницу, он начнёт разбивать её на пакеты. Каждый пакет — это часть файла размером от 1 до 64 КБ. Внутри находятся сами данные и служебная информация: номер пакета, адреса отправителя и получателя и другое.

Зачем нужны пакеты. Представьте, что вам нужно перенести сразу много блюд из кухни в гостиную. Конечно, можно загрузить тарелки в обе руки, а часть поставить на голову, как делают женщины кенийского племени Луо, но, если вдруг в коридоре на вас нападёт кошка или младший брат с игрушечным пистолетом, есть риск всё выронить и испортить ужин. Гораздо безопаснее переносить блюда по одному, а ещё лучше — раздать по тарелке каждому члену семьи.

С данными точно так же: лучше передавать их маленькими порциями, так как никогда не знаешь, где по пути случится проблема. Если что-то пойдёт не так, вы потеряете всего один пакет, а не весь файл целиком.

Протокол IP ищет нужный путь, советуясь с системой DNS
Иллюстрация: Оля Ежак для Skillbox Media

Чтобы пакеты без потерь долетали от сервера к пользователю, подключается протокол TCP. Для этого в него зашили механизм подтверждения: когда сервер отправляет пакет, TCP спрашивает у устройства пользователя, нормально ли он добрался. Если ответ «да», протокол отправляет следующую порцию, если «нет» — пробует ещё раз.

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

Повторим ещё раз весь процесс:

  • Вы нажимаете на ссылку или вводите адрес сайта в строке браузера.
  • Браузер создаёт HTTP-запрос к серверу, чтобы тот отправил вам нужную страницу.
  • Протокол IP с помощью системы DNS находит сервер, где лежит страница, и разбивает её на пакеты.
  • Далее в игру вступает TCP — он устанавливает надёжное соединение между компьютером и сервером и следит, чтобы пакеты не потерялись по дороге.
  • Браузер склеивает пакеты воедино и рендерит страницу.

Этот алгоритм справедлив для статичных файлов — то есть таких, которые вы загружаете один раз и пользуетесь. Но если вы, например, хотите посмотреть видео, понадобится другой протокол — UDP. Он не гарантирует целостности данных и может потерять пакеты по пути, но это компенсируется скоростью передачи. Именно поэтому, например, вы видите пиксельные изображения, когда смотрите видео при плохом интернет-соединении.

Пора окунуться в детали и узнать, как модель TCP/IP устроена изнутри. Глобально она делится на четыре уровня:

  • канальный уровень — отвечает за взаимодействие по сетевому оборудованию, например по Ethernet-кабелю или Wi-Fi;
  • межсетевой уровень — помогает отдельным сетям общаться друг с другом;
  • транспортный уровень — отвечает за передачу данных между устройствами, например, по протоколам TCP и UDP;
  • прикладной уровень — помогает приложениям общаться друг с другом с помощью интерфейсов или API.

Структура модели TCP/IP
Иллюстрация: Оля Ежак для Skillbox Media

На каждом уровне есть свои протоколы, которые обеспечивают надёжность передачи данных между компьютерами в Сети. Всего модель TCP/IP поддерживает сотни разных протоколов.

Для чего нужен: устанавливать физическое соединение между устройствами в локальной сети с помощью радиоволн и проводов.

Примеры протоколов: Ethernet, Wi-Fi, Bluetooth.

Как работает: данные делятся на небольшие кусочки (фреймы) и передаются между устройствами. Каждый фрейм содержит часть передаваемой информации и служебные данные.

Чтобы понять, куда отправлять фреймы, используют адресацию канального уровня — MAC-адреса. Это уникальные физические адреса устройств — по ним протоколы канального уровня определяют отправителей и получателей.

Из чего состоит фрейм
Изображение: Skillbox Media

Ещё одна важная задача канального уровня — проверять, что данные передаются безошибочно. Для этого протоколы используют свои средства проверки:

  • Если возникла ошибка, устройство отправляет фрейм обратно, а второе устройство передаёт его ещё раз.
  • Если всё прошло удачно, то фрейм передаётся на следующий уровень для обработки.

Для чего нужен: строить маршруты между устройствами по всему интернету — этот процесс называется маршрутизацией.

Примеры протоколов: IP, ICMP, ARP.

Как работает: IP-протокол вычисляет местонахождение устройств по их IP-адресам, а также строит до них кратчайшие пути и делит данные на пакеты (или, как говорят на юге России, — кульки :)).

Чтобы определить, где находится получатель и как построить путь к нему, IP обращается к системе DNS — она знает IP-адреса всех устройств в интернете.

Когда адрес получен, передаваемый файл разбивается на небольшие части — пакеты. Они содержат фрагменты данных и служебную информацию, например IP-адреса отправителя и получателя.

Из чего состоит пакет
Изображение: Skillbox Media

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

Для чего нужен: передавать данные по маршруту, построенному на предыдущем уровне.

Примеры протоколов: TCP, UDP.

Как работает: устанавливает надёжное соединение между устройствами, а затем следит за передачей данных по нему и исправляет ошибки.

Главных протокола здесь два:

  • TCP (Transmission Control Protocol) — гарантирует передачу всех данных без потерь. Полезен при отправке текстовых файлов.
  • UDP (User Datagram Protocol) — не гарантирует передачу данных без потерь, но обеспечивает хорошую скорость. Полезен при просмотре видео или прослушивании музыки в интернете.

TCP решает всё медленно, но надёжно. UDP — быстро, но не факт, что качественно
Иллюстрация: Оля Ежак для Skillbox Media

И у нас остаётся последний уровень — прикладной.

Для чего нужен: настраивать связи между приложениями — например, между браузером и серверным софтом.

Примеры протоколов: HTTP, FTP, SMTP.

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

На прикладном уровне хранятся протоколы для всего, что нужно человеку: отправки имейлов, веб-браузинга, передачи файлов и удалённого доступа. Вот некоторые из них:

  • HTTP (Hypertext Transfer Protocol) — самый популярный протокол для передачи данных по интернету.
  • FTP (File Transfer Protocol) — ещё один известный протокол, заточенный под передачу файлов.
  • SMTP (Simple Mail Transfer Protocol) — протокол для отправки электронных писем.

Этот уровень нужен, чтобы упростить пользователям передачу данных по интернету. Именно с его помощью программисты и обычные пользователи взаимодействуют с моделью TCP/IP.

Модель TCP/IP — это набор правил, по которым данные перемещаются по интернету. Главными здесь являются два протокола: TCP и IP. Они нужны, чтобы устанавливать надёжный канал связи между устройствами и передавать по нему данные.

Кроме TCP и IP в модели есть и другие протоколы — например, HTTP, Ethernet, FTP и UDP. Все они решают определённые задачи, связанные с доставкой данных от одного устройства к другому.

Модель TCP/IP очень похожа на сетевую модель OSI — подробнее о ней можно почитать в другой нашей статье.

Научитесь: Профессия Специалист по кибер­безопас­нос­ти с нуля
Узнать больше

В одной из предыдущих статей мы выяснили, что такое как таковой протокол в ИТ и зачем он нужен. Кратко так: 

  • Компьютеры могут общаться между собой.
  • Для этого им нужно договориться о языке общения — это и есть протокол.
  • Протоколы бывают физическими — какие вольты, амперы, радиочастоты и модуляции использовать оборудованию.
  • Протоколы бывают логическими — как понимать сигналы, закодированные в этих вольтах и модуляциях.
  • Существует целый стек протоколов — как многослойный пирог. В фундаменте там вольты и амперы, потом основы языка, потом сложные конструкции языка и на самой верхушке — как должны общаться приложения. Этот стек (или модель) называют OSI — Open Systems Interconnection Model.

Сегодня поговорим о протоколах TCP/IP — именно они отвечают за работу всего интернета и позволяют нам отправлять запросы на сервер в другой стране и получать в ответ гифки, музыку и всё остальное.

Коротко: что такое и зачем нужны TCP/IP

  1. TCP/IP — это названия протоколов, которые лежат в основе интернета. Благодаря им компьютеры обмениваются данными, не мешая друг другу.
  2. Оба протокола отвечают за передачу данных, но IP просто отправляет их в сеть, а TCP ещё следит за тем, чтобы эти данные попали по нужному адресу.
  3. В TCP встроено подтверждение получения, поэтому при хорошей связи данные точно дойдут до получателя.

Что такое TCP/IP

TCP/IP — общее стандартное название двух протоколов, TCP и IP. Они стоят рядом потому, что протокол TCP работает поверх IP, а вместе эти протоколы образуют универсальный стек протоколов передачи данных.

TCP — это протокол управления передачей (Transmission Control Protocol). Его задача — управлять отправкой данных и следить за тем, чтобы они были гарантированно приняты получателем. Именно гарантия получения данных и сделала этот протокол таким востребованным. Про гарантированную доставку расскажем чуть позже.

IP — протокол, который отвечает за адресацию: чтобы нужные данные долетели до нужного компьютера. Его основная задача — логически соединить компьютеры между собой, чтобы можно было отправлять данные от одного к другому. Для этого он выделяет IP-адреса, строит маршруты доставки пакетов, а главное — умеет организовать передачу данных с помощью пакетов. 

Получается так: 

  • IP-протокол знает, ЧТО нужно сделать, чтобы доставить данные от одного компьютера к другому; 
  • а TCP-протокол знает, КАК это сделать и при этом убедиться, что получатель точно получил все свои пакеты.

Что такое TCP/IP и зачем они нужны

Кто за что отвечает в связке TCP/IP

Пакетная передача данных

Когда один компьютер хочет передать что-то другому, то он не отправляет байт за байтом по очереди. Вместо этого он отправляет данные мелкими порциями, а получатель собирает из них исходные данные. Этим как раз занимаются протоколы — разбивают всё на части и склеивает заново, потому что каждый пакет пронумерован.

Пакет может быть размером от 1 до 64 килобайт, но в нём всегда есть несколько обязательных полей — по ним протокол понимает, кому какие данные нужно передать.

Что такое TCP/IP и зачем они нужны

Протокол IP разбивает исходные данные на пронумерованные пакеты
Что такое TCP/IP и зачем они нужны
В каждом пакете: адреса отправителя и получателя, служебная информация, номер пакета и сами данные. Так получатель сможет собрать исходные данные и ответить, что они дошли без потерь

Гарантированная доставка пакетов

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

Если сигнала подтверждения нет, то протокол отправляет этот же пакет данных ещё раз — мало ли что. Если подтверждения нет несколько раз подряд, то протокол выдаёт сообщение об ошибке и закрывает соединение.

Что такое TCP/IP и зачем они нужны

Тут всё прошло удачно: получатель подтвердил доставку пакетов
Что такое TCP/IP и зачем они нужны
Тут получатель не принимает пакеты. Хорошо, что отправитель это вовремя понял

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

Чтобы не было таких задержек, в протоколе предусмотрели кумулятивное и выборочное подтверждение:

  • В кумулятивном получатель подтверждает приём последнего пакета и всех предыдущих.
  • В выборочном — подтверждает диапазон пакетов, которые он получил. Если какого-то пакета нет в подтверждении, отправитель посылает его заново. Это одна из оптимизаций работы протокола, и в TCP таких оптимизаций много — благодаря им у нас шустрый интернет с быстрыми подтверждениями.

По умолчанию используется кумулятивное подтверждение, например, каждых 100 пакетов:

Что такое TCP/IP и зачем они нужны

Пример кумулятивного подтверждения отправки 100 пакетов

И что с того?

Связка протоколов TCP/IP делает так, чтобы мы могли отправить данные куда-то в интернет и они точно дошли. Всё это происходит быстро, незаметно для нас, где-то в глубинах наших компьютеров и телефонов. 

При этом связка TCP/IP — не единственная, которая бывает. Например, есть ещё UDP/IP, которая чаще используется в онлайн-играх и видеосозвонах — там нет подтверждения получения пакетов, просто данные льются без конца. 

Если вы не инженер или не разработчик сетевых систем, вам не нужно в этом разбираться — вы просто пользуетесь этим каждый день. Но зато теперь вы знаете, как это работает. 

Вёрстка:

Кирилл Климентьев

Протоколы — это правила в интернете, по которым устройства с разными операционными системами и программным обеспечением обмениваются данными. С их помощью, например, пользователь Safari на MacBook получает сообщение, отправленное через Chrome на Android.

Чтобы обмениваться данными было удобнее, задачи по их отправке и получению разделены. Создана архитектура «клиент-сервер», где клиент отправляет запрос, а сервер принимает его и возвращает ответ.

Сервер — это специальная программа, или мощный компьютер, его ещё называют хост-системой. Клиент — любое устройство для работы с сайтом, например, ноутбук, смартфон или бортовой компьютер в автомобиле.

Веб-приложение — это клиент-серверное приложение, в котором клиентом выступает браузер. Допустим, на сервере хранится HTML-страница с кодом. Браузер получает файл и показывает этот код как привычную страницу сайта.

Браузер отправляет запрос, а сервер принимает его и возвращает ответ

Браузер отправляет запрос, а сервер принимает его и возвращает ответ

Какие бывают протоколы

Протоколы определяют правила выполнения конкретных задач. Но фронтендерам необязательно знать все существующие протоколы — достаточно разбираться в основных.

Internet Protocol — IP

IP отвечает за поиск компьютеров в сети по их IP-адресам. Ещё он предоставляет стратегию маршрутизации, то есть составляет оптимальный маршрут для передачи данных.

Данные в интернете передаются IP-пакетами. У каждого пакета есть заголовок и данные. В заголовке находятся IP-адреса источника и пункта назначения. Данные — это само содержимое, например, часть веб-страницы.

Работу IP можно сравнить с почтовым отделением: протокол направляет IP-пакеты по интернету так же, как почта рассылает письма по всему миру. При доставке почта использует пункты передачи: письмо из отделения сначала попадает на поезд, потом на грузовик и в конце вручается адресату. В интернете тоже есть «пункты передачи» — их называют маршрутизаторами. Цель маршрутизатора — отправить пакет в пункт назначения по самому короткому пути. Если всё идёт хорошо, пакет прибывает на ближайший к получателю маршрутизатор, который точно знает, куда его отправить. Но бывает и так, что какой-то из маршрутизаторов на пути взломан или вышел из строя, и тогда выбирается другой путь:

Множество соседних путей делает передачу данных более надёжной

Множество соседних путей делает передачу данных более надёжной

DNS

Уникальный IP-адрес есть у каждого домена. Он записывается в виде четырёх чисел от нуля до 255 — например, 74.125.20.113. Введите этот адрес в браузерную строку и посмотрите, на какой сайт вы попали.

DNS связывает IP-адрес с понятным для людей доменным именем, например, 178.79.181.169 превращается в htmlacademy.ru:

Принцип работы DNS похож на поиск и вызов контактов в телефоне. Вряд ли кто-то помнит 1317а друзей — да это и необязательно, ведь они хранятся в списке контактов. Когда мы хотим кому-то позвонить, то просто находим нужное имя и нажимаем кнопку вызова — в этот момент начинается соединение, но не по имени, а по 1317у телефона.

DNS-сервер — это и есть «список всех контактов», то есть IP-адресов, которые там хранятся. Каждому IP-адресу присвоен домен. И когда мы вводим в строке браузера имя домена, то происходит запрос к DNS-серверу — запрашивается IP-адрес.

SSL/TLS

SSL — криптографический протокол шифрования запросов и ответов, он нужен для безопасного перемещения данных по интернету, а TLS — его продвинутая версия. SSL уже почти не используют, но это название было таким популярным, что его до сих пор употребляют, а любой SSL-сертификат у хостинг-компаний — TLS-сертификат.

TCP и UDP

Оба протокола отвечают за передачу данных и работают поверх IP, но с небольшой разницей. TCP доставляет данные без потерь, поэтому его используют для передачи фотографий, сообщений и другой важной информации. А вот UDP не гарантирует доставку, но зато он гораздо быстрее. Его используют, когда скорость важнее надёжности, например, при передаче аудиосообщений или видеотрансляциях.

HTTP и HTTPS

HTTP и HTTPS предназначены для передачи данных и в итоге пользователи могут просматривать веб-страницы. На самом деле HTTPS — это не отдельный протокол, а расширение HTTP. Он безопаснее, так как использует SSL/TLS для шифрования обычных запросов и ответов.

HTTP

HTTP — один из самых используемых протоколов в интернете, поэтому посмотрим подробнее, как он работает.

Протокол работает в формате запрос-ответ с двумя участниками общения:

  • клиент — формирует запросы и обрабатывает ответы;
  • сервер — обрабатывает запросы и формирует ответы.

Клиент делает запрос на сервер для передачи каждого ресурса: файлов HTML, CSS, JavaScript, изображений или видеофайлов. Затем сервер отвечает на запрос, отправляя ресурс.

Представим, что мы создали HTML со следующей разметкой:

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Главная страница</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <header>
    <img src="logo.svg" alt="">
  </header>
</body>
</html>

Это простой HTML-файл, в котором подключены два ресурса: стилевой файл style.css и изображение logo.svg. Браузер запросит три ресурса: index.html, style.css и logo.svg.

Для каждого запроса и ответа открывается своё TCP-соединение. При каждом соединении происходит трёхстороннее «рукопожатие»: клиент и сервер трижды обмениваются пустыми пакетами данных, чтобы удостовериться в существовании друг друга и готовности к работе с данными:

Запрос-ответ выглядит так:

Трёхстороннее «рукопожатие» нужно проводить в каждом TCP-соединении, так как HTTP не запоминает состояния, поэтому ни клиент, ни сервер не могут сохранять информацию между различными запросами. HTTP — один из самых ранних протоколов, и при его создании никто не ожидал, что на веб-странице придётся загружать так много ресурсов.

Такое «рукопожатие» делает загрузку страницы медленнее. Чтобы решить проблему, разработчикам приходится сокращать количество загружаемых ресурсов, например, использовать спрайты или разделять файлы по разным доменам — этот метод называется domain sharding. Такие манипуляции уменьшают количество TCP-соединений, хотя и создают свои трудности.

HTTP/2

HTTP/2 — улучшенная версия HTTP. По данным Can I Use, его поддерживают большинство браузеров.

Главное нововведение этого протокола — одно TCP-соединение на разные запросы, или мультиплексирование:

Как выглядит запрос-ответ в HTTP/2:

Ещё в HTTP/2 появился push-сервер, то есть сервер может отправлять больше ответов на один клиентский запрос. Например, если клиент запрашивает файлы index.html, style.css и logo.svg, то сервер отправит сразу три файла. Без push-сервера клиенту нужно запрашивать каждый файл отдельно

Поэтому многие оптимизации под HTTP при переходе на HTTP/2 уже не нужны. Например, можно отказаться от разделения ресурсов по доменам.

HTTP/3

HTTP/3 — третья версия HTTP, основанная на QUIC — протоколе, который предполагает быстрое подключение к интернету через UDP.

Главное преимущество HTTP/3 — сокращение задержки при установке соединения. QUIC достаточно одного «рукопожатия», чтобы установить безопасный сеанс. А ещё HTTP/3 работает поверх UDP, поэтому скорость доставки данных быстрее, чем у HTTP и HTTP/2 поверх TCP.

Протокол уже получил статус предложенного стандарта, то есть браузеры почти завершили работу над поддержкой протокола. Но пока поддержки недостаточно, чтобы переводить сайт с HTTP/2 на HTTP/3.

WebSockets

В этом протоколе соединение устанавливается гораздо быстрее, чем в HTTP — здесь отправляется «рукопожатие» сразу со всей необходимой информацией для передачи данных. Канал при этом остаётся открытым, пока кто-то из сторон не прервёт его. Это означает, что запросы и ответы будут происходить практически мгновенно. А если сервер получит новые данные, он отправит их клиенту без запроса.

Протокол WebSockets используют там, где важна скорость доставки данных, например, в чатах и мессенджерах, играх, онлайн-трансляциях. Он, скорее всего, не пригодится при разработке простых веб-приложений, небольших CMS или при использовании REST API, где достаточно HTTP-запросов GET, POST, PUT и DELETE.

Зачем разбираться в протоколах и сетях

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

Выбор технологии для приложения

Знание протоколов даёт понимание, какие технологии использовать для определённых задач. Какой протокол выбрать для онлайн-чата с большим количеством пользователей, а какой — для загрузки фотографии пользователя в профиль.

Защита данных

Если знать уязвимости на пути передачи данных, можно предусмотреть и смягчить последствия атак на веб-приложение. Например, создать стратегию защиты данных банковских карт на стороне клиента и на стороне сервера.

Оптимизация приложения под протоколы

Зная особенности протоколов, можно ускорить веб-приложение и не тратить время на ненужную оптимизацию. А ещё появляется понимание, что менять при переходе на другой протокол.

Например, чтобы оптимизировать приложение под HTTP/1, нужно уменьшить количество TCP-соединений. Для этого разработчики сокращают количество файлов: все стили объединяют в styles.css, а все скрипты — в scripts.js. Для HTTP/2 такая оптимизация не нужна, поэтому можно разделить общие CSS и JS-файлы на отдельные и подключать на страницу только необходимые.

Спрайты — оптимизация для протокола HTTP. Их минус в том, что для каждой страницы загружается спрайт с иконками всего веб-приложения, даже если на странице используется всего несколько иконок. Для HTTP/2 можно загружать только те изображения, которые нужны пользователю. При этом необязательно полностью избавляться от спрайтов — можно создать спрайты для компонентов и использовать необходимые на конкретной странице.

Если приложение оптимизировано к HTTP/2, то для перехода на HTTP/3 ничего не нужно делать: все оптимизации подойдут и для HTTP/3.

Прохождение собеседований

Знание протоколов и сетей повышает ценность фронтендера и влияет на его зарплату. Чтобы успешно пройти собеседование на мидла в крупные компании, полезно знать TCP/IP, HTTP/HTTPS, DNS и WebSocket. Ещё нужно хотя бы на базовом уровне знать про безопасность: XSS-атаки и CORS — а разобраться в этой теме без знания протоколов не получится.


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

Материалы по теме

  • Как защитить приложение от хакеров
  • Чем отличаются HTTP-методы GET и POST
  • Протокол HTTP и работа с заголовками

«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.

ТелеграмПодкастБесплатные учебники

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *