Программирование сокетов Linux (не ограничивается Linux)

задняя часть Linux
Программирование сокетов Linux (безлимитный Linux) - Wu Qin - Blog Garden Код меняет мир

У Цинь (Тайлер)

Программирование сокетов Linux (не ограничивается Linux)

2010-12-12 21:58 от Wu Qin, 264619 прочтений, 73 комментария,собирать, редактировать

"Все есть Сокет!"

Это немного преувеличено, но факт в том, что почти все современные сетевые программы используют сокеты.

—— Я заинтересован в реальном программировании и исследованиях проектов с открытым исходным кодом.

Мы хорошо понимаем значение обмена информацией.Как взаимодействуют процессы в сети?Например, когда мы каждый день открываем браузер для просмотра веб-страниц, как процесс браузера взаимодействует с веб-сервером? Когда вы используете QQ для чата, как процесс QQ взаимодействует с сервером или процессом QQ, на котором находятся ваши друзья? Все они должны полагаться на сокет? Итак, что такое сокет? Какие есть типы розеток? Есть также основные функции сокета, которые мы хотим представить в этой статье. Основное содержание этой статьи следующее:

  • 1. Как общаться между процессами в сети?
  • 2. Что такое сокет?
  • 3. Основные операции сокета
    • 3.1, функция сокета ()
    • 3.2, BING () Функция
    • 3.3, функции listen(), connect()
    • 3.4, функция accept()
    • 3.5, функции read(), write() и т. д.
    • 3.6, функция закрытия()
  • 4. Подробное объяснение трехстороннего рукопожатия TCP в сокете для установления соединения.
  • 5. Подробное объяснение соединения TCP с четырехсторонним рукопожатием в сокете.
  • 6. Пример (практика)
  • 7. Оставьте вопрос, добро пожаловать на ответ! ! !

1. Как общаться между процессами в сети?

Существует много способов локального межпроцессного взаимодействия (IPC), но их можно свести к следующим четырем категориям:

  • Обмен сообщениями (каналы, FIFO, очереди сообщений)
  • Синхронизация (мьютексы, условные переменные, блокировки чтения-записи, блокировки файла и записи-записи, семафоры)
  • Общая память (анонимная и именованная)
  • Удаленные процедуры вызовы (ворота Solaris и Sun RPC)

Но это не тема данной статьи! Мы говорим о том, как взаимодействуют процессы в сети? Первая проблема, которую необходимо решить, — как однозначно идентифицировать процесс, иначе коммуникация будет невозможна! Локально процесс может быть однозначно идентифицирован по его PID процесса, но это не работает в сети. Фактически набор протоколов TCP/IP помог нам решить эту проблему.айпи адрес"может однозначно идентифицировать хосты в сети, а транспортный уровень"Протокол + порт" может однозначно идентифицировать приложение (процесс) на хосте. Таким образом, тройка (IP-адрес, протокол, порт) может использоваться для идентификации процесса в сети, а связь процесса в сети может использовать этот флаг для взаимодействовать с другими процессами.

Используя интерфейсы прикладного программирования протокола TCP / IP, обычно используемые приложения: сокет UNIX BSD (Socket) TLI и UNIX System V (он был устранен), для сетевой связи между процессами. На данный момент почти все приложения основаны на сокетах, но сейчас век Интернета, обмен данными по сетевым процессам повсюду, поэтому я говорю «Все сокеты».

2. Что такое сокет?

Выше мы уже знаем, что процессы в сети взаимодействуют через сокеты, так что же такое сокет? Socket произошел от Unix, и одна из основных философий Unix/Linux заключается в том, что «все является файлом», с которым можно работать в режиме «открыть открыть -> прочитать и записать запись/чтение -> закрыть закрыть». Насколько я понимаю, Socket — это реализация этого режима, сокет — это специальный файл, а некоторые функции сокета — это операции с ним (чтение/запись ввода-вывода, открытие, закрытие), и мы представим эти функции позже.

Происхождение слова гнездо

Первое использование в области сетей было в литературе, опубликованной 12 февраля 1970 г.IETF RFC33Найдено в , написано Стивеном Карром, Стивом Крокером и Винтом Серфом. Согласно Американскому музею компьютерной истории, Крокер писал: «Элементы пространства имен могут называться интерфейсами сокетов. Интерфейс сокета представляет собой один конец соединения, а соединение может быть полностью определено парой интерфейсов сокета. Музей компьютерной истории добавил: «Это предшествует определению интерфейса сокетов в BSD примерно на 12 лет».

3. Основные операции сокета

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

3.1, функция сокета()

int socket(int domain, int type, int protocol);

Функция сокета соответствует операции открытия обычного файла. Обычная операция открытия файла возвращает дескриптор файла, в то время какsocket()Используется для создания дескриптора сокета (socket descriptor), который однозначно идентифицирует сокет. Это слово описания сокета совпадает со словом описания файла, оно используется в последующих операциях и используется в качестве параметра для выполнения некоторых операций чтения и записи.

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

  • домен: Домен протокола, также известный как семейство протоколов. Обычно используемые семейства протоколов: AF_INET, AF_INET6, AF_LOCAL (или AF_UNIX, сокет домена Unix), AF_ROUTE и так далее. Семейство протоколов определяет тип адреса сокета, и соответствующий адрес должен использоваться при обмене данными.Например, AF_INET решает использовать комбинацию адреса ipv4 (32-разрядного) и номера порта (16-разрядного), AF_UNIX решает использовать использовать абсолютный путь в качестве адреса.
  • тип: определяет тип сокета. Обычно используемые типы сокетов: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_PACKET, SOCK_SEQPACKET и т. д. (какие типы сокетов?).
  • Протокол: как следует из названия, он предназначен для указания протокола. Обычно используемые протоколы: IPPROTO_TCP, IPPTOTO_UDP, IPPROTO_SCTP, IPPROTO_TIPC и т. д., которые соответствуют транспортному протоколу TCP, транспортному протоколу UDP, транспортному протоколу STCP, транспортному протоколу TIPC (об этом протоколе я расскажу отдельно!).

Примечание. Это не означает, что вышеуказанные типы и протоколы можно комбинировать по желанию, например, SOCK_STREAM нельзя комбинировать с IPPROTO_UDP. Если протокол равен 0, автоматически выбирается протокол по умолчанию, соответствующий типу типа.

когда мы звонимsocketПри создании сокета возвращаемое слово описания сокета существует в пространстве семейства протоколов (семейство адресов, AF_XXX), но не имеет определенного адреса. Если вы хотите присвоить ему адрес, вы должны вызвать функцию bind(), иначе система автоматически назначит порт случайным образом, когда вы вызываете connect() и listen().

3.2, функция привязки()

Как упоминалось выше, функция bind() назначает сокету определенный адрес в семействе адресов. Например, соответствие AF_INET и AF_INET6 означает присвоение сокету комбинации адреса ipv4 или ipv6 и номера порта.

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

Три параметра функции:

  • sockfd: слово описания сокета, которое создается функцией socket() и однозначно идентифицирует сокет. Функция bind() предназначена для привязки имени к этому дескриптору.
  • addr: указатель const struct sockaddr * на адрес протокола, который будет привязан к sockfd. Эта структура адреса отличается в зависимости от семейства протоколов адресов при создании сокета.Например, ipv4 соответствует:
    struct sockaddr_in {
        sa_family_t    sin_family; /* address family: AF_INET */
        in_port_t      sin_port;   /* port in network byte order */
        struct in_addr sin_addr;   /* internet address */
    };
    
    /* Internet address. */
    struct in_addr {
        uint32_t       s_addr;     /* address in network byte order */
    };
    ipv6 соответствует:
    struct sockaddr_in6 { 
        sa_family_t     sin6_family;   /* AF_INET6 */ 
        in_port_t       sin6_port;     /* port number */ 
        uint32_t        sin6_flowinfo; /* IPv6 flow information */ 
        struct in6_addr sin6_addr;     /* IPv6 address */ 
        uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */ 
    };
    
    struct in6_addr { 
        unsigned char   s6_addr[16];   /* IPv6 address */ 
    };
    Домен Unix соответствует:
    #define UNIX_PATH_MAX    108
    
    struct sockaddr_un { 
        sa_family_t sun_family;               /* AF_UNIX */ 
        char        sun_path[UNIX_PATH_MAX];  /* pathname */ 
    };
  • addrlen: соответствует длине адреса.

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

Порядок байтов в сети и порядок байтов хоста

порядок байтов хостаЭто то, что мы обычно называем режимами big-endian и little-endian: разные процессоры имеют разные типы порядка байтов, которые относятся к порядку, в котором целые числа хранятся в памяти, который называется порядком хоста. Определения Big-Endian и Little-Endian со ссылкой на стандарт следующие:

а) Little-Endian означает, что младшие байты размещаются в конце памяти с младшим адресом, а старшие байты размещаются в конце памяти с высоким адресом.

b) Big-Endian означает, что байты с высоким порядком размещаются на нижнем окончании адреса памяти, а байты с низким уровнем порядка размещаются на высоком окончании памяти.

сетевой порядок байтов: 32-битное значение из 4 байтов передается в следующем порядке: сначала 0~7 бит, затем 8~15 бит, затем 16~23 бит и, наконец, 24~31 бит. Такой порядок передачи называется прямым порядком байтов.Поскольку все двоичные целые числа в заголовке TCP/IP должны быть в этом порядке при передаче по сети, этот порядок также называется сетевым порядком байтов.Порядок байтов, как следует из названия, — это порядок, в котором данные более чем одного байтового типа хранятся в памяти.С порядком одного байта данных проблем нет.

Итак: при привязке адреса к сокету сначала преобразуйте порядок байтов хоста в сетевой порядок байтов, вместо того, чтобы предполагать, что порядок байтов хоста совпадает с порядком байтов сети, используя Big-Endian. Из-за этой проблемы произошло кровопролитие! Из-за этой проблемы в коде проекта компании возникает множество необъяснимых проблем, поэтому помните, что не следует делать никаких предположений о порядке байтов хоста, и обязательно преобразовать его в сетевой порядок байтов и назначить его сокету.

3.3, функции listen(), connect()

Если он вызывается как сервер, listen() будет вызываться после вызова socket(), а если клиент вызывает connect(), выдает запрос на соединение, сервер получит этот запрос.

int listen(int sockfd, int backlog);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

Первый параметр функции listen — это описание контролируемого сокета, а второй параметр — максимальное количество подключений, которые может поставить в очередь соответствующий сокет. Сокет, созданный функцией socket(), по умолчанию имеет активный тип, а функция listen превращает сокет в пассивный тип, ожидая запроса на подключение от клиента.

Первый параметр функции подключения — это дескриптор сокета клиента, второй параметр — адрес сокета сервера, а третий параметр — длина адреса сокета. Клиент устанавливает соединение с TCP-сервером, вызывая функцию соединения.

3.4, функция accept()

После того, как TCP-сервер вызовет socket(), bind() и listen() по очереди, он будет прослушивать указанный адрес сокета. После того, как TCP-клиент поочередно вызывает socket() и connect(), он отправляет запрос на подключение к TCP-серверу. После того, как сервер TCP прослушает запрос, он вызовет функцию accept() для получения запроса, чтобы установить соединение. После этого можно запускать сетевые операции ввода-вывода, то есть операции чтения и записи ввода-вывода, аналогичные обычным файлам.

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

Первый параметр функции accept — это дескриптор сокета сервера, второй параметр — указатель на структуру sockaddr *, которая используется для возврата адреса протокола клиента, а третий параметр — длина адреса протокола. Если accpet завершается успешно, возвращаемое значение представляет собой совершенно новый дескриптор, автоматически сгенерированный ядром, представляющий TCP-соединение с вернувшимся клиентом.

Примечание. Первый параметр приема - это описание сокета сервера, которое генерируется сервером, вызывающим функцию Socket (), которая называется описанием сокета прослушивания; и функция ACCECT возвращает описание подключенного разъема. Сервер обычно создает только дескриптор сокета прослушивания, который существует для срока службы сервера. Ядро создает подключенный дескриптор сокета для каждого клиентского соединения, принятого процессом сервера. Когда сервер завершает обслуживание клиенту, соответствующий подключенный дескриптор сокета закрыт.

3.5, прочитайте (), напишите () и другие функции

Все на месте и только должен Dongfeng, пока сервер и клиент установили хорошее соединение. Вы можете вызывать сетевой ввод-вывод для операций чтения и записи, то есть для реализации связи между различными процессами в сети! Существует несколько групп сетевых операций ввода-вывода:

  • read()/write()
  • recv()/send()
  • readv()/writev()
  • recvmsg()/sendmsg()
  • recvfrom()/sendto()

Я рекомендую использовать функции recvmsg()/sendmsg(), эти две функции являются наиболее общими функциями ввода-вывода, и вы можете фактически заменить другие функции выше этими двумя функциями. Они объявляются следующим образом:

       #include <unistd.h>

       ssize_t read(int fd, void *buf, size_t count);
       ssize_t write(int fd, const void *buf, size_t count);

       #include <sys/types.h>
       #include <sys/socket.h>

       ssize_t send(int sockfd, const void *buf, size_t len, int flags);
       ssize_t recv(int sockfd, void *buf, size_t len, int flags);

       ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);
       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

       ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
       ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

Функция чтения отвечает за чтение содержимого из fd.При успешном чтении read возвращает фактическое количество прочитанных байт.Если возвращаемое значение равно 0, это означает, что прочитан конец файла, а меньше 0 означает произошла ошибка. Если ошибка EINTR, чтение вызвано прерыванием, а если ECONNREST, проблема с сетевым подключением.

Функция записи записывает nbytes байтов из buf в файловый дескриптор fd и возвращает количество записанных байтов в случае успеха. Возвращает -1 в случае ошибки и устанавливает переменную errno. В сетевой программе есть две возможности записи в файловый дескриптор сокета. 1) Возвращаемое значение записи больше 0, что указывает на то, что часть или все данные были записаны. 2) Возвращаемое значение меньше 0, и произошла ошибка. Мы хотим обрабатывать в соответствии с типом ошибки. Если ошибка EINTR, во время записи произошла ошибка прерывания. Если это EPIPE, это означает, что есть проблема с сетевым подключением (другая сторона закрыла соединение).

Я не буду представлять эти пары функций ввода-вывода одну за другой. За подробностями обращайтесь к документу man или baidu и Google.В следующем примере будет использоваться send/recv.

3.6, функция закрытия()

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

#include <unistd.h>
int close(int fd);

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

Примечание: Операция закрытия только делает счетчик ссылок соответствующего слова описания сокета равным 1. Только когда счетчик ссылок равен 0, клиент TCP инициируется для отправки запроса на завершение соединения на сервер.

4. Подробное объяснение трехстороннего рукопожатия TCP в сокете для установления соединения.

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

  • Клиент отправляет SYN J на ​​сервер
  • Сервер отвечает клиенту с помощью SYN K и подтверждает SYN J с помощью ACK J+1.
  • Клиент хочет, чтобы сервер отправил подтверждение ACK K+1

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

image

Рис. 1. Трехстороннее рукопожатие TCP, отправленное в сокет

Как видно из рисунка, когда клиент вызывает соединение, срабатывает запрос на соединение, и на сервер отправляется пакет SYN J. В это время соединение переходит в состояние блокировки, сервер прослушивает запрос на соединение, т.е. получает пакет SYN J и вызывает функцию accept.Запрос на получение отправляет SYN K, ACK J+1 клиенту, затем accept переходит в состояние блокировки; после того, как клиент получает SYN K, ACK J+1 от сервера, затем соединение возвращает и подтверждает SYN K; сервер получает Когда он достигает ACK K+1, возвращается accept, пока трехстороннее рукопожатие завершено, и соединение установлено.

Резюме: соединение клиента возвращается во второй раз трехстороннего рукопожатия, а согласие на стороне сервера возвращается в третий раз трехстороннего рукопожатия.

5. Подробное объяснение соединения TCP с четырехсторонним рукопожатием в сокете.

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

image

Рисунок 2. Четырехэтапное рукопожатие TCP, отправленное в сокет

Иллюстрированный процесс выглядит следующим образом:

  • Процесс приложения сначала вызывает close, чтобы активно закрыть соединение, затем TCP отправляет FIN M;
  • После того, как другой конец получает FIN M, он выполняет пассивное отключение для подтверждения FIN. Его получение также передается процессу приложения как символ конца файла, потому что получение FIN означает, что процесс приложения больше не может получать дополнительные данные по соответствующему соединению;
  • Через некоторое время процесс приложения, получивший символ конца файла, вызывает метод close, чтобы закрыть свой сокет. Это приводит к тому, что его TCP также отправляет FIN N;
  • Получение этого отправляющего источника TCP FIN для его подтверждения.

Таким образом, есть FIN и ACK в каждом направлении.

6. Пример (практика)

Хватит говорить, давайте тренироваться. Давайте напишем простой сервер и клиент (используя TCP) - сервер всегда слушает порт 6666 машины. Если он получает запрос на соединение, он получит запрос и получит сообщение от клиента, клиент и сервер устанавливают соединение и отправить сообщение.

Код на стороне сервера:

Сервис-терминал
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>

#define MAXLINE 4096

int main(int argc, char** argv)
{
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[4096];
int n;

if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}

memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6666);

if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}

if( listen(listenfd, 10) == -1){
printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}

printf("======waiting for client's request======\n");
while(1){
if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){
printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
continue;
}
n = recv(connfd, buff, MAXLINE, 0);
buff[n] = '\0';
printf("recv msg from client: %s\n", buff);
close(connfd);
}

close(listenfd);
}

Код клиента:

клиент
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>

#define MAXLINE 4096

int main(int argc, char** argv)
{
int sockfd, n;
char recvline[4096], sendline[4096];
struct sockaddr_in servaddr;

if( argc != 2){
printf("usage: ./client <ipaddress>\n");
exit(0);
}

if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
exit(0);
}

memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6666);
if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
printf("inet_pton error for %s\n",argv[1]);
exit(0);
}

if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}

printf("send msg to server: \n");
fgets(sendline, 4096, stdin);
if( send(sockfd, sendline, strlen(sendline), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}

close(sockfd);
exit(0);
}

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

7. Двигайте руками

Оставьте вопрос, каждый может ответить! ! ! Вы знакомы с сетевым программированием под Linux? Если вы знакомы, напишите следующую программу для выполнения следующих функций:

Сервис-терминал:

Получить информацию о клиенте по адресу 192.168.100.2,Если информация «Запрос клиента», выведите «Получить запрос».

Клиент:

Отправьте сообщение «Client Query test», «Cleint Query», «Client Query Quit» 192.168.100.168 последовательных адресов на сервер, а затем выйдите.

IP-адрес, указанный в вопросе, можно определить в зависимости от реальной ситуации.

- В этой статье рассказывается только о простом программировании сокетов.

Более сложные должны продолжать идти глубже.

(сокет домена unix) с использованием udp для отправки> = 128K сообщений сообщит об ошибке ENOBUFS(Проблема, возникающая при реальном программировании сокетов, надеюсь, она вам поможет)

Автор: У Цинь
Источник: http://www.cnblogs.com/skynet/
Эта статья основана наАтрибуция 2.5 Материковый КитайЛицензионное соглашение выпущено, добро пожаловать на перепечатку, вывод или использование в коммерческих целях, но авторство этой статьи должно быть сохранено.У Цинь(содержит ссылку).

< Prev12 Add your comment

  1. № 51 u011603302   2014-07-01 19:11
    socket base, mark Поддержка(0)против (0)
  2. №52 Этаж sjtufighter   2014-07-28 10:43
    очень замечательно, спасибо, что поделилисьПоддержка(0)против (0)
  3. №53 Этаж окрашенный старый   2014-10-09 15:22
    if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) Изменился только код:
    char IPdotdec[20]; //Сохраняем IP-адрес в десятичном формате
    printf("please input ip address");
    scanf("%s",IPdotdec);
    inet_pton(AF_INET,IPdotdec,&servaddr.sin_addr)Поддержка(0)против (0)
  4. №54 Этаж окрашенный старый   2014-10-09 15:24
    Этот sizeof(servaddr) равен 16Поддержка(0)против (0)
  5. # 55 этаж zzf-bingo   2014-11-26 09:50
    Хорошая статья! Тем не менее, я нахожу момент, не нашел, что последующее открытие сокета отделит вас, говорите (ах, только объяснение) в поле протокола? (Говорят, что для того, чтобы отписаться от вас, я специально зарегистрировал аккаунт в садовом блоге...)Поддержка(0)против (0)
  6. №56 Этаж jueying_8888   2015-01-28 08:50
    хорошая статья, маркПоддержка(0)против (0)
  7. №57 Этаж не преследовать   2015-02-27 16:27
    Что делать, если я хочу перезапустить сервер, но сокет не закрывается в течение всего процесса, то есть я все еще могу получить запрос от клиента, а просто закешировать его и продолжить обработку после успешного перезапуска сервера? ?Поддержка(0)против (0)http://pic.cnblogs.com/face/u303875.gif?id=26210113
  8. №58 Этаж[арендодатель] У Цинь   2015-02-27 16:30
    @не преследуй
    ЦитироватьЧто делать, если я хочу перезапустить сервер, но сокет не закрывается в течение всего процесса, то есть я все еще могу получить запрос от клиента, а просто закешировать его и продолжить обработку после успешного перезапуска сервера? ?
    Вы можете обратиться к практике «плавного перезапуска и плавного обновления nginx».Поддержка(0) против (0)http://pic.cnblogs.com/face/u92071.jpg
  9. Дом # 59. roger9567   2015-04-14 00:30
    nice! Поддержка(0)против (0)
  10. №60 Этаж Ле Анджу   2015-06-03 15:44
    Действительно хорошо написано. В прошлом «несколько рукопожатий» были просто понятием, и эта картинка очень подробно объясняет его!Поддержка(0)против (0)
  11. Дом № 61 Sawyer Ford   2015-06-09 21:18
    Объяснить очень хорошоПоддержка(0)против (0)http://pic.cnblogs.com/face/565026/20141119212220.png
  12. №62 Этаж myg   2015-06-21 17:25
    Арендодатель:
    Сервер прослушивает запрос на соединение, то есть получает пакет SYN J, и вызывает функцию принятия для получения запроса на отправку клиенту SYN K, ACK J + 1. В это время accept переходит в состояние блокировки; есть проблема с этим предложением! !
    Если сервер не вызывает функцию принятия, он все равно отправит клиенту сообщение SYN+ACK! ! !Поддержка(0)против (0)
  13. №63 Этаж нет другого   2015-07-23 22:22
    Прежде всего, спасибо хозяину за галантерейные товары, я думаю, что я должен посмотреть его снова.Поддержка(0)против (0)
  14. №64 Этаж Лет вилла   2015-11-17 11:07
    Здравствуйте, арендодатель, «Сервер прослушивает запрос на подключение, то есть получает пакет SYN J, и вызывает функцию принятия, чтобы получить запрос на отправку SYN K, ACK J+1 клиенту. В это время accept входит состояние блокировки». Что-то не так с предложением. Когда клиент отправляет SYN K, ACK J+1, нет необходимости вызывать функцию приема. Функция вызова приема состоит в том, чтобы взять из очереди TCP тот, который установил соединение.Поддержка(0) против (0)
  15. №65 Этаж У Лао Эр   2015-12-28 10:40
    хорошая статьяПоддержка(0)против (0)http://pic.cnblogs.com/face/828194/20151027113020.png
  16. №66 Этаж Tomasmule   2016-04-19 11:58
    Только открыл блог-сад, уже фанатыПоддержка(0)против (0)
  17. №67 Этаж Программист -- меньше остановок   2017-04-17 14:03
    ХвалитьПоддержка(0)против (0)http://pic.cnblogs.com/face/781239/20170930105542.png
  18. №68 Этаж бесстрашный бесстрашный   2017-06-19 11:51
    хорошо, как одинПоддержка(0)против (0)http://pic.cnblogs.com/face/726451/20150302175807.png
  19. Дом № 69 Apprentice_saber   2017-07-24 19:19
    Спасибо хозяину за хороший материал. поставь лайк! ! !Поддержка(0)против (0)
  20. №70 Этаж беги, зайчик   2017-09-11 18:04
    Блестяще, спасибо.Поддержка(0)против (0)http://pic.cnblogs.com/face/990360/20170523180602.png
  21. №71 Этаж KRCheung   2017-12-05 21:57
    Редко у владельца хватает духу это организовать! благодарный!Поддержка(0)против (0)http://pic.cnblogs.com/face/1066524/20170227130418.png
  22. # 72 этаж перо работает не покладая рук   2017-12-06 10:34
    Действительно удивительным. . отметка .Поддержка(0)против (0)
  23. №73 Этаж38616902017/12/9 13:54:10 ~Дождь идет грустный~   2017-12-09 13:54
    очень хорошийПоддержка(0)против (0)http://pic.cnblogs.com/face/856389/20171120165836.png
< Prev12 обновить комментарийобновить страницуBack to topЗарегистрированные пользователи могут оставлять комментарии только после авторизации.Авторизоватьсяилирегистр,доступдомашняя страница сайта.[Рекомендуется] Более 500 000 исходных кодов VC++: крупномасштабное промышленное управление, конфигурация\моделирование, моделирование, исходный код САПР 2018!
[Рекомендация] Как выгоднее купить облачный сервер Tencent?
SpreadJS2_1206 Последние ИТ-новости:
· Зайди на сайт LeTV, заплати один раз, потерял 300 GEM прибыли
· Краудфандинг-кровать и завтрак Горячий круг друзей, почему я не оптимистично к этому?
· Рост пользователей Facebook замедляется, руководители: это всего лишь временное явление
· Если iPhone X «убили», кто настоящий виновник?
· Сколько представителей среднего класса попали в «ловушку среднего дохода»?
» больше новостей... 阿里云C2-1208 Последние статьи базы знаний:
· Практика доменно-ориентированного проектирования в развитии интернет-бизнеса
· Шаг в облачных вычислениях
· Описывать потоки и процессы с точки зрения операционной системы.
· Путь к трансформации тестирования программного обеспечения
· Посмотрите внутри и снаружи двери, чтобы увидеть набор
» Другие статьи базы знаний...

About

Никнейм:У Цинь
Возраст сада:8 лет 3 месяца
честь:Рекомендуемый блог
вентилятор:3504
обрати внимание на:18 +Добавить подписку

последнее эссе

последний комментарий

Архив эссе

календарь

< декабрь 2010 г. >
день один два три Четыре пять шесть
28 29 30 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8

классификация эссе

Рекомендуемая таблица лидеров

Читать таблицу лидеров

Серия Индекс Сообщений

www.spiga.com.mx

Copyright © 2018 У Цинь

Блог Парк