# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025, 2026. msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" "POT-Creation-Date: 2026-02-22 15:58+0000\n" "PO-Revision-Date: 2026-03-04 20:01+0000\n" "Last-Translator: Vladlen Popolitov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: YAML Front Matter: description #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1 #, no-wrap msgid "FreeBSD Sockets" msgstr "Сокеты FreeBSD" #. type: YAML Front Matter: title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1 #, no-wrap msgid "Chapter 7. Sockets" msgstr "Глава 7. Сокеты" #. type: Title = #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:16 #, no-wrap msgid "Sockets" msgstr "Сокеты" #. type: Title == #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:54 #, no-wrap msgid "Synopsis" msgstr "Обзор" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:59 msgid "" "BSD sockets take interprocess communications to a new level. It is no " "longer necessary for the communicating processes to run on the same " "machine. They still _can_, but they do not have to." msgstr "" "Сокеты BSD выводят межпроцессное взаимодействие на новый уровень. Теперь " "взаимодействующие процессы не обязательно должны выполняться на одной " "машине. Они всё ещё _могут_, но не обязаны." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:62 msgid "" "Not only do these processes not have to run on the same machine, they do not " "have to run under the same operating system. Thanks to BSD sockets, your " "FreeBSD software can smoothly cooperate with a program running on a " "Macintosh(R), another one running on a Sun(TM) workstation, yet another one " "running under Windows(R) 2000, all connected with an Ethernet-based local " "area network." msgstr "" "Не только эти процессы не обязаны выполняться на одной машине, они также " "могут работать под разными операционными системами. Благодаря BSD-сокетам, " "ваше ПО на FreeBSD может легко взаимодействовать с программой, работающей на " "Macintosh(R), другой — на рабочей станции Sun(TM), и ещё одной — под " "Windows(R) 2000, при этом все они подключены к локальной сети на основе " "Ethernet." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:64 msgid "" "But your software can equally well cooperate with processes running in " "another building, or on another continent, inside a submarine, or a space " "shuttle." msgstr "" "Но ваше программное обеспечение может так же эффективно взаимодействовать с " "процессами, работающими в другом здании, на другом континенте, внутри " "подводной лодки или космического челнока." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:67 msgid "" "It can also cooperate with processes that are not part of a computer (at " "least not in the strict sense of the word), but of such devices as printers, " "digital cameras, medical equipment. Just about anything capable of digital " "communications." msgstr "" "Он также может взаимодействовать с процессами, которые не являются частью " "компьютера (по крайней мере, не в строгом смысле этого слова), а таких " "устройств, как принтеры, цифровые камеры, медицинское оборудование. " "Практически со всем, что способно к цифровой коммуникации." #. type: Title == #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:69 #, no-wrap msgid "Networking and Diversity" msgstr "Сетевое взаимодействие и разнообразие" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:75 msgid "" "We have already hinted on the _diversity_ of networking. Many different " "systems have to talk to each other. And they have to speak the same " "language. They also have to _understand_ the same language the same way." msgstr "" "Мы уже упоминали о _разнообразии_ сетевых технологий. Множество различных " "систем должны взаимодействовать друг с другом. И они должны говорить на " "одном языке. Также они должны _понимать_ этот язык одинаковым образом." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:80 msgid "" "People often think that _body language_ is universal. But it is not. Back " "in my early teens, my father took me to Bulgaria. We were sitting at a " "table in a park in Sofia, when a vendor approached us trying to sell us some " "roasted almonds." msgstr "" "Часто думают, что _язык тела_ универсален. Но это не так. В ранней юности " "отец взял меня с собой в Болгарию. Мы сидели за столиком в парке Софии, " "когда к нам подошел продавец, предлагая купить жареный миндаль." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:83 msgid "" "I had not learned much Bulgarian by then, so, instead of saying no, I shook " "my head from side to side, the \"universal\" body language for _no_. The " "vendor quickly started serving us some almonds." msgstr "" "Я тогда ещё не знал болгарского, поэтому вместо словесного отказа я покачал " "головой из стороны в сторону — это «универсальный» язык тела для обозначения " "_нет_. Продавец тут же начал угощать нас миндалем." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:91 msgid "" "I then remembered I had been told that in Bulgaria shaking your head " "sideways meant _yes_. Quickly, I started nodding my head up and down. The " "vendor noticed, took his almonds, and walked away. To an uninformed " "observer, I did not change the body language: I continued using the language " "of shaking and nodding my head. What changed was the _meaning_ of the body " "language. At first, the vendor and I interpreted the same language as " "having completely different meaning. I had to adjust my own interpretation " "of that language so the vendor would understand." msgstr "" "Затем я вспомнил, что мне говорили, будто в Болгарии покачивание головой из " "стороны в сторону означает _да_. Быстро я начал кивать головой вверх-вниз. " "Продавец заметил, забрал свои орехи и ушёл. Для непосвящённого наблюдателя я " "не изменил язык тела: я продолжал использовать движения головой — " "покачивание и кивание. Изменился _смысл_ языка тела. Сначала продавец и я " "интерпретировали одни и те же жесты как имеющие совершенно разный смысл. Мне " "пришлось скорректировать свою собственную интерпретацию этих жестов, чтобы " "продавец меня понял." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:95 msgid "" "It is the same with computers: The same symbols may have different, even " "outright opposite meaning. Therefore, for two computers to understand each " "other, they must not only agree on the same _language_, but on the same " "_interpretation_ of the language." msgstr "" "То же самое и с компьютерами: одни и те же символы могут иметь разное, даже " "полностью противоположное значение. Поэтому, чтобы два компьютера понимали " "друг друга, они должны договориться не только об одном _языке_, но и об " "одном _толковании_ языка." #. type: Title == #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:97 #, no-wrap msgid "Protocols" msgstr "Протоколы" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:104 msgid "" "While various programming languages tend to have complex syntax and use a " "number of multi-letter reserved words (which makes them easy for the human " "programmer to understand), the languages of data communications tend to be " "very terse. Instead of multi-byte words, they often use individual _bits_. " "There is a very convincing reason for it: While data travels _inside_ your " "computer at speeds approaching the speed of light, it often travels " "considerably slower between two computers." msgstr "" "В то время как различные языки программирования обычно имеют сложный " "синтаксис и используют множество многосимвольных зарезервированных слов (что " "облегчает их понимание для человека-программиста), языки передачи данных, " "как правило, очень лаконичны. Вместо многосимвольных слов они часто " "используют отдельные _биты_. Для этого есть очень убедительная причина: хотя " "данные внутри вашего компьютера передаются со скоростью, близкой к скорости " "света, между двумя компьютерами они часто передаются значительно медленнее." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:106 msgid "" "As the languages used in data communications are so terse, we usually refer " "to them as _protocols_ rather than languages." msgstr "" "Поскольку языки, используемые в передаче данных, настолько лаконичны, мы " "обычно называем их _протоколами_, а не языками." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:111 msgid "" "As data travels from one computer to another, it always uses more than one " "protocol. These protocols are _layered_. The data can be compared to the " "inside of an onion: You have to peel off several layers of \"skin\" to get " "to the data. This is best illustrated with a picture:" msgstr "" "При передаче данных от одного компьютера к другому всегда используется более " "одного протокола. Эти протоколы _располагаются слоями_. Данные можно " "сравнить с внутренней частью лука: необходимо снять несколько слоёв «кожи», " "чтобы добраться до данных. Это лучше всего проиллюстрировано на рисунке:" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:112 #, no-wrap msgid "Protocol Layers" msgstr "Уровни протоколов" #. type: Target for macro image #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:113 #, no-wrap msgid "layers.png" msgstr "layers.png" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:116 msgid "" "In this example, we are trying to get an image from a web page we are " "connected to via an Ethernet." msgstr "" "В этом примере мы пытаемся получить изображение с веб-страницы, к которой " "подключены через Ethernet." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:119 msgid "" "The image consists of raw data, which is simply a sequence of RGB values " "that our software can process, i.e., convert into an image and display on " "our monitor." msgstr "" "Изображение состоит из необработанных данных, которые представляют собой " "просто последовательность значений RGB, которые наше программное обеспечение " "может обработать, т.е. преобразовать в изображение и отобразить на нашем " "мониторе." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:124 msgid "" "Alas, our software has no way of knowing how the raw data is organized: Is " "it a sequence of RGB values, or a sequence of grayscale intensities, or " "perhaps of CMYK encoded colors? Is the data represented by 8-bit quanta, or " "are they 16 bits in size, or perhaps 4 bits? How many rows and columns does " "the image consist of? Should certain pixels be transparent?" msgstr "" "Увы, наше программное обеспечение не может определить, как организованы " "сырые данные: это последовательность значений RGB, последовательность " "интенсивностей в градациях серого или, возможно, цвета в кодировке CMYK? " "Представлены ли данные 8-битными квантами, или они имеют размер 16 бит, а " "может быть, 4 бита? Из скольких строк и столбцов состоит изображение? Должны " "ли определённые пиксели быть прозрачными?" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:126 msgid "I think you get the picture..." msgstr "Я думаю, вы поняли..." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:129 msgid "" "To inform our software how to handle the raw data, it is encoded as a PNG " "file. It could be a GIF, or a JPEG, but it is a PNG." msgstr "" "Чтобы наше программное обеспечение понимало, как обрабатывать сырые данные, " "они кодируются в формате PNG. Это мог бы быть GIF или JPEG, но выбран PNG." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:131 msgid "And PNG is a protocol." msgstr "И PNG — это протокол." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:133 msgid "" "At this point, I can hear some of you yelling, _\"No, it is not! It is a " "file format!\"_" msgstr "" "В этот момент я слышу, как некоторые из вас кричат: _\"Нет, это не так! Это " "формат файла!\"_" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:138 msgid "" "Well, of course it is a file format. But from the perspective of data " "communications, a file format is a protocol: The file structure is a " "_language_, a terse one at that, communicating to our _process_ how the data " "is organized. Ergo, it is a _protocol_." msgstr "" "Ну что ж, конечно, это формат файла. Но с точки зрения передачи данных, " "формат файла — это протокол: структура файла — это _язык_, причем " "лаконичный, сообщающий нашему _процессу_, как организованы данные. " "Следовательно, это _протокол_." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:141 msgid "" "Alas, if all we received was the PNG file, our software would be facing a " "serious problem: How is it supposed to know the data is representing an " "image, as opposed to some text, or perhaps a sound, or what not? Secondly, " "how is it supposed to know the image is in the PNG format as opposed to GIF, " "or JPEG, or some other image format?" msgstr "" "Увы, если бы мы получили только PNG-файл, наше программное обеспечение " "столкнулось бы с серьёзной проблемой: как ему узнать, что данные " "представляют изображение, а не текст, звук или что-то ещё? Во-вторых, как " "ему определить, что изображение сохранено в формате PNG, а не GIF, JPEG или " "каком-либо другом формате изображений?" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:145 msgid "" "To obtain that information, we are using another protocol: HTTP. This " "protocol can tell us exactly that the data represents an image, and that it " "uses the PNG protocol. It can also tell us some other things, but let us " "stay focused on protocol layers here." msgstr "" "Для получения этой информации мы используем другой протокол: HTTP. Этот " "протокол может точно сообщить нам, что данные представляют изображение и " "используют протокол PNG. Он также может сообщить некоторые другие сведения, " "но давайте сосредоточимся на уровнях протоколов здесь." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:148 msgid "" "So, now we have some data wrapped in the PNG protocol, wrapped in the HTTP " "protocol. How did we get it from the server?" msgstr "" "Итак, теперь у нас есть некоторые данные, упакованные в протокол PNG, " "который в свою очередь упакован в протокол HTTP. Как мы получили их с " "сервера?" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:152 msgid "" "By using TCP/IP over Ethernet, that is how. Indeed, that is three more " "protocols. Instead of continuing inside out, I am now going to talk about " "Ethernet, simply because it is easier to explain the rest that way." msgstr "" "Используя TCP/IP поверх Ethernet, вот как. Действительно, это ещё три " "протокола. Вместо того чтобы продолжать изнутри наружу, я теперь расскажу " "про Ethernet, просто потому что так проще объяснить остальное." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:156 msgid "" "Ethernet is an interesting system of connecting computers in a _local area " "network_ (LAN). Each computer has a _network interface card_ (NIC), which " "has a unique 48-bit ID called its _address_. No two Ethernet NICs in the " "world have the same address." msgstr "" "Ethernet — это интересная система соединения компьютеров в _локальной сети_ " "(LAN). У каждого компьютера есть _карта сетевого интерфейса_ (NIC — Network " "Interface Card) с уникальным 48-битным идентификатором, называемым " "_адресом_. Не существует двух сетевых интерфейсов Ethernet в мире с " "одинаковым адресом." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:162 msgid "" "These NICs are all connected with each other. Whenever one computer wants " "to communicate with another in the same Ethernet LAN, it sends a message " "over the network. Every NIC sees the message. But as part of the Ethernet " "_protocol_, the data contains the address of the destination NIC (among " "other things). So, only one of all the network interface cards will pay " "attention to it, the rest will ignore it." msgstr "" "Эти сетевые карты соединены между собой. Когда один компьютер хочет " "связаться с другим в той же локальной сети Ethernet, он отправляет сообщение " "по сети. Каждая сетевая карта видит это сообщение. Однако, согласно " "_протоколу_ Ethernet, данные содержат адрес сетевой карты назначения (среди " "прочего). Таким образом, только одна из всех сетевых карт обратит на него " "внимание, остальные проигнорируют его." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:166 msgid "" "But not all computers are connected to the same network. Just because we " "have received the data over our Ethernet does not mean it originated in our " "own local area network. It could have come to us from some other network " "(which may not even be Ethernet based) connected with our own network via " "the Internet." msgstr "" "Но не все компьютеры подключены к одной сети. Тот факт, что мы получили " "данные через наш Ethernet, не означает, что они возникли в нашей локальной " "сети. Они могли попасть к нам из другой сети (которая может быть даже не на " "основе Ethernet), соединённой с нашей сетью через Интернет." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:170 msgid "" "All data is transferred over the Internet using IP, which stands for " "_Internet Protocol_. Its basic role is to let us know where in the world " "the data has arrived from, and where it is supposed to go to. It does not " "_guarantee_ we will receive the data, only that we will know where it came " "from _if_ we do receive it." msgstr "" "Все данные передаются через Интернет с использованием IP, что означает " "_Internet Protocol_. Его основная роль — сообщать нам, откуда в мире пришли " "данные и куда они должны быть направлены. Он не _гарантирует_, что мы " "получим данные, только что мы узнаем, откуда они пришли, _если_ мы их " "получим." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:173 msgid "" "Even if we do receive the data, IP does not guarantee we will receive " "various chunks of data in the same order the other computer has sent it to " "us. So, we can receive the center of our image before we receive the upper " "left corner and after the lower right, for example." msgstr "" "Даже если мы получим данные, IP не гарантирует, что различные фрагменты " "данных придут в том же порядке, в котором их отправил другой компьютер. " "Например, мы можем получить центр нашего изображения до того, как получим " "его верхний левый угол, а после — нижний правый." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:175 msgid "" "It is TCP (_Transmission Control Protocol_) that asks the sender to resend " "any lost data and that places it all into the proper order." msgstr "" "Это TCP (_Transmission Control Protocol_), который запрашивает у отправителя " "повторную отправку потерянных данных и располагает их в правильном порядке." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:178 msgid "" "All in all, it took _five_ different protocols for one computer to " "communicate to another what an image looks like. We received the data " "wrapped into the PNG protocol, which was wrapped into the HTTP protocol, " "which was wrapped into the TCP protocol, which was wrapped into the IP " "protocol, which was wrapped into the Ethernet protocol." msgstr "" "В итоге потребовалось _пять_ различных протоколов, чтобы один компьютер мог " "сообщить другому, как выглядит изображение. Мы получили данные, упакованные " "в протокол PNG, который был упакован в протокол HTTP, который был упакован в " "протокол TCP, который был упакован в протокол IP, который был упакован в " "протокол Ethernet." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:182 msgid "" "Oh, and by the way, there probably were several other protocols involved " "somewhere on the way. For example, if our LAN was connected to the Internet " "through a dial-up call, it used the PPP protocol over the modem which used " "one (or several) of the various modem protocols, et cetera, et cetera, et " "cetera..." msgstr "" "О, и кстати, вероятно, на пути были задействованы и несколько других " "протоколов. Например, если наша локальная сеть была подключена к Интернету " "через дозвон, то использовался протокол PPP над модемом, который, в свою " "очередь, использовал один (или несколько) из различных модемных протоколов, " "и так далее, и так далее, и так далее..." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:184 msgid "" "As a developer you should be asking by now, _\"How am I supposed to handle " "it all?\"_" msgstr "" "Как разработчик, вы уже должны задаваться вопросом: _\"Как я должен со всем " "этим справляться?\"_" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:189 msgid "" "Luckily for you, you are _not_ supposed to handle it all. You _are_ " "supposed to handle some of it, but not all of it. Specifically, you need " "not worry about the physical connection (in our case Ethernet and possibly " "PPP, etc). Nor do you need to handle the Internet Protocol, or the " "Transmission Control Protocol." msgstr "" "К счастью для вас, вам _не_ нужно разбираться во всём этом. Вам _придётся_ " "разобраться в некоторой части, но не во всей. В частности, вам не нужно " "беспокоиться о физическом подключении (в нашем случае Ethernet и, возможно, " "PPP и т.д.). Также вам не нужно разбираться с протоколом IP или протоколом " "TCP." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:192 msgid "" "In other words, you do not have to do anything to receive the data from the " "other computer. Well, you do have to _ask_ for it, but that is almost as " "simple as opening a file." msgstr "" "Другими словами, вам не нужно ничего делать, чтобы получить данные с другого " "компьютера. Ну, разве что _попросить_ их, но это почти так же просто, как " "открыть файл." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:195 msgid "" "Once you have received the data, it is up to you to figure out what to do " "with it. In our case, you would need to understand the HTTP protocol and " "the PNG file structure." msgstr "" "Получив данные, вам предстоит решить, что с ними делать. В нашем случае " "потребуется понимание протокола HTTP и структуры файла PNG." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:199 msgid "" "To use an analogy, all the internetworking protocols become a gray area: Not " "so much because we do not understand how it works, but because we are no " "longer concerned about it. The sockets interface takes care of this gray " "area for us:" msgstr "" "Используя аналогию, все межсетевые протоколы становятся серой зоной: не " "столько потому, что мы не понимаем, как они работают, а потому, что нас это " "больше не беспокоит. Интерфейс сокетов берёт на себя заботу об этой серой " "зоне:" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:200 #, no-wrap msgid "Sockets Covered Protocol Layers" msgstr "Уровни протоколов, покрываемые сокетами" #. type: Target for macro image #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:201 #, no-wrap msgid "slayers.png" msgstr "slayers.png" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:204 msgid "" "We only need to understand any protocols that tell us how to _interpret the " "data_, not how to _receive_ it from another process, nor how to _send_ it to " "another process." msgstr "" "Нам нужно понимать только те протоколы, которые говорят нам, как " "_интерпретировать данные_, а не как _получать_ их от другого процесса или " "как _передавать_ их другому процессу." #. type: Title == #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:206 #, no-wrap msgid "The Sockets Model" msgstr "Модель сокетов" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:211 msgid "" "BSD sockets are built on the basic UNIX(R) model: _Everything is a file._ In " "our example, then, sockets would let us receive an _HTTP file_, so to " "speak. It would then be up to us to extract the _PNG file_ from it." msgstr "" "Сокеты BSD построены по базовой модели UNIX(R): _Все является файлом._ Таким " "образом, в нашем примере сокеты позволят нам получить, образно говоря, _HTTP-" "файл_. Затем нам предстоит извлечь из него _PNG-файл_." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:214 msgid "" "Due to the complexity of internetworking, we cannot just use the `open` " "system call, or the `open()` C function. Instead, we need to take several " "steps to \"opening\" a socket." msgstr "" "Из-за сложности межсетевого взаимодействия мы не можем просто использовать " "системный вызов `open` или функцию `open()` в языке C. Вместо этого " "необходимо выполнить несколько шагов для \"открытия\" сокета." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:217 msgid "" "Once we do, however, we can start treating the _socket_ the same way we " "treat any _file descriptor_: We can `read` from it, `write` to it, `pipe` " "it, and, eventually, `close` it." msgstr "" "Однако, как только мы это сделаем, мы можем начать обращаться с _сокетом_ " "так же, как и с любым _файловым дескриптором_: мы можем `читать` из него, " "`писать` в него, передавать его через `канал` и, в конечном итоге, " "`закрывать` его." #. type: Title == #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:219 #, no-wrap msgid "Essential Socket Functions" msgstr "Основные функции сокетов" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:223 msgid "" "While FreeBSD offers different functions to work with sockets, we only " "_need_ four to \"open\" a socket. And in some cases we only need two." msgstr "" "В то время как FreeBSD предлагает различные функции для работы с сокетами, " "нам _требуется_ только четыре, чтобы \"открыть\" сокет. А в некоторых " "случаях достаточно двух." #. type: Title === #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:225 #, no-wrap msgid "The Client-Server Difference" msgstr "Разница между клиентом и сервером" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:228 msgid "" "Typically, one of the ends of a socket-based data communication is a " "_server_, the other is a _client_." msgstr "" "Обычно одним из концов связи на основе сокетов является _сервер_, а другой — " "_клиент_." #. type: Title ==== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:230 #, no-wrap msgid "The Common Elements" msgstr "Общие элементы" #. type: Title ===== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:233 #, no-wrap msgid "`socket`" msgstr "`socket`" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:237 msgid "" "The one function used by both, clients and servers, is man:socket[2]. It is " "declared this way:" msgstr "" "Функция, используемая как клиентами, так и серверами, это man:socket[2]. Она " "объявляется следующим образом:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:241 #, no-wrap msgid "int socket(int domain, int type, int protocol);\n" msgstr "int socket(int domain, int type, int protocol);\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:246 msgid "" "The return value is of the same type as that of `open`, an integer. FreeBSD " "allocates its value from the same pool as that of file handles. That is " "what allows sockets to be treated the same way as files." msgstr "" "Возвращаемое значение имеет тот же тип, что и у `open`, целое число. FreeBSD " "выделяет его значение из того же пула, что и дескрипторы файлов. Это " "позволяет обрабатывать сокеты так же, как файлы." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:250 msgid "" "The `domain` argument tells the system what _protocol family_ you want it to " "use. Many of them exist, some are vendor specific, others are very common. " "They are declared in [.filename]#sys/socket.h#." msgstr "" "Аргумент `domain` указывает системе, какое _семейство протоколов_ следует " "использовать. Существует множество семейств, некоторые из них специфичны для " "определённых поставщиков, другие широко распространены. Они объявлены в [." "filename]#sys/socket.h#." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:252 msgid "Use `PF_INET` for UDP, TCP and other Internet protocols (IPv4)." msgstr "" "Используйте `PF_INET` для UDP, TCP и других интернет-протоколов (IPv4)." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:256 msgid "" "Five values are defined for the `type` argument, again, in [.filename]#sys/" "socket.h#. All of them start with \"`SOCK_`\". The most common one is " "`SOCK_STREAM`, which tells the system you are asking for a _reliable stream " "delivery service_ (which is TCP when used with `PF_INET`)." msgstr "" "Для аргумента `type` определено пять значений, также указанных в [." "filename]#sys/socket.h#. Все они начинаются с \"`SOCK_`\". Наиболее " "распространённое — `SOCK_STREAM`, которое указывает системе, что " "запрашивается _надёжный сервис потоковой доставки_ (это TCP при " "использовании с `PF_INET`)." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:258 msgid "" "If you asked for `SOCK_DGRAM`, you would be requesting a _connectionless " "datagram delivery service_ (in our case, UDP)." msgstr "" "Если бы вы запросили `SOCK_DGRAM`, вы бы запросили _сервис доставки " "датаграмм без установления соединения_ (в нашем случае, UDP)." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:260 msgid "" "If you wanted to be in charge of the low-level protocols (such as IP), or " "even network interfaces (e.g., the Ethernet), you would need to specify " "`SOCK_RAW`." msgstr "" "Если вы хотите управлять низкоуровневыми протоколами (такими как IP) или " "даже сетевыми интерфейсами (например, Ethernet), вам потребуется указать " "`SOCK_RAW`." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:263 msgid "" "Finally, the `protocol` argument depends on the previous two arguments, and " "is not always meaningful. In that case, use `0` for its value." msgstr "" "Наконец, аргумент `protocol` зависит от двух предыдущих аргументов и не " "всегда имеет смысл. В таком случае используйте значение `0`." #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:265 #, no-wrap msgid "The Unconnected Socket" msgstr "Неподключенный сокет" #. type: delimited block = 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:269 msgid "" "Nowhere, in the `socket` function have we specified to what other system we " "should be connected. Our newly created socket remains _unconnected_." msgstr "" "Нигде в функции `socket` мы не указали, к какой другой системе должны быть " "подключены. Наш только что созданный сокет остаётся _неподключённым_." #. type: delimited block = 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:272 msgid "" "This is on purpose: To use a telephone analogy, we have just attached a " "modem to the phone line. We have neither told the modem to make a call, nor " "to answer if the phone rings." msgstr "" "Это сделано намеренно: если проводить аналогию с телефоном, мы только что " "подключили модем к телефонной линии. Мы не сказали модему совершить звонок " "или ответить, если телефон зазвонит." #. type: Title ===== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:275 #, no-wrap msgid "`sockaddr`" msgstr "`sockaddr`" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:280 msgid "" "Various functions of the sockets family expect the address of (or pointer " "to, to use C terminology) a small area of the memory. The various C " "declarations in the [.filename]#sys/socket.h# refer to it as `struct " "sockaddr`. This structure is declared in the same file:" msgstr "" "Различные функции семейства сокетов ожидают адрес (или указатель, если " "использовать терминологию языка C) небольшой области памяти. Различные " "объявления на языке C в файле [.filename]#sys/socket.h# ссылаются на неё как " "на `struct sockaddr`. Эта структура объявлена в том же файле:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:293 #, no-wrap msgid "" "/*\n" " * Structure used by kernel to store most\n" " * addresses.\n" " */\n" "struct sockaddr {\n" "\tunsigned char\tsa_len;\t\t/* total length */\n" "\tsa_family_t\tsa_family;\t/* address family */\n" "\tchar\t\tsa_data[14];\t/* actually longer; address value */\n" "};\n" "#define\tSOCK_MAXADDRLEN\t255\t\t/* longest possible addresses */\n" msgstr "" "/*\n" " * Structure used by kernel to store most\n" " * addresses.\n" " */\n" "struct sockaddr {\n" "\tunsigned char\tsa_len;\t\t/* total length */\n" "\tsa_family_t\tsa_family;\t/* address family */\n" "\tchar\t\tsa_data[14];\t/* actually longer; address value */\n" "};\n" "#define\tSOCK_MAXADDRLEN\t255\t\t/* longest possible addresses */\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:297 msgid "" "Please note the _vagueness_ with which the `sa_data` field is declared, just " "as an array of `14` bytes, with the comment hinting there can be more than " "`14` of them." msgstr "" "Обратите внимание на _неопределённость_, с которой объявлено поле `sa_data` " "— просто как массив из `14` байт, с комментарием, намекающим, что их может " "быть больше `14`." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:300 msgid "" "This vagueness is quite deliberate. Sockets is a very powerful interface. " "While most people perhaps think of it as nothing more than the Internet " "interface-and most applications probably use it for that nowadays-sockets " "can be used for just about _any_ kind of interprocess communications, of " "which the Internet (or, more precisely, IP) is only one." msgstr "" "Эта неопределённость вполне преднамеренна. Сокеты — это очень мощный " "интерфейс. Хотя большинство людей, возможно, считают их не более чем " "интерфейсом для Интернета — и большинство приложений, вероятно, используют " "их именно для этого в наши дни — сокеты могут быть использованы практически " "для _любого_ вида межпроцессного взаимодействия, из которых Интернет (или, " "точнее, IP) — лишь один из них." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:303 msgid "" "The [.filename]#sys/socket.h# refers to the various types of protocols " "sockets will handle as _address families_, and lists them right before the " "definition of `sockaddr`:" msgstr "" "[.filename]#sys/socket.h# ссылается на различные типы протоколов, с которыми " "работают сокеты, как на _семейства адресов_, и перечисляет их " "непосредственно перед определением `sockaddr`:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:352 #, no-wrap msgid "" "/*\n" " * Address families.\n" " */\n" "#define\tAF_UNSPEC\t0\t\t/* unspecified */\n" "#define\tAF_LOCAL\t1\t\t/* local to host (pipes, portals) */\n" "#define\tAF_UNIX\t\tAF_LOCAL\t/* backward compatibility */\n" "#define\tAF_INET\t\t2\t\t/* internetwork: UDP, TCP, etc. */\n" "#define\tAF_IMPLINK\t3\t\t/* arpanet imp addresses */\n" "#define\tAF_PUP\t\t4\t\t/* pup protocols: e.g. BSP */\n" "#define\tAF_CHAOS\t5\t\t/* mit CHAOS protocols */\n" "#define\tAF_NS\t\t6\t\t/* XEROX NS protocols */\n" "#define\tAF_ISO\t\t7\t\t/* ISO protocols */\n" "#define\tAF_OSI\t\tAF_ISO\n" "#define\tAF_ECMA\t\t8\t\t/* European computer manufacturers */\n" "#define\tAF_DATAKIT\t9\t\t/* datakit protocols */\n" "#define\tAF_CCITT\t10\t\t/* CCITT protocols, X.25 etc */\n" "#define\tAF_SNA\t\t11\t\t/* IBM SNA */\n" "#define AF_DECnet\t12\t\t/* DECnet */\n" "#define AF_DLI\t\t13\t\t/* DEC Direct data link interface */\n" "#define AF_LAT\t\t14\t\t/* LAT */\n" "#define\tAF_HYLINK\t15\t\t/* NSC Hyperchannel */\n" "#define\tAF_APPLETALK\t16\t\t/* Apple Talk */\n" "#define\tAF_ROUTE\t17\t\t/* Internal Routing Protocol */\n" "#define\tAF_LINK\t\t18\t\t/* Link layer interface */\n" "#define\tpseudo_AF_XTP\t19\t\t/* eXpress Transfer Protocol (no AF) */\n" "#define\tAF_COIP\t\t20\t\t/* connection-oriented IP, aka ST II */\n" "#define\tAF_CNT\t\t21\t\t/* Computer Network Technology */\n" "#define pseudo_AF_RTIP\t22\t\t/* Help Identify RTIP packets */\n" "#define\tAF_IPX\t\t23\t\t/* Novell Internet Protocol */\n" "#define\tAF_SIP\t\t24\t\t/* Simple Internet Protocol */\n" "#define\tpseudo_AF_PIP\t25\t\t/* Help Identify PIP packets */\n" "#define\tAF_ISDN\t\t26\t\t/* Integrated Services Digital Network*/\n" "#define\tAF_E164\t\tAF_ISDN\t\t/* CCITT E.164 recommendation */\n" "#define\tpseudo_AF_KEY\t27\t\t/* Internal key-management function */\n" "#define\tAF_INET6\t28\t\t/* IPv6 */\n" "#define\tAF_NATM\t\t29\t\t/* native ATM access */\n" "#define\tAF_ATM\t\t30\t\t/* ATM */\n" "#define pseudo_AF_HDRCMPLT 31\t\t/* Used by BPF to not rewrite headers\n" "\t\t\t\t\t * in interface output routine\n" "\t\t\t\t\t */\n" "#define\tAF_NETGRAPH\t32\t\t/* Netgraph sockets */\n" "#define\tAF_SLOW\t\t33\t\t/* 802.3ad slow protocol */\n" "#define\tAF_SCLUSTER\t34\t\t/* Sitara cluster protocol */\n" "#define\tAF_ARP\t\t35\n" "#define\tAF_BLUETOOTH\t36\t\t/* Bluetooth sockets */\n" "#define\tAF_MAX\t\t37\n" msgstr "" "/*\n" " * Address families.\n" " */\n" "#define\tAF_UNSPEC\t0\t\t/* unspecified */\n" "#define\tAF_LOCAL\t1\t\t/* local to host (pipes, portals) */\n" "#define\tAF_UNIX\t\tAF_LOCAL\t/* backward compatibility */\n" "#define\tAF_INET\t\t2\t\t/* internetwork: UDP, TCP, etc. */\n" "#define\tAF_IMPLINK\t3\t\t/* arpanet imp addresses */\n" "#define\tAF_PUP\t\t4\t\t/* pup protocols: e.g. BSP */\n" "#define\tAF_CHAOS\t5\t\t/* mit CHAOS protocols */\n" "#define\tAF_NS\t\t6\t\t/* XEROX NS protocols */\n" "#define\tAF_ISO\t\t7\t\t/* ISO protocols */\n" "#define\tAF_OSI\t\tAF_ISO\n" "#define\tAF_ECMA\t\t8\t\t/* European computer manufacturers */\n" "#define\tAF_DATAKIT\t9\t\t/* datakit protocols */\n" "#define\tAF_CCITT\t10\t\t/* CCITT protocols, X.25 etc */\n" "#define\tAF_SNA\t\t11\t\t/* IBM SNA */\n" "#define AF_DECnet\t12\t\t/* DECnet */\n" "#define AF_DLI\t\t13\t\t/* DEC Direct data link interface */\n" "#define AF_LAT\t\t14\t\t/* LAT */\n" "#define\tAF_HYLINK\t15\t\t/* NSC Hyperchannel */\n" "#define\tAF_APPLETALK\t16\t\t/* Apple Talk */\n" "#define\tAF_ROUTE\t17\t\t/* Internal Routing Protocol */\n" "#define\tAF_LINK\t\t18\t\t/* Link layer interface */\n" "#define\tpseudo_AF_XTP\t19\t\t/* eXpress Transfer Protocol (no AF) */\n" "#define\tAF_COIP\t\t20\t\t/* connection-oriented IP, aka ST II */\n" "#define\tAF_CNT\t\t21\t\t/* Computer Network Technology */\n" "#define pseudo_AF_RTIP\t22\t\t/* Help Identify RTIP packets */\n" "#define\tAF_IPX\t\t23\t\t/* Novell Internet Protocol */\n" "#define\tAF_SIP\t\t24\t\t/* Simple Internet Protocol */\n" "#define\tpseudo_AF_PIP\t25\t\t/* Help Identify PIP packets */\n" "#define\tAF_ISDN\t\t26\t\t/* Integrated Services Digital Network*/\n" "#define\tAF_E164\t\tAF_ISDN\t\t/* CCITT E.164 recommendation */\n" "#define\tpseudo_AF_KEY\t27\t\t/* Internal key-management function */\n" "#define\tAF_INET6\t28\t\t/* IPv6 */\n" "#define\tAF_NATM\t\t29\t\t/* native ATM access */\n" "#define\tAF_ATM\t\t30\t\t/* ATM */\n" "#define pseudo_AF_HDRCMPLT 31\t\t/* Used by BPF to not rewrite headers\n" "\t\t\t\t\t * in interface output routine\n" "\t\t\t\t\t */\n" "#define\tAF_NETGRAPH\t32\t\t/* Netgraph sockets */\n" "#define\tAF_SLOW\t\t33\t\t/* 802.3ad slow protocol */\n" "#define\tAF_SCLUSTER\t34\t\t/* Sitara cluster protocol */\n" "#define\tAF_ARP\t\t35\n" "#define\tAF_BLUETOOTH\t36\t\t/* Bluetooth sockets */\n" "#define\tAF_MAX\t\t37\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:356 msgid "The one used for IP is AF_INET. It is a symbol for the constant `2`." msgstr "Используемый для IP — это AF_INET. Это символ для константы `2`." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:358 msgid "" "It is the _address family_ listed in the `sa_family` field of `sockaddr` " "that decides how exactly the vaguely named bytes of `sa_data` will be used." msgstr "" "Это _семейство адресов_, указанное в поле `sa_family` структуры `sockaddr`, " "определяет, как именно будут использоваться нечетко названные байты " "`sa_data`." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:360 msgid "" "Specifically, whenever the _address family_ is AF_INET, we can use `struct " "sockaddr_in` found in [.filename]#netinet/in.h#, wherever `sockaddr` is " "expected:" msgstr "" "В частности, когда _семейство адресов_ — AF_INET, можно использовать `struct " "sockaddr_in` из [.filename]#netinet/in.h# везде, где ожидается `sockaddr`:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:373 #, no-wrap msgid "" "/*\n" " * Socket address, internet style.\n" " */\n" "struct sockaddr_in {\n" "\tuint8_t\t\tsin_len;\n" "\tsa_family_t\tsin_family;\n" "\tin_port_t\tsin_port;\n" "\tstruct\tin_addr sin_addr;\n" "\tchar\tsin_zero[8];\n" "};\n" msgstr "" "/*\n" " * Socket address, internet style.\n" " */\n" "struct sockaddr_in {\n" "\tuint8_t\t\tsin_len;\n" "\tsa_family_t\tsin_family;\n" "\tin_port_t\tsin_port;\n" "\tstruct\tin_addr sin_addr;\n" "\tchar\tsin_zero[8];\n" "};\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:376 msgid "We can visualize its organization this way:" msgstr "Мы можем визуализировать его организацию следующим образом:" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:377 #, no-wrap msgid "sockaddr_in structure" msgstr "Структура `sockaddr_in`" #. type: Target for macro image #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:378 #, no-wrap msgid "sain.png" msgstr "sain.png" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:381 msgid "" "The three important fields are `sin_family`, which is byte 1 of the " "structure, `sin_port`, a 16-bit value found in bytes 2 and 3, and " "`sin_addr`, a 32-bit integer representation of the IP address, stored in " "bytes 4-7." msgstr "" "Три важных поля — это `sin_family`, которое находится в байте 1 структуры, " "`sin_port`, 16-битное значение, расположенное в байтах 2 и 3, и `sin_addr`, " "32-битное целочисленное представление IP-адреса, хранящееся в байтах 4–7." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:387 msgid "" "Now, let us try to fill it out. Let us assume we are trying to write a " "client for the _daytime_ protocol, which simply states that its server will " "write a text string representing the current date and time to port 13. We " "want to use TCP/IP, so we need to specify `AF_INET` in the address family " "field. `AF_INET` is defined as `2`. Let us use the IP address of " "`132.163.96.1`, which is the time server of US federal government (`time." "nist.gov`)." msgstr "" "Теперь попробуем заполнить его. Предположим, мы пытаемся написать клиент для " "протокола _daytime_, который просто указывает, что его сервер записывает " "текстовую строку с текущей датой и временем в порт 13. Мы хотим использовать " "TCP/IP, поэтому нам нужно указать `AF_INET` в поле семейства адресов. " "`AF_INET` определен как `2`. Давайте используем IP-адрес `132.163.96.1`, " "который является сервером времени федерального правительства США (`time.nist." "gov`)." #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:388 #, no-wrap msgid "Specific example of sockaddr_in" msgstr "Конкретный пример sockaddr_in" #. type: Target for macro image #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:389 #, no-wrap msgid "sainfill.png" msgstr "sainfill.png" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:392 msgid "" "By the way the `sin_addr` field is declared as being of the `struct in_addr` " "type, which is defined in [.filename]#netinet/in.h#:" msgstr "" "Кстати, поле `sin_addr` объявлено как имеющее тип `struct in_addr`, который " "определён в [.filename]#netinet/in.h#:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:401 #, no-wrap msgid "" "/*\n" " * Internet address (a structure for historical reasons)\n" " */\n" "struct in_addr {\n" "\tin_addr_t s_addr;\n" "};\n" msgstr "" "/*\n" " * Internet address (a structure for historical reasons)\n" " */\n" "struct in_addr {\n" "\tin_addr_t s_addr;\n" "};\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:404 msgid "In addition, `in_addr_t` is a 32-bit integer." msgstr "В дополнение, `in_addr_t` является 32-битным целым числом." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:406 msgid "" "The `132.163.96.1` is just a convenient notation of expressing a 32-bit " "integer by listing all of its 8-bit bytes, starting with the _most " "significant_ one." msgstr "" "`132.163.96.1` — это просто удобная форма записи 32-битного целого числа, в " "которой перечисляются все его 8-битные байты, начиная с _старшего_." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:410 msgid "" "So far, we have viewed `sockaddr` as an abstraction. Our computer does not " "store `short` integers as a single 16-bit entity, but as a sequence of 2 " "bytes. Similarly, it stores 32-bit integers as a sequence of 4 bytes." msgstr "" "До сих пор мы рассматривали `sockaddr` как абстракцию. Наш компьютер не " "хранит `short` целые числа как единую 16-битную сущность, а как " "последовательность 2 байт. Аналогично, он хранит 32-битные целые числа как " "последовательность 4 байт." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:412 msgid "Suppose we coded something like this:" msgstr "Предположим, мы написали что-то вроде этого:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:418 #, no-wrap msgid "" "sa.sin_family = AF_INET;\n" "sa.sin_port = 13;\n" "sa.sin_addr.s_addr = (((((132 << 8) | 163) << 8) | 96) << 8) | 1;\n" msgstr "" "sa.sin_family = AF_INET;\n" "sa.sin_port = 13;\n" "sa.sin_addr.s_addr = (((((132 << 8) | 163) << 8) | 96) << 8) | 1;\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:421 msgid "What would the result look like?" msgstr "Как будет выглядеть результат?" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:424 msgid "" "Well, that depends, of course. On a Pentium(R), or other x86, based " "computer, it would look like this:" msgstr "" "Ну, это, конечно, зависит от многого. На компьютере с процессором Pentium(R) " "или другим на базе x86 это будет выглядеть так:" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:425 #, no-wrap msgid "sockaddr_in on an Intel system" msgstr "`sockaddr_in` в системе с архитектурой Intel" #. type: Target for macro image #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:426 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:472 #, no-wrap msgid "sainlsb.png" msgstr "sainlsb.png" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:429 msgid "On a different system, it might look like this:" msgstr "На другой системе это может выглядеть так:" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:430 #, no-wrap msgid "sockaddr_in on an MSB system" msgstr "`sockaddr_in` в системе с порядком байтов от старшего к младшему" #. type: Target for macro image #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:431 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:477 #, no-wrap msgid "sainmsb.png" msgstr "sainmsb.png" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:435 msgid "" "And on a PDP it might look different yet. But the above two are the most " "common ways in use today." msgstr "" "И на PDP это может выглядеть иначе. Однако два приведённых выше варианта " "являются наиболее распространёнными на сегодняшний день." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:439 msgid "" "Ordinarily, wanting to write portable code, programmers pretend that these " "differences do not exist. And they get away with it (except when they code " "in assembly language). Alas, you cannot get away with it that easily when " "coding for sockets." msgstr "" "Обычно, стремясь писать переносимый код, программисты делают вид, что этих " "различий не существует. И им это сходит с рук (за исключением случаев, когда " "они пишут на ассемблере). Увы, при программировании сокетов так легко " "отделаться не получится." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:441 msgid "Why?" msgstr "Почему?" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:443 msgid "" "Because when communicating with another computer, you usually do not know " "whether it stores data _most significant byte_ (MSB) or _least significant " "byte_ (LSB) first." msgstr "" "Потому что при обмене данными с другим компьютером вы обычно не знаете, " "хранит ли он данные, начиная со _старшего байта_ (MSB) или с _младшего " "байта_ (LSB)." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:445 msgid "You might be wondering, _\"So, will sockets not handle it for me?\"_" msgstr "" "Вы можете задаться вопросом: _\"Значит, сокеты не будут это делать за меня?" "\"_" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:447 msgid "It will not." msgstr "Не будут." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:450 msgid "" "While that answer may surprise you at first, remember that the general " "sockets interface only understands the `sa_len` and `sa_family` fields of " "the `sockaddr` structure. You do not have to worry about the byte order " "there (of course, on FreeBSD `sa_family` is only 1 byte anyway, but many " "other UNIX(R) systems do not have `sa_len` and use 2 bytes for `sa_family`, " "and expect the data in whatever order is native to the computer)." msgstr "" "Хотя этот ответ может сначала вас удивить, помните, что общий интерфейс " "сокетов понимает только поля `sa_len` и `sa_family` структуры `sockaddr`. " "Вам не нужно беспокоиться о порядке байтов (конечно, в FreeBSD `sa_family` " "занимает всего 1 байт, но многие другие UNIX(R)-системы не имеют `sa_len` и " "используют 2 байта для `sa_family`, ожидая данные в том порядке, который " "является родным для компьютера)." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:453 msgid "" "But the rest of the data is just `sa_data[14]` as far as sockets goes. " "Depending on the _address family_, sockets just forwards that data to its " "destination." msgstr "" "Но остальные данные — это просто `sa_data[14]` с точки зрения сокетов. В " "зависимости от _семейства адресов_ сокеты просто передают эти данные по " "назначению." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:458 msgid "" "Indeed, when we enter a port number, it is because we want the other " "computer to know what service we are asking for. And, when we are the " "server, we read the port number so we know what service the other computer " "is expecting from us. Either way, sockets only has to forward the port " "number as data. It does not interpret it in any way." msgstr "" "Действительно, когда мы указываем номер порта, это делается для того, чтобы " "другая компьютерная система знала, какую службу мы запрашиваем. И, когда мы " "выступаем в роли сервера, мы считываем номер порта, чтобы понять, какую " "службу ожидает от нас другая система. В любом случае, сокетам нужно лишь " "передать номер порта в качестве данных. Они никак его не интерпретируют." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:461 msgid "" "Similarly, we enter the IP address to tell everyone on the way where to send " "our data to. Sockets, again, only forwards it as data." msgstr "" "Аналогично, мы указываем IP-адрес, чтобы сообщить всем на пути, куда " "отправлять наши данные. Сокеты, опять же, просто пересылают их как данные." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:463 msgid "" "That is why, we (the _programmers_, not the _sockets_) have to distinguish " "between the byte order used by our computer and a conventional byte order to " "send the data in to the other computer." msgstr "" "Вот почему мы (программисты, а не сокеты) должны различать порядок байтов, " "используемый нашим компьютером, и условный порядок байтов для отправки " "данных на другой компьютер." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:465 msgid "" "We will call the byte order our computer uses the _host byte order_, or just " "the _host order_." msgstr "" "Мы будем называть порядок байтов, который использует наш компьютер, " "_порядком байтов хоста_ или просто _хост-порядком_." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:468 msgid "" "There is a convention of sending the multi-byte data over IP _MSB first_. " "This, we will refer to as the _network byte order_, or simply the _network " "order_." msgstr "" "Существует соглашение о передаче многобайтовых данных по IP _старшим байтом " "вперёд_. Это мы будем называть _порядком байтов сети_ или просто _сетевым " "порядком_." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:470 msgid "" "Now, if we compiled the above code for an Intel based computer, our _host " "byte order_ would produce:" msgstr "" "Вот, если бы мы скомпилировали приведённый выше код для компьютера на базе " "Intel, наш _порядок байтов хоста_ выдал бы:" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:471 #, no-wrap msgid "Host byte order on an Intel system" msgstr "Порядок байтов на хосте в системе Intel" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:475 msgid "But the _network byte order_ requires that we store the data MSB first:" msgstr "" "Но порядок байтов в _сетевом формате_ требует, чтобы данные хранились " "начиная со старшего байта (MSB):" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:476 #, no-wrap msgid "Network byte order" msgstr "Порядок байтов в сети" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:480 msgid "" "Unfortunately, our _host order_ is the exact opposite of the _network order_." msgstr "" "К сожалению, наш _порядок хоста_ полностью противоположен _порядку сети_." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:483 msgid "" "We have several ways of dealing with it. One would be to _reverse_ the " "values in our code:" msgstr "" "У нас есть несколько способов решения этой проблемы. Один из них — " "_инвертировать_ значения в нашем коде:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:489 #, no-wrap msgid "" "sa.sin_family = AF_INET;\n" "sa.sin_port = 13 << 8;\n" "sa.sin_addr.s_addr = (((((1 << 8) | 96) << 8) | 163) << 8) | 132;\n" msgstr "" "sa.sin_family = AF_INET;\n" "sa.sin_port = 13 << 8;\n" "sa.sin_addr.s_addr = (((((1 << 8) | 96) << 8) | 163) << 8) | 132;\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:494 msgid "" "This will _trick_ our compiler into storing the data in the _network byte " "order_. In some cases, this is exactly the way to do it (e.g., when " "programming in assembly language). In most cases, however, it can cause a " "problem." msgstr "" "Это _обманет_ наш компилятор, заставив его сохранить данные в _порядке " "байтов сети_. В некоторых случаях это именно тот способ, который нужен " "(например, при программировании на ассемблере). Однако в большинстве случаев " "это может вызвать проблему." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:498 msgid "" "Suppose, you wrote a sockets-based program in C. You know it is going to " "run on a Pentium(R), so you enter all your constants in reverse and force " "them to the _network byte order_. It works well." msgstr "" "Предположим, вы написали программу на C, использующую сокеты. Вы знаете, что " "она будет работать на Pentium(R), поэтому вводите все константы в обратном " "порядке и приводите их к _порядку байтов сети_. Она работает хорошо." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:503 msgid "" "Then, some day, your trusted old Pentium(R) becomes a rusty old Pentium(R). " "You replace it with a system whose _host order_ is the same as the _network " "order_. You need to recompile all your software. All of your software " "continues to perform well, except the one program you wrote." msgstr "" "Затем, однажды, ваш надёжный старый Pentium(R) превращается в ржавый старый " "Pentium(R). Вы заменяете его системой, у которой _порядок байтов хоста_ " "совпадает с _сетевым порядком байтов_. Вам нужно перекомпилировать все ваше " "программное обеспечение. Все ваши программы продолжают работать хорошо, " "кроме той одной программы, которую вы написали." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:507 msgid "" "You have since forgotten that you had forced all of your constants to the " "opposite of the _host order_. You spend some quality time tearing out your " "hair, calling the names of all gods you ever heard of (and some you made " "up), hitting your monitor with a nerf bat, and performing all the other " "traditional ceremonies of trying to figure out why something that has worked " "so well is suddenly not working at all." msgstr "" "Вы уже забыли, что принудительно задали все свои константы противоположными " "_порядку хоста_. Вы проводите некоторое время, яростно рвя на себе волосы, " "взывая ко всем известным вам богам (и к некоторым, которых вы придумали), " "стуча нерф-битой по монитору и выполняя прочие традиционные ритуалы в " "попытке понять, почему то, что работало так хорошо, внезапно перестало " "работать вообще." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:509 msgid "" "Eventually, you figure it out, say a couple of swear words, and start " "rewriting your code." msgstr "" "В конце концов, вы разбираетесь в проблеме, произносите пару крепких " "словечек и начинаете переписывать свой код." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:512 msgid "" "Luckily, you are not the first one to face the problem. Someone else has " "created the man:htons[3] and man:htonl[3] C functions to convert a `short` " "and `long` respectively from the _host byte order_ to the _network byte " "order_, and the man:ntohs[3] and man:ntohl[3] C functions to go the other " "way." msgstr "" "К счастью, вы не первый, кто столкнулся с этой проблемой. Кто-то уже создал " "функции man:htons[3] и man:htonl[3] на языке C для преобразования `short` и " "`long` соответственно из _порядка байтов хоста_ в _порядок байтов сети_, а " "также функции man:ntohs[3] и man:ntohl[3] на языке C для обратного " "преобразования." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:515 msgid "" "On _MSB-first_ systems these functions do nothing. On _LSB-first_ systems " "they convert values to the proper order." msgstr "" "На системах с порядком _старший байт первый_ эти функции не выполняют " "никаких действий. На системах с порядком _младший байт первый_ они " "преобразуют значения в правильный порядок." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:517 msgid "" "So, regardless of what system your software is compiled on, your data will " "end up in the correct order if you use these functions." msgstr "" "Итак, независимо от того, на какой системе компилируется ваше программное " "обеспечение, ваши данные будут в правильном порядке, если вы используете эти " "функции." #. type: Title ==== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:519 #, no-wrap msgid "Client Functions" msgstr "Функции клиента" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:524 msgid "" "Typically, the client initiates the connection to the server. The client " "knows which server it is about to call: It knows its IP address, and it " "knows the _port_ the server resides at. It is akin to you picking up the " "phone and dialing the number (the _address_), then, after someone answers, " "asking for the person in charge of wingdings (the _port_)." msgstr "" "Обычно клиент инициирует подключение к серверу. Клиент знает, к какому " "серверу он собирается обратиться: он знает его IP-адрес и _порт_, на котором " "работает сервер. Это похоже на то, как вы поднимаете трубку и набираете " "номер (_адрес_), а затем, когда кто-то отвечает, просите соединить со " "специалистом по непонятным символам (_порт_)." #. type: Title ===== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:526 #, no-wrap msgid "`connect`" msgstr "`connect`" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:529 msgid "" "Once a client has created a socket, it needs to connect it to a specific " "port on a remote system. It uses man:connect[2]:" msgstr "" "Как только клиент создал сокет, ему нужно подключить его к определённому " "порту на удалённой системе. Для этого используется man:connect[2]:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:533 #, no-wrap msgid "int connect(int s, const struct sockaddr *name, socklen_t namelen);\n" msgstr "int connect(int s, const struct sockaddr *name, socklen_t namelen);\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:538 msgid "" "The `s` argument is the socket, i.e., the value returned by the `socket` " "function. The `name` is a pointer to `sockaddr`, the structure we have " "talked about extensively. Finally, `namelen` informs the system how many " "bytes are in our `sockaddr` structure." msgstr "" "Аргумент `s` — это сокет, то есть значение, возвращаемое функцией `socket`. " "Аргумент `name` — это указатель на структуру `sockaddr`, которую мы подробно " "обсуждали. Наконец, `namelen` сообщает системе, сколько байт находится в " "нашей структуре `sockaddr`." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:541 msgid "" "If `connect` is successful, it returns `0`. Otherwise it returns `-1` and " "stores the error code in `errno`." msgstr "" "Если `connect` завершается успешно, он возвращает `0`. В противном случае " "возвращается `-1`, а код ошибки сохраняется в `errno`." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:545 msgid "" "There are many reasons why `connect` may fail. For example, with an attempt " "to an Internet connection, the IP address may not exist, or it may be down, " "or just too busy, or it may not have a server listening at the specified " "port. Or it may outright _refuse_ any request for specific code." msgstr "" "Существует множество причин, по которым `connect` может завершиться " "неудачей. Например, при попытке подключения к интернету, IP-адрес может не " "существовать, быть недоступен, перегружен или на указанном порту может не " "быть сервера. Или же подключение может быть явно _отклонено_ по определённым " "причинам." #. type: Title ===== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:547 #, no-wrap msgid "Our First Client" msgstr "Наш первый клиент" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:550 msgid "" "We now know enough to write a very simple client, one that will get current " "time from `132.163.96.1` and print it to [.filename]#stdout#." msgstr "" "Теперь мы знаем достаточно, чтобы написать очень простого клиента, который " "получит текущее время от `132.163.96.1` и выведет его в [.filename]#stdout#." #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:564 #, no-wrap msgid "" "/*\n" " * daytime.c\n" " *\n" " * Programmed by G. Adam Stanislav\n" " */\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" msgstr "" "/*\n" " * daytime.c\n" " *\n" " * Programmed by G. Adam Stanislav\n" " */\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:569 #, no-wrap msgid "" "int main() {\n" " int s, bytes;\n" " struct sockaddr_in sa;\n" " char buffer[BUFSIZ+1];\n" msgstr "" "int main() {\n" " int s, bytes;\n" " struct sockaddr_in sa;\n" " char buffer[BUFSIZ+1];\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:574 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:993 #, no-wrap msgid "" " if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {\n" " perror(\"socket\");\n" " return 1;\n" " }\n" msgstr "" " if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {\n" " perror(\"socket\");\n" " return 1;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:576 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:995 #, no-wrap msgid " memset(&sa, '\\0', sizeof(sa));\n" msgstr " memset(&sa, '\\0', sizeof(sa));\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:585 #, no-wrap msgid "" " sa.sin_family = AF_INET;\n" " sa.sin_port = htons(13);\n" " sa.sin_addr.s_addr = htonl((((((132 << 8) | 163) << 8) | 96) << 8) | 1);\n" " if (connect(s, (struct sockaddr *)&sa, sizeof sa) < 0) {\n" " perror(\"connect\");\n" " close(s);\n" " return 2;\n" " }\n" msgstr "" " sa.sin_family = AF_INET;\n" " sa.sin_port = htons(13);\n" " sa.sin_addr.s_addr = htonl((((((132 << 8) | 163) << 8) | 96) << 8) | 1);\n" " if (connect(s, (struct sockaddr *)&sa, sizeof sa) < 0) {\n" " perror(\"connect\");\n" " close(s);\n" " return 2;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:588 #, no-wrap msgid "" " while ((bytes = read(s, buffer, BUFSIZ)) > 0)\n" " write(1, buffer, bytes);\n" msgstr "" " while ((bytes = read(s, buffer, BUFSIZ)) > 0)\n" " write(1, buffer, bytes);\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:592 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1019 #, no-wrap msgid "" " close(s);\n" " return 0;\n" "}\n" msgstr "" " close(s);\n" " return 0;\n" "}\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:595 msgid "" "Go ahead, enter it in your editor, save it as [.filename]#daytime.c#, then " "compile and run it:" msgstr "" "Вперед! Введите это в вашем редакторе, сохраните как [.filename]#daytime.c#, " "затем скомпилируйте и запустите:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:600 #, no-wrap msgid "" "% cc -O3 -o daytime daytime.c\n" "% ./daytime\n" msgstr "" "% cc -O3 -o daytime daytime.c\n" "% ./daytime\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:603 #, no-wrap msgid "" "52079 01-06-19 02:29:25 50 0 1 543.9 UTC(NIST) *\n" "%\n" msgstr "" "52079 01-06-19 02:29:25 50 0 1 543.9 UTC(NIST) *\n" "%\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:607 msgid "" "In this case, the date was June 19, 2001, the time was 02:29:25 UTC. " "Naturally, your results will vary." msgstr "" "В данном случае дата была 19 июня 2001 года, время — 02:29:25 UTC. " "Естественно, ваши результаты могут отличаться." #. type: Title ==== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:609 #, no-wrap msgid "Server Functions" msgstr "Функции сервера" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:615 msgid "" "The typical server does not initiate the connection. Instead, it waits for " "a client to call it and request services. It does not know when the client " "will call, nor how many clients will call. It may be just sitting there, " "waiting patiently, one moment, The next moment, it can find itself swamped " "with requests from a number of clients, all calling in at the same time." msgstr "" "Типичный сервер не инициирует соединение. Вместо этого он ожидает, когда " "клиент обратится к нему и запросит услуги. Он не знает, когда клиент " "обратится, ни сколько клиентов обратится. В один момент он может просто " "спокойно ожидать, а в следующий момент он может оказаться перегруженным " "запросами от множества клиентов, обращающихся одновременно." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:617 msgid "The sockets interface offers three basic functions to handle this." msgstr "" "Интерфейс сокетов предоставляет три основные функции для обработки этого." #. type: Title ===== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:619 #, no-wrap msgid "`bind`" msgstr "`bind`" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:622 msgid "" "Ports are like extensions to a phone line: After you dial a number, you dial " "the extension to get to a specific person or department." msgstr "" "Порты подобны внутренним номерам телефонной линии: после набора основного " "номера вы набираете внутренний номер, чтобы связаться с конкретным человеком " "или отделом." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:626 msgid "" "There are 65535 IP ports, but a server usually processes requests that come " "in on only one of them. It is like telling the phone room operator that we " "are now at work and available to answer the phone at a specific extension. " "We use man:bind[2] to tell sockets which port we want to serve." msgstr "" "Существует 65535 IP-портов, но сервер обычно обрабатывает запросы, " "поступающие только на один из них. Это как сказать оператору телефонной " "комнаты, что мы сейчас на месте и готовы отвечать на звонки по определённому " "внутреннему номеру. Мы используем man:bind[2], чтобы указать сокетам, на " "каком порту мы хотим обслуживать запросы." #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:630 #, no-wrap msgid "int bind(int s, const struct sockaddr *addr, socklen_t addrlen);\n" msgstr "int bind(int s, const struct sockaddr *addr, socklen_t addrlen);\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:635 msgid "" "Beside specifying the port in `addr`, the server may include its IP " "address. However, it can just use the symbolic constant INADDR_ANY to " "indicate it will serve all requests to the specified port regardless of what " "its IP address is. This symbol, along with several similar ones, is " "declared in [.filename]#netinet/in.h#" msgstr "" "Помимо указания порта в `addr`, сервер может включать свой IP-адрес. Однако " "он может просто использовать символическую константу INADDR_ANY, чтобы " "указать, что будет обслуживать все запросы на указанный порт, независимо от " "его IP-адреса. Этот символ, наряду с несколькими аналогичными, объявлен в [." "filename]#netinet/in.h#" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:639 #, no-wrap msgid "#define\tINADDR_ANY\t\t(u_int32_t)0x00000000\n" msgstr "#define\tINADDR_ANY\t\t(u_int32_t)0x00000000\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:644 msgid "" "Suppose we were writing a server for the _daytime_ protocol over TCP/IP. " "Recall that it uses port 13. Our `sockaddr_in` structure would look like " "this:" msgstr "" "Предположим, мы пишем сервер для протокола _daytime_ поверх TCP/IP. " "Напомним, что он использует порт 13. Наша структура `sockaddr_in` будет " "выглядеть так:" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:645 #, no-wrap msgid "Example Server sockaddr_in" msgstr "Пример sockaddr_in сервера" #. type: Target for macro image #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:646 #, no-wrap msgid "sainserv.png" msgstr "sainserv.png" #. type: Title ===== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:649 #, no-wrap msgid "`listen`" msgstr "`listen`" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:653 msgid "" "To continue our office phone analogy, after you have told the phone central " "operator what extension you will be at, you now walk into your office, and " "make sure your own phone is plugged in and the ringer is turned on. Plus, " "you make sure your call waiting is activated, so you can hear the phone ring " "even while you are talking to someone." msgstr "" "Продолжая аналогию с офисным телефоном, после того как вы сообщили оператору " "АТС, на каком внутреннем номере вы будете находиться, вы заходите в свой " "офис и убеждаетесь, что ваш телефон подключен и звонок включен. Кроме того, " "вы активируете функцию ожидания вызова, чтобы слышать звонок даже во время " "разговора с кем-то." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:655 msgid "The server ensures all of that with the man:listen[2] function." msgstr "Сервер обеспечивает все это с помощью функции man:listen[2]." #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:659 #, no-wrap msgid "int listen(int s, int backlog);\n" msgstr "int listen(int s, int backlog);\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:663 msgid "" "In here, the `backlog` variable tells sockets how many incoming requests to " "accept while you are busy processing the last request. In other words, it " "determines the maximum size of the queue of pending connections." msgstr "" "Здесь переменная `backlog` указывает сокетам, сколько входящих запросов " "принимать, пока вы заняты обработкой последнего запроса. Другими словами, " "она определяет максимальный размер очереди ожидающих соединений." #. type: Title ===== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:665 #, no-wrap msgid "`accept`" msgstr "`accept`" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:670 msgid "" "After you hear the phone ringing, you accept the call by answering the " "call. You have now established a connection with your client. This " "connection remains active until either you or your client hang up." msgstr "" "После того как вы услышите телефонный звонок, вы принимаете вызов, отвечая " "на звонок. Теперь вы установили соединение с вашим клиентом. Это соединение " "остаётся активным, пока вы или ваш клиент не повесите трубку." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:672 msgid "The server accepts the connection by using the man:accept[2] function." msgstr "Сервер принимает соединение, используя функцию man:accept[2]." #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:676 #, no-wrap msgid "int accept(int s, struct sockaddr *addr, socklen_t *addrlen);\n" msgstr "int accept(int s, struct sockaddr *addr, socklen_t *addrlen);\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:680 msgid "" "Note that this time `addrlen` is a pointer. This is necessary because in " "this case it is the socket that fills out `addr`, the `sockaddr_in` " "structure." msgstr "" "Обратите внимание, что в этот раз `addrlen` является указателем. Это " "необходимо, потому что в данном случае именно сокет заполняет структуру " "`addr` — `sockaddr_in`." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:684 msgid "" "The return value is an integer. Indeed, the `accept` returns a _new " "socket_. You will use this new socket to communicate with the client." msgstr "" "Возвращаемое значение является целым числом. Действительно, `accept` " "возвращает _новый сокет_. Этот новый сокет будет использоваться для обмена " "данными с клиентом." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:686 msgid "" "What happens to the old socket? It continues to listen for more requests " "(remember the `backlog` variable we passed to `listen`?) until we `close` it." msgstr "" "Что происходит со старым сокетом? Он продолжает ожидать новые запросы " "(помните переменную `backlog`, которую мы передали в `listen`?), пока мы не " "закроем его (`close`)." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:690 msgid "" "Now, the new socket is meant only for communications. It is fully " "connected. We cannot pass it to `listen` again, trying to accept additional " "connections." msgstr "" "Теперь новый сокет предназначен только для обмена данными. Он полностью " "подключен. Мы не можем снова передать его в `listen`, чтобы принимать " "дополнительные соединения." #. type: Title ===== #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:692 #, no-wrap msgid "Our First Server" msgstr "Наш первый сервер" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:696 msgid "" "Our first server will be somewhat more complex than our first client was: " "Not only do we have more sockets functions to use, but we need to write it " "as a daemon." msgstr "" "Наш первый сервер будет несколько сложнее, чем первый клиент: нам нужно не " "только использовать больше функций сокетов, но и написать его как демон." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:699 msgid "" "This is best achieved by creating a _child process_ after binding the port. " "The main process then exits and returns control to the shell (or whatever " "program invoked it)." msgstr "" "Это лучше всего достигается созданием _дочернего процесса_ после привязки " "порта. Затем основной процесс завершается и возвращает управление оболочке " "(или любой другой программе, которая его вызвала)." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:701 msgid "" "The child calls `listen`, then starts an endless loop, which accepts a " "connection, serves it, and eventually closes its socket." msgstr "" "Дочерний процесс вызывает `listen`, затем запускает бесконечный цикл, " "который принимает соединение, обслуживает его и в конечном итоге закрывает " "свой сокет." #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:717 #, no-wrap msgid "" "/*\n" " * daytimed - a port 13 server\n" " *\n" " * Programmed by G. Adam Stanislav\n" " * June 19, 2001\n" " */\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" msgstr "" "/*\n" " * daytimed - a port 13 server\n" " *\n" " * Programmed by G. Adam Stanislav\n" " * June 19, 2001\n" " */\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:719 #, no-wrap msgid "#define BACKLOG 4\n" msgstr "#define BACKLOG 4\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:727 #, no-wrap msgid "" "int main() {\n" " int s, c;\n" " socklen_t b;\n" " struct sockaddr_in sa;\n" " time_t t;\n" " struct tm *tm;\n" " FILE *client;\n" msgstr "" "int main() {\n" " int s, c;\n" " socklen_t b;\n" " struct sockaddr_in sa;\n" " time_t t;\n" " struct tm *tm;\n" " FILE *client;\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:732 #, no-wrap msgid "" " if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {\n" " perror(\"socket\");\n" " return 1;\n" " }\n" msgstr "" " if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {\n" " perror(\"socket\");\n" " return 1;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:734 #, no-wrap msgid " memset(&sa, '\\0', sizeof(sa));\n" msgstr " memset(&sa, '\\0', sizeof(sa));\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:737 #, no-wrap msgid "" " sa.sin_family = AF_INET;\n" " sa.sin_port = htons(13);\n" msgstr "" " sa.sin_family = AF_INET;\n" " sa.sin_port = htons(13);\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:740 #, no-wrap msgid "" " if (INADDR_ANY)\n" " sa.sin_addr.s_addr = htonl(INADDR_ANY);\n" msgstr "" " if (INADDR_ANY)\n" " sa.sin_addr.s_addr = htonl(INADDR_ANY);\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:745 #, no-wrap msgid "" " if (bind(s, (struct sockaddr *)&sa, sizeof sa) < 0) {\n" " perror(\"bind\");\n" " return 2;\n" " }\n" msgstr "" " if (bind(s, (struct sockaddr *)&sa, sizeof sa) < 0) {\n" " perror(\"bind\");\n" " return 2;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:756 #, no-wrap msgid "" " switch (fork()) {\n" " case -1:\n" " perror(\"fork\");\n" " return 3;\n" " default:\n" " close(s);\n" " return 0;\n" " case 0:\n" " break;\n" " }\n" msgstr "" " switch (fork()) {\n" " case -1:\n" " perror(\"fork\");\n" " return 3;\n" " default:\n" " close(s);\n" " return 0;\n" " case 0:\n" " break;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:758 #, no-wrap msgid " listen(s, BACKLOG);\n" msgstr " listen(s, BACKLOG);\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:761 #, no-wrap msgid "" " for (;;) {\n" " b = sizeof sa;\n" msgstr "" " for (;;) {\n" " b = sizeof sa;\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:766 #, no-wrap msgid "" " if ((c = accept(s, (struct sockaddr *)&sa, &b)) < 0) {\n" " perror(\"daytimed accept\");\n" " return 4;\n" " }\n" msgstr "" " if ((c = accept(s, (struct sockaddr *)&sa, &b)) < 0) {\n" " perror(\"daytimed accept\");\n" " return 4;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:771 #, no-wrap msgid "" " if ((client = fdopen(c, \"w\")) == NULL) {\n" " perror(\"daytimed fdopen\");\n" " return 5;\n" " }\n" msgstr "" " if ((client = fdopen(c, \"w\")) == NULL) {\n" " perror(\"daytimed fdopen\");\n" " return 5;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:776 #, no-wrap msgid "" " if ((t = time(NULL)) < 0) {\n" " perror(\"daytimed time\");\n" " return 6;\n" " }\n" msgstr "" " if ((t = time(NULL)) < 0) {\n" " perror(\"daytimed time\");\n" " return 6;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:785 #, no-wrap msgid "" " tm = gmtime(&t);\n" " fprintf(client, \"%.4i-%.2i-%.2iT%.2i:%.2i:%.2iZ\\n\",\n" " tm->tm_year + 1900,\n" " tm->tm_mon + 1,\n" " tm->tm_mday,\n" " tm->tm_hour,\n" " tm->tm_min,\n" " tm->tm_sec);\n" msgstr "" " tm = gmtime(&t);\n" " fprintf(client, \"%.4i-%.2i-%.2iT%.2i:%.2i:%.2iZ\\n\",\n" " tm->tm_year + 1900,\n" " tm->tm_mon + 1,\n" " tm->tm_mday,\n" " tm->tm_hour,\n" " tm->tm_min,\n" " tm->tm_sec);\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:789 #, no-wrap msgid "" " fclose(client);\n" " }\n" "}\n" msgstr "" " fclose(client);\n" " }\n" "}\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:794 msgid "" "We start by creating a socket. Then we fill out the `sockaddr_in` structure " "in `sa`. Note the conditional use of INADDR_ANY:" msgstr "" "Начинаем с создания сокета. Затем заполняем структуру `sockaddr_in` в `sa`. " "Обратите внимание на условное использование INADDR_ANY:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:799 #, no-wrap msgid "" "if (INADDR_ANY)\n" " sa.sin_addr.s_addr = htonl(INADDR_ANY);\n" msgstr "" "if (INADDR_ANY)\n" " sa.sin_addr.s_addr = htonl(INADDR_ANY);\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:806 msgid "" "Its value is `0`. Since we have just used `memset` to set zeroes on the " "entire structure, it would be redundant to set it to `0` again. But if we " "port our code to some other system where INADDR_ANY is perhaps not a zero, " "we need to assign it to `sa.sin_addr.s_addr`. Most modern C compilers are " "clever enough to notice that INADDR_ANY is a constant. As long as it is a " "zero, they will optimize the entire conditional statement out of the code." msgstr "" "Его значение равно `0`. Поскольку мы только что использовали `memset`, чтобы " "установить в 0 все байты структуры, будет избыточным снова устанавливать его " "в `0`. Но если мы перенесём наш код на другую систему, где INADDR_ANY, " "возможно, не равен нулю, нам нужно будет присвоить его `sa.sin_addr.s_addr`. " "Большинство современных компиляторов C достаточно умны, чтобы заметить, что " "INADDR_ANY — это константа. Пока она равна нулю, они оптимизируют все " "условное выражение из кода." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:810 msgid "" "After we have called `bind` successfully, we are ready to become a _daemon_: " "We use `fork` to create a child process. In both, the parent and the child, " "the `s` variable is our socket. The parent process will not need it, so it " "calls `close`, then it returns `0` to inform its own parent it had " "terminated successfully." msgstr "" "После успешного вызова `bind` мы готовы стать _демоном_: используем `fork` " "для создания дочернего процесса. В обоих процессах, родительском и дочернем, " "переменная `s` является нашим сокетом. Родительскому процессу он больше не " "нужен, поэтому он вызывает `close`, затем возвращает `0`, чтобы сообщить " "своему родителю об успешном завершении." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:815 msgid "" "Meanwhile, the child process continues working in the background. It calls " "`listen` and sets its backlog to `4`. It does not need a large value here " "because _daytime_ is not a protocol many clients request all the time, and " "because it can process each request instantly anyway." msgstr "" "Между тем, дочерний процесс продолжает работать в фоновом режиме. Он " "вызывает `listen` и устанавливает размер очереди ожидания (`backlog`) равным " "`4`. Здесь не требуется большое значение, так как _daytime_ — это не " "протокол, который часто запрашивают клиенты, и, кроме того, он может " "мгновенно обрабатывать каждый запрос." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:817 msgid "" "Finally, the daemon starts an endless loop, which performs the following " "steps:" msgstr "" "Наконец, демон запускает бесконечный цикл, который выполняет следующие шаги:" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:820 msgid "" "Call `accept`. It waits here until a client contacts it. At that point, it " "receives a new socket, `c`, which it can use to communicate with this " "particular client." msgstr "" "Вызовите `accept`. Он ожидает здесь, пока клиент не свяжется с ним. В этот " "момент он получает новый сокет, `c`, который можно использовать для обмена " "данными с этим конкретным клиентом." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:821 msgid "" "It uses the C function `fdopen` to turn the socket from a low-level _file " "descriptor_ to a C-style `FILE` pointer. This will allow the use of " "`fprintf` later on." msgstr "" "Он использует функцию C `fdopen` для преобразования сокета из " "низкоуровневого _дескриптора файла_ в указатель типа `FILE` в стиле C. Это " "позволит в дальнейшем использовать `fprintf`." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:822 msgid "" "It checks the time, and prints it in the _ISO 8601_ format to the `client` " "\"file\". It then uses `fclose` to close the file. That will automatically " "close the socket as well." msgstr "" "Он проверяет время и выводит его в формате _ISO 8601_ в «файл» `client`. " "Затем он использует `fclose` для закрытия файла. Это также автоматически " "закроет сокет." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:824 msgid "We can _generalize_ this, and use it as a model for many other servers:" msgstr "" "Мы можем _обобщить_ это и использовать в качестве модели для многих других " "серверов:" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:825 #, no-wrap msgid "Sequential Server" msgstr "Последовательный Сервер" #. type: Target for macro image #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:826 #, no-wrap msgid "serv.png" msgstr "serv.png" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:832 msgid "" "This flowchart is good for _sequential servers_, i.e., servers that can " "serve one client at a time, just as we were able to with our _daytime_ " "server. This is only possible whenever there is no real \"conversation\" " "going on between the client and the server: As soon as the server detects a " "connection to the client, it sends out some data and closes the connection. " "The entire operation may take nanoseconds, and it is finished." msgstr "" "Эта блок-схема подходит для _последовательных серверов_, то есть серверов, " "которые могут обслуживать одного клиента за раз, как это было возможно с " "нашим _daytime_ сервером. Это возможно только в тех случаях, когда между " "клиентом и сервером не происходит реального \"диалога\": как только сервер " "обнаруживает подключение клиента, он отправляет некоторые данные и закрывает " "соединение. Вся операция может занять наносекунды, и она завершена." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:835 msgid "" "The advantage of this flowchart is that, except for the brief moment after " "the parent ``fork``s and before it exits, there is always only one _process_ " "active: Our server does not take up much memory and other system resources." msgstr "" "Преимущество этой блок-схемы в том, что, за исключением короткого момента " "после того, как родительский процесс выполняет ``fork`` и до его завершения, " "всегда активен только один _процесс_: Наш сервер не занимает много памяти и " "других системных ресурсов." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:839 msgid "" "Note that we have added _initialize daemon_ in our flowchart. We did not " "need to initialize our own daemon, but this is a good place in the flow of " "the program to set up any `signal` handlers, open any files we may need, etc." msgstr "" "Обратите внимание, что мы добавили _инициализацию демона_ в нашу блок-схему. " "Нам не нужно было инициализировать собственный демон, но это подходящее " "место в потоке выполнения программы для настройки обработчиков `signal`, " "открытия необходимых файлов и т. д." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:843 msgid "" "Just about everything in the flow chart can be used literally on many " "different servers. The _serve_ entry is the exception. We think of it as a " "_\"black box\"_, i.e., something you design specifically for your own " "server, and just \"plug it into the rest.\"" msgstr "" "Почти все элементы блок-схемы могут быть использованы буквально на множестве " "различных серверов. Элемент _serve_ является исключением. Мы рассматриваем " "его как _\"чёрный ящик\"_, то есть нечто, что вы проектируете специально для " "своего сервера и просто \"подключаете к остальной системе.\"" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:849 msgid "" "Not all protocols are that simple. Many receive a request from the client, " "reply to it, then receive another request from the same client. As a " "result, they do not know in advance how long they will be serving the " "client. Such servers usually start a new process for each client. While " "the new process is serving its client, the daemon can continue listening for " "more connections." msgstr "" "Не все протоколы настолько просты. Многие получают запрос от клиента, " "отвечают на него, а затем получают ещё один запрос от того же клиента. В " "результате, они не знают заранее, как долго будут обслуживать клиента. Такие " "серверы обычно запускают новый процесс для каждого клиента. Пока новый " "процесс обслуживает своего клиента, демон может продолжать прослушивать " "новые подключения." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:852 msgid "" "Now, go ahead, save the above source code as [.filename]#daytimed.c# (it is " "customary to end the names of daemons with the letter `d`). After you have " "compiled it, try running it:" msgstr "" "Теперь сохраните приведённый исходный код в файл [.filename]#daytimed.c# " "(обычно имена демонов оканчиваются буквой `d`). После компиляции попробуйте " "запустить его:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:858 #, no-wrap msgid "" "% ./daytimed\n" "bind: Permission denied\n" "%\n" msgstr "" "% ./daytimed\n" "bind: Permission denied\n" "%\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:862 msgid "" "What happened here? As you will recall, the _daytime_ protocol uses port " "13. But all ports below 1024 are reserved to the superuser (otherwise, " "anyone could start a daemon pretending to serve a commonly used port, while " "causing a security breach)." msgstr "" "Что произошло? Как вы помните, протокол _daytime_ использует порт 13. Однако " "все порты ниже 1024 зарезервированы для суперпользователя (в противном " "случае любой мог бы запустить демон, притворяясь, что обслуживает часто " "используемый порт, создавая угрозу безопасности)." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:864 msgid "Try again, this time as the superuser:" msgstr "Попробуйте снова, на этот раз как суперпользователь:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:869 #, no-wrap msgid "" "# ./daytimed\n" "#\n" msgstr "" "# ./daytimed\n" "#\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:872 msgid "What... Nothing? Let us try again:" msgstr "Что... Ничего? Давайте попробуем ещё раз:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:876 #, no-wrap msgid "# ./daytimed\n" msgstr "# ./daytimed\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:879 #, no-wrap msgid "" "bind: Address already in use\n" "#\n" msgstr "" "bind: Address already in use\n" "#\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:884 msgid "" "Every port can only be bound by one program at a time. Our first attempt " "was indeed successful: It started the child daemon and returned quietly. It " "is still running and will continue to run until you either kill it, or any " "of its system calls fail, or you reboot the system." msgstr "" "Каждый порт может быть связан только одной программой одновременно. Наша " "первая попытка действительно была успешной: она запустила дочерний демон и " "завершилась без ошибок. Он продолжает работать и будет работать до тех пор, " "пока вы его не завершите командой kill, пока какой-либо из его системных " "вызовов не завершится с ошибкой или пока вы не перезагрузите систему." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:887 msgid "" "Fine, we know it is running in the background. But is it working? How do we " "know it is a proper _daytime_ server? Simple:" msgstr "" "Хорошо, мы знаем, что он работает в фоновом режиме. Но работает ли он? Как " "мы можем убедиться, что это настоящий сервер _daytime_? Просто:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:891 #, no-wrap msgid "% telnet localhost 13\n" msgstr "% telnet localhost 13\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:900 #, no-wrap msgid "" "Trying ::1...\n" "telnet: connect to address ::1: Connection refused\n" "Trying 127.0.0.1...\n" "Connected to localhost.\n" "Escape character is '^]'.\n" "2001-06-19T21:04:42Z\n" "Connection closed by foreign host.\n" "%\n" msgstr "" "Trying ::1...\n" "telnet: connect to address ::1: Connection refused\n" "Trying 127.0.0.1...\n" "Connected to localhost.\n" "Escape character is '^]'.\n" "2001-06-19T21:04:42Z\n" "Connection closed by foreign host.\n" "%\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:905 msgid "" "telnet tried the new IPv6, and failed. It retried with IPv4 and succeeded. " "The daemon works." msgstr "" "telnet попробовал использовать новый IPv6, но не смог. Затем он повторил " "попытку с IPv4, и это удалось. Демон работает." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:908 msgid "" "If you have access to another UNIX(R) system via telnet, you can use it to " "test accessing the server remotely. My computer does not have a static IP " "address, so this is what I did:" msgstr "" "Если у вас есть доступ к другой UNIX(R)-системе через telnet, вы можете " "использовать её для проверки удалённого доступа к серверу. Мой компьютер не " "имеет статического IP-адреса, поэтому я сделал следующее:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:912 #, no-wrap msgid "% who\n" msgstr "% who\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:916 #, no-wrap msgid "" "whizkid ttyp0 Jun 19 16:59 (216.127.220.143)\n" "xxx ttyp1 Jun 19 16:06 (xx.xx.xx.xx)\n" "% telnet 216.127.220.143 13\n" msgstr "" "whizkid ttyp0 Jun 19 16:59 (216.127.220.143)\n" "xxx ttyp1 Jun 19 16:06 (xx.xx.xx.xx)\n" "% telnet 216.127.220.143 13\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:923 #, no-wrap msgid "" "Trying 216.127.220.143...\n" "Connected to r47.bfm.org.\n" "Escape character is '^]'.\n" "2001-06-19T21:31:11Z\n" "Connection closed by foreign host.\n" "%\n" msgstr "" "Trying 216.127.220.143...\n" "Connected to r47.bfm.org.\n" "Escape character is '^]'.\n" "2001-06-19T21:31:11Z\n" "Connection closed by foreign host.\n" "%\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:926 msgid "Again, it worked. Will it work using the domain name?" msgstr "" "Снова, это сработало. Сработает ли это с использованием доменного имени?" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:930 #, no-wrap msgid "% telnet r47.bfm.org 13\n" msgstr "% telnet r47.bfm.org 13\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:937 #, no-wrap msgid "" "Trying 216.127.220.143...\n" "Connected to r47.bfm.org.\n" "Escape character is '^]'.\n" "2001-06-19T21:31:40Z\n" "Connection closed by foreign host.\n" "%\n" msgstr "" "Trying 216.127.220.143...\n" "Connected to r47.bfm.org.\n" "Escape character is '^]'.\n" "2001-06-19T21:31:40Z\n" "Connection closed by foreign host.\n" "%\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:941 msgid "" "By the way, telnet prints the _Connection closed by foreign host_ message " "after our daemon has closed the socket. This shows us that, indeed, using " "`fclose(client);` in our code works as advertised." msgstr "" "Кстати, telnet выводит сообщение _Connection closed by foreign host_ после " "того, как наш демон закрыл сокет. Это показывает, что использование " "`fclose(client);` в нашем коде действительно работает, как заявлено." #. type: Title == #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:943 #, no-wrap msgid "Helper Functions" msgstr "Вспомогательные функции" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:949 msgid "" "FreeBSD C library contains many helper functions for sockets programming. " "For example, in our sample client we hard coded the `time.nist.gov` IP " "address. But we do not always know the IP address. Even if we do, our " "software is more flexible if it allows the user to enter the IP address, or " "even the domain name." msgstr "" "Библиотека C в FreeBSD содержит множество вспомогательных функций для " "программирования сокетов. Например, в нашем примере клиента мы жёстко " "прописали IP-адрес `time.nist.gov`. Но мы не всегда знаем IP-адрес. Даже " "если знаем, наше программное обеспечение будет более гибким, если позволит " "пользователю ввести IP-адрес или даже доменное имя." #. type: Title === #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:951 #, no-wrap msgid "`gethostbyname`" msgstr "`gethostbyname`" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:954 msgid "" "While there is no way to pass the domain name directly to any of the sockets " "functions, the FreeBSD C library comes with the man:gethostbyname[3] and man:" "gethostbyname2[3] functions, declared in [.filename]#netdb.h#." msgstr "" "Хотя нет возможности передать имя домена напрямую в какие-либо функции " "сокетов, стандартная библиотека C в FreeBSD предоставляет функции man:" "gethostbyname[3] и man:gethostbyname2[3], объявленные в [.filename]#netdb.h#." #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:959 #, no-wrap msgid "" "struct hostent * gethostbyname(const char *name);\n" "struct hostent * gethostbyname2(const char *name, int af);\n" msgstr "" "struct hostent * gethostbyname(const char *name);\n" "struct hostent * gethostbyname2(const char *name, int af);\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:963 msgid "" "Both return a pointer to the `hostent` structure, with much information " "about the domain. For our purposes, the `h_addr_list[0]` field of the " "structure points at `h_length` bytes of the correct address, already stored " "in the _network byte order_." msgstr "" "Оба возвращают указатель на структуру `hostent`, содержащую много информации " "о домене. Для наших целей поле `h_addr_list[0]` структуры указывает на " "`h_length` байтов правильного адреса, уже сохранённого в _порядке байтов " "сети_." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:965 msgid "" "This allows us to create a much more flexible-and much more useful-version " "of our daytime program:" msgstr "" "Это позволяет нам создать гораздо более гибкую — и гораздо более полезную — " "версию нашей программы daytime:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:981 #, no-wrap msgid "" "/*\n" " * daytime.c\n" " *\n" " * Programmed by G. Adam Stanislav\n" " * 19 June 2001\n" " */\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" msgstr "" "/*\n" " * daytime.c\n" " *\n" " * Programmed by G. Adam Stanislav\n" " * 19 June 2001\n" " */\n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" "#include \n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:988 #, no-wrap msgid "" "int main(int argc, char *argv[]) {\n" " int s, bytes;\n" " struct sockaddr_in sa;\n" " struct hostent *he;\n" " char buf[BUFSIZ+1];\n" " char *host;\n" msgstr "" "int main(int argc, char *argv[]) {\n" " int s, bytes;\n" " struct sockaddr_in sa;\n" " struct hostent *he;\n" " char buf[BUFSIZ+1];\n" " char *host;\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:998 #, no-wrap msgid "" " sa.sin_family = AF_INET;\n" " sa.sin_port = htons(13);\n" msgstr "" " sa.sin_family = AF_INET;\n" " sa.sin_port = htons(13);\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1000 #, no-wrap msgid " host = (argc > 1) ? argv[1] : \"time.nist.gov\";\n" msgstr " host = (argc > 1) ? argv[1] : \"time.nist.gov\";\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1005 #, no-wrap msgid "" " if ((he = gethostbyname(host)) == NULL) {\n" " herror(host);\n" " return 2;\n" " }\n" msgstr "" " if ((he = gethostbyname(host)) == NULL) {\n" " herror(host);\n" " return 2;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1007 #, no-wrap msgid " memcpy(&sa.sin_addr, he->h_addr_list[0], he->h_length);\n" msgstr " memcpy(&sa.sin_addr, he->h_addr_list[0], he->h_length);\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1012 #, no-wrap msgid "" " if (connect(s, (struct sockaddr *)&sa, sizeof sa) < 0) {\n" " perror(\"connect\");\n" " return 3;\n" " }\n" msgstr "" " if (connect(s, (struct sockaddr *)&sa, sizeof sa) < 0) {\n" " perror(\"connect\");\n" " return 3;\n" " }\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1015 #, no-wrap msgid "" " while ((bytes = read(s, buf, BUFSIZ)) > 0)\n" " write(1, buf, bytes);\n" msgstr "" " while ((bytes = read(s, buf, BUFSIZ)) > 0)\n" " write(1, buf, bytes);\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1025 msgid "" "We now can type a domain name (or an IP address, it works both ways) on the " "command line, and the program will try to connect to its _daytime_ server. " "Otherwise, it will still default to `time.nist.gov`. However, even in this " "case we will use `gethostbyname` rather than hard coding `132.163.96.1`. " "That way, even if its IP address changes in the future, we will still find " "it." msgstr "" "Теперь мы можем ввести доменное имя (или IP-адрес, это работает в обоих " "направлениях) в командной строке, и программа попытается подключиться к его " "серверу _daytime_. В противном случае по умолчанию будет использоваться `time" ".nist.gov`. Однако даже в этом случае мы будем использовать `gethostbyname` " "вместо жёсткого указания `132.163.96.1`. Таким образом, даже если его IP-" "адрес изменится в будущем, мы всё равно сможем его найти." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1029 msgid "" "Since it takes virtually no time to get the time from your local server, you " "could run daytime twice in a row: First to get the time from `time.nist." "gov`, the second time from your own system. You can then compare the " "results and see how exact your system clock is:" msgstr "" "Поскольку получение времени от локального сервера занимает практически " "нулевое время, вы можете запустить daytime дважды подряд: сначала для " "получения времени от `time.nist.gov`, а затем от вашей собственной системы. " "После этого вы можете сравнить результаты и увидеть, насколько точны часы " "вашей системы:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1033 #, no-wrap msgid "% daytime ; daytime localhost\n" msgstr "% daytime ; daytime localhost\n" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1037 #, no-wrap msgid "" "52080 01-06-20 04:02:33 50 0 0 390.2 UTC(NIST) *\n" "2001-06-20T04:02:35Z\n" "%\n" msgstr "" "52080 01-06-20 04:02:33 50 0 0 390.2 UTC(NIST) *\n" "2001-06-20T04:02:35Z\n" "%\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1040 msgid "As you can see, my system was two seconds ahead of the NIST time." msgstr "Как видно, моя система опережала время NIST на две секунды." #. type: Title === #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1042 #, no-wrap msgid "`getservbyname`" msgstr "`getservbyname`" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1046 msgid "" "Sometimes you may not be sure what port a certain service uses. The man:" "getservbyname[3] function, also declared in [.filename]#netdb.h# comes in " "very handy in those cases:" msgstr "" "Иногда вы можете быть не уверены, какой порт использует определённая служба. " "В таких случаях очень полезна функция man:getservbyname[3], также " "объявленная в [.filename]#netdb.h#:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1050 #, no-wrap msgid "struct servent * getservbyname(const char *name, const char *proto);\n" msgstr "struct servent * getservbyname(const char *name, const char *proto);\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1053 msgid "" "The `servent` structure contains the `s_port`, which contains the proper " "port, already in _network byte order_." msgstr "" "Структура `servent` содержит `s_port`, в котором находится соответствующий " "порт, уже в _порядке байтов сети_." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1055 msgid "" "Had we not known the correct port for the _daytime_ service, we could have " "found it this way:" msgstr "" "Если бы мы не знали правильный порт для службы _daytime_, мы могли бы найти " "его следующим образом:" #. type: delimited block . 4 #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1065 #, no-wrap msgid "" "struct servent *se;\n" " ...\n" " if ((se = getservbyname(\"daytime\", \"tcp\")) == NULL {\n" " fprintf(stderr, \"Cannot determine which port to use.\\n\");\n" " return 7;\n" " }\n" " sa.sin_port = se->s_port;\n" msgstr "" "struct servent *se;\n" " ...\n" " if ((se = getservbyname(\"daytime\", \"tcp\")) == NULL {\n" " fprintf(stderr, \"Cannot determine which port to use.\\n\");\n" " return 7;\n" " }\n" " sa.sin_port = se->s_port;\n" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1072 msgid "" "You usually do know the port. But if you are developing a new protocol, you " "may be testing it on an unofficial port. Some day, you will register the " "protocol and its port (if nowhere else, at least in your [.filename]#/etc/" "services#, which is where `getservbyname` looks). Instead of returning an " "error in the above code, you just use the temporary port number. Once you " "have listed the protocol in [.filename]#/etc/services#, your software will " "find its port without you having to rewrite the code." msgstr "" "Обычно порт известен. Но если вы разрабатываете новый протокол, вы можете " "тестировать его на неофициальном порту. Когда-нибудь вы зарегистрируете " "протокол и его порт (если не где-то ещё, то хотя бы в вашем [.filename]#/etc/" "services#, где `getservbyname` ищет). Вместо возврата ошибки в приведённом " "выше коде вы просто используете временный номер порта. Как только вы " "добавите протокол в [.filename]#/etc/services#, ваше программное обеспечение " "найдёт его порт без необходимости переписывать код." #. type: Title == #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1074 #, no-wrap msgid "Concurrent Servers" msgstr "Многозадачные серверы" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1078 msgid "" "Unlike a sequential server, a _concurrent server_ has to be able to serve " "more than one client at a time. For example, a _chat server_ may be serving " "a specific client for hours-it cannot wait till it stops serving a client " "before it serves the next one." msgstr "" "В отличие от последовательного сервера, _многозадачный сервер_ должен иметь " "возможность обслуживать более одного клиента одновременно. Например, _сервер " "чата_ может обслуживать конкретного клиента часами — он не может ждать, пока " "закончит обслуживать текущего клиента, прежде чем перейти к следующему." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1080 msgid "This requires a significant change in our flowchart:" msgstr "Это требует значительных изменений в нашей блок-схеме:" #. type: Block title #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1081 #, no-wrap msgid "Concurrent Server" msgstr "Многозадачный сервер" #. type: Target for macro image #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1082 #, no-wrap msgid "serv2.png" msgstr "serv2.png" #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1086 msgid "" "We moved the _serve_ from the _daemon process_ to its own _server process_. " "However, because each child process inherits all open files (and a socket is " "treated just like a file), the new process inherits not only the _\"accepted " "handle,\"_ i.e., the socket returned by the `accept` call, but also the _top " "socket_, i.e., the one opened by the top process right at the beginning." msgstr "" "Мы переместили _службу_ из _демона_ в её собственный _серверный процесс_. " "Однако, поскольку каждый дочерний процесс наследует все открытые файлы (а " "сокет обрабатывается так же, как файл), новый процесс наследует не только _" "\"принятый дескриптор\"_, т.е. сокет, возвращённый вызовом `accept`, но и " "_главный сокет_, т.е. тот, который был открыт главным процессом в самом " "начале." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1089 msgid "" "However, the _server process_ does not need this socket and should `close` " "it immediately. Similarly, the _daemon process_ no longer needs the " "_accepted socket_, and not only should, but _must_ `close` it-otherwise, it " "will run out of available _file descriptors_ sooner or later." msgstr "" "Однако _серверному процессу_ этот сокет не нужен, и он должен немедленно " "вызвать ему `close`. Аналогично, _демону_ больше не нужен _сокет, принятый " "вызовом accept_, и он не только должен, но и _обязан_ вызвать ему `close` — " "в противном случае рано или поздно закончатся доступные _файловые " "дескрипторы_." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1092 msgid "" "After the _server process_ is done serving, it should close the _accepted " "socket_. Instead of returning to `accept`, it now exits." msgstr "" "После завершения обслуживания _серверного процесса_ он должен закрыть " "_принятый сокет_. Вместо возврата к `accept`, процесс теперь завершается." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1099 msgid "" "Under UNIX(R), a process does not really _exit_. Instead, it _returns_ to " "its parent. Typically, a parent process ``wait``s for its child process, " "and obtains a return value. However, our _daemon process_ cannot simply " "stop and wait. That would defeat the whole purpose of creating additional " "processes. But if it never does `wait`, its children will become _zombies_-" "no longer functional but still roaming around." msgstr "" "В UNIX(R) процесс на самом деле не _завершается_. Вместо этого он " "_возвращается_ к своему родителю. Обычно родительский процесс ``ждёт`` " "(wait) завершения своего дочернего процесса и получает возвращаемое " "значение. Однако наш _демон-процесс_ не может просто остановиться и ждать. " "Это бы свело на нет всю цель создания дополнительных процессов. Но если он " "никогда не выполняет `wait`, его дочерние процессы станут _зомби_ — более не " "функционирующими, но всё ещё бродящими вокруг." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1102 msgid "" "For that reason, the _daemon process_ needs to set _signal handlers_ in its " "_initialize daemon_ phase. At least a SIGCHLD signal has to be processed, " "so the daemon can remove the zombie return values from the system and " "release the system resources they are taking up." msgstr "" "По этой причине _демону_ необходимо установить _обработчики сигналов_ на " "этапе _инициализации демона_. Как минимум, должен обрабатываться сигнал " "SIGCHLD, чтобы демон мог удалять зомби-процессы из системы и освобождать " "занимаемые ими системные ресурсы." #. type: Plain text #: documentation/content/en/books/developers-handbook/sockets/_index.adoc:1105 msgid "" "That is why our flowchart now contains a _process signals_ box, which is not " "connected to any other box. By the way, many servers also process SIGHUP, " "and typically interpret as the signal from the superuser that they should " "reread their configuration files. This allows us to change settings without " "having to kill and restart these servers." msgstr "" "Вот почему наша блок-схема теперь содержит блок _обработки сигналов_, " "который не соединен с другими блоками. Кстати, многие серверы также " "обрабатывают SIGHUP и обычно интерпретируют его как сигнал от " "суперпользователя, указывающий на необходимость перечитать конфигурационные " "файлы. Это позволяет нам изменять настройки без необходимости завершать и " "перезапускать эти серверы."