Русские Блоги
После изучения Linux я узнал, что сетевое программирование в рамках системы Linux очень интересно. Здесь давайте поговорим о TCP/IP.Это соединение и надежный набор протоколов, И этоНа постоянной основеКоммуникация. Его существование делает интернет -мир красочным. Ядро Linux предоставит ряд функций, которые помогут нам завершить сетевое программирование.
Если вы хотите узнать сетевое программирование, вы должны сначала это знатьУстановить соединение, передача данных, отключить соединениеВ ожидании процесса.
Мы знаем, что текущие 5 слоев распознаются с низкого уровня ::Физический уровень, уровень канала данных, транспортный уровень, сетевой уровень, уровень приложения. Основное обсуждение здесьТранспортный слой является слоем TCP.
Три рукопожатия (три рукопожатия)
Мы знаем, что для создания соединения TCP требуется три ситуации рукопожатия。
- Сервер должен быть готов принять иностранные соединения. Это обычно называется вызовомsocket,bindа такжеlistenЭти три функции выполнены (эти три функции упоминаются ниже), которые называются пассивными открытыми здесь.
- Клиенты инициируют Active Open, вызывая Connect. Это заставляет клиента TCP отправлять одинSYNВ разделе он сообщает начальному номеру последовательности клиента сервера данных отправленных данных (которые будут установлены). обычноSYN не несет данные в разделах. IP -пакет, где его IP содержит только один IP -адрес сначала, сначала TCPИ возможноОпция TCP.
- Сервер долженОК (ACK) SYN клиентаВ то же время вы должны отправить одинSyn sub -section,Он содержит начальный номер последовательности данных, отправляемых сервером в одном и том же соединенииСущность Сервер отправляет Syn и Syn иACK (подтвержденный) клиента Syn.
- Клиенты должны быть определеныСин сервера。
Этот обмен требует как минимум 3 группы, поэтому он называется трехбое рукопожатие TCP. Как показано ниже
Размахивая четыре раза
Соединение TCP прекращается, и 4 балла требуются
- Процесс подачи заявки сначала вызовы ** Закройте, и ** мы называем конечное выполнение Active Clos. TCP конца отправил раздел FIN, что указывает на то, что данные были отправлены.
- Получите пассивное закрытие окончания -до -ендическое выполнение. Этот плавник подтвержден TCP.Его прием также передается в процесс получения подачи заявления в качестве конца файла(После ожидания в очереди, чтобы дождаться любых других данных, полученных в процессе подачи заявления),),Потому что получение плавника означает, что нет дополнительных данных о соответствующем подключении процесса приема приема.
- Спустя некоторое время,Процесс подачи заявки на получение окончания этого файла позвонит, чтобы закрыть ее сокетСущность Это заставляет его TCP отправлять плавник.
- Получите окончательный деривативный конец этого окончательного TCP(То есть конец активного отключения) Подтвердите этот плавник.
Теперь этоОдин плавник и ACK требуют каждого направленияТак что обычно нужно4 баллаСущность Мы используем ограниченное слово «обычно», потому что:В некоторых случаях плавник шага 1 отправляется с данными; кроме того, подразделы, отправленные на шаг 2 и шаг 3, с конца пассивного отключения, которые могут быть объединены в подраздел。
Процесс, как показано ниже
На рисунке ниже показан фактический групповой обмен полным соединением TCP.Включая установление соединения, обмен данными и прекращение трех этапов.
Основное программирование прокрутки TCP
Система C/S в основном принята здесь, то естьПрограмма клиента/сервераСущность Если вы хотите выполнить ввод/вывод сети, первое, что должно быть сделано в процессе, этоВызовите функцию сокетаИ укажите ожидаемый тип протокола (IPv4 TCP, IPv6 UDP, протокол бега Unix Homenion и т. Д.).
1. Сервер
1. Функция
Используется для создания набора мониторинга, чтобы узнать, кто хочет меня подключить
Файл заголовка: #include
Функциональный корпус: int socket (int family, int type, int protocol);
Возврат: успех возвращает неотрицательные дескрипторы, а ошибки —1
вСемейный параметр указывает соглашение, Обычно это определенное количество следующих цифр:
Параметр типа указывает тип набора словОбычно это ценность подчиненного:
Параметр протокола должен быть установлен на длинное правило типа протокола, как показано ниже, или установить на 0, чтобы выбрать значения по умолчанию, указанные данной системой комбинации семейства и типа.
Функция сокета вернет небольшое полетное значение после успешного выполнения. Она похожа на дескриптор файла. Мы называем егоУпакованный символ дескриптораЧтобы получить этоПомещение дескриптора персонажа,Мы толькоУкажите тип типа протокола и розетки,а такжеНет указанного локального адреса протокола или удаленного адреса протокола。
2. Функция связывания
Функция связывания дает локальный адрес протокола в розетку
Файл заголовка: #include
Функциональное тело: int bind (int sockfd, const struct sockaddr * myaddr, socklen_t addrlen);
ВЕРНАТЬ: Вернуться к 0, а ошибка —1
вышеФункция сокетаВернуться к дескриптору упаковки,Его сущность — дескриптор файлаРазница в том, что он является дескриптором сети,Через серию,Как показано ниже:
Теперь, когда розетка была создана, я хочу позволить другим подключить меня, тогда я должен раскрыть свой IP -адрес и номер порта.Затем функция BIND играет эту роль. Он используется для привязки IP -адреса и порта, чтобы облегчить другим подключить нас.
Первый параметр: sockfdЭто значение мониторинга функции сокета успешно возвращаемой.
Второй параметр: указатель на структуру struct sockaddr,struct sockaddrЭто общая структура,Поскольку ядро не знает, что IPv4, который я хочу связать, или даже IPv6 или даже привязывать другие вещи.Поэтому здесь разработана универсальная структура, чтобы облегчить программистам решить, что нужно связано.Например, структура IPv4 заключается в следующем:
struct sockaddr_in sa_family_t sin_family;/*Адрес: af_inet*/ u_int16_t sin_port;/*Порт в соответствии с заказами сетевого байта*/ struct in_addr sin_addr;/*Интернет -адрес, то есть IP -адрес*/ > /*Интернет -адрес*/ struct in_addr u_int32_t s_addr/*В соответствии с адресом заказа байта сети*/ >
Третий параметр: addrlen Размер второго параметра.
Здесь стоит упомянуть, что, поскольку данные передаются через сеть, то еслиБайт -порядок двух сторон разныеТогда передаваемые данные не могут быть использованы, поэтомуУпомянуто, что данные о передаче в сети должны использоваться в порядке сетевого байтаСистема предоставила набор функций преобразования заказа байтов:
#include // эта последовательность байтов -конверсии заказа на машине конверсии заказа uint32_t htonl(uint32_t hostlong);// 32 -bit uint16_t htons(uint16_t hostshort);// 16 // сетевой байт -конверсия uint32_t ntohl(uint32_t netlong);// 32 -bit uint16_t ntohs(uint16_t netshort);// 16
h:host n:net l:int s:short
После привязки он эквивалентен моему IP -адресу и номеру порта, который может быть подключен ко мне, но он все еще не может быть подключен здесь.Чтобы пройти функцию прослушивания, преобразовать ее в пассивные слова。
Слушать функцию
Слушать функциюБудутПрослушиваниеКонвертироватьПассивныйСущность Цель пассивных словОн используется, чтобы позволить другим соединить нас.
Файл заголовка: #include
Функциональный корпус: int listn (int sockfd, int backlog)
Первый параметр: sockfd — это сокет мониторинга
Точка является вторым параметром: отставание
Функция Listn создаст две очереди, СоответственноОчередь, которая не была завершена три разаа такжеОчередь, которая была завершена три разаОбъясните в некоторых книгахОтстава — это сумма размера этих двух очередей,Тем не менее, размер трех очереди рукопожатия теперь изменился.
Когда вы закончите три рукопожатия, вы позвоните функции доступа.
Принять функцию
Функция приема вызывается TCP и возвращает следующее завершенное соединение с доменом из очереди, которая завершила три подключения рукопожатия.
Лучшее понимание здесь заключается в том, что, например, я набрал 78888, затем, когда я набрал, я буду переведен. В этом случае другой человек все еще может набрать, когда вы звоните по этому вызову.Затем 78888 эквивалентен набору мониторинга, Я знаю, кто позвонил мне, и передача после набора эквивалентнаИстинное соединение Джин, Хозяин разговаривал с людьми.Следовательно, функция Accept будет вызвать новый розетка из нового способа создания нового розетки, который используется для действительно подключения к вызовам
Файл заголовка: #include
Функциональный корпус: int Access (int sockfd, struct sockaddr * cliaddr, socketlen_t addrlen)
Возврат: успех возвращает неотрицательные дескрипторы, а ошибки —1
Функция принятия является функцией блокировки. Когда соединение установлено, ядро будет даватьСигнал,Просните эту функцию блокировки и создайте новый розетка, затем вам нужно знать мой адрес и порт идентификатор, поэтому второй параметр все еще указывает на указатель на структуру struct sockaddr.,Третий параметр — это размер этой структурыСущность Когда функция доступа к успешному вызвана, сервер должен только дождаться подключения клиента кЗапустите данные передачи и обработки данных!
Во -вторых, клиент
Когда сервер будет завершен, клиент должен быть создан.
Клиент сначала нуждаетсяВызовите функцию сокетаПоскольку он должен подключиться к серверу, для подключения требуется розетка. здесьФункция связывания не требуетсяТак же, как я звоню 110, я могу позвонить 110 с любым телефоном, и я не предусматриваю, что число 110 может быть только определенным номером.
После вызова функции сокета клиент должен быть толькоВызовите функцию Connect, чтобы подключиться к серверу。
Подключить функцию
Эта функция используется для подключения к серверуСущность Если это розетка TCP, эта функция будет стимулировать триполосные рукопожатия TCP,И возвращается только тогда, когда соединение успешно или ошибки。
Файл заголовка: #include
Функциональное тело: int connect (int sockfd, const struct sockaddr * servaddr, socklen_t addrlen);
Возврат: успех равен 0, а ошибка —1
Подключить функциюПервый параметр — это розетка, которую я перезвоняю из розетки выше,Второй параметр — это IP -адрес и номер порта сервера,Это указатель на структуру Struct Sockaddr, Последний параметрРазмер этой структуры。
Весь процесс, как показано ниже:
Компиляционная среда, основанная на системе CentOS7
Код сервера
#include #include #include #include #include #include #include // Создать настройки прослушивания int creat_socket() int lfd = 0; lfd = socket(AF_INET,SOCK_STREAM,0); if(lfd == -1) // если не так perror("socket"); exit(1); > printf("Успешное создание мониторинга розетков \ n"); return lfd; > // преобразовать все строчные буквы в данных, отправленных клиентом в заглавное письмо void change(char *p,int size) for(int i = 0;isize;i++) if(p[i] >= 'a' && p[i] 'z') p[i] = p[i] - 32; > > > int main() int lfd = creat_socket();、 // определить IP -адрес и порт struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(6666); inet_aton("192.168.66.66",&addr.sin_addr); // Связывать int r = bind(lfd,(struct sockaddr*)&addr,sizeof(addr)); printf("Бенс успешно \ n"); if(r == -1) perror("bind"); exit(1); > // преобразовать в пассивные слова рукава if((r = listen(lfd,SOMAXCONN)) == -1) perror("listen"); exit(1); > printf(«Пассивные столкновения создаются успешно, дождитесь соединения \ n»); int newfd = accept(lfd,NULL,NULL);// Соединять printf("Есть клиентское соединение \ n"); while(1) char buf[1024] = >; r = read(newfd,buf,1024); if(r == 0) break; > printf("%s\n",buf); change(buf,strlen(buf)); write(newfd,buf,r); > close(lfd); close(newfd); printf("Сервер был отключен \ n"); return 0; >
Клиентский код
#include #include #include #include #include #include #include int main() int lfd = socket(AF_INET,SOCK_STREAM,0);// Создать реактивное слово if(lfd == -1) perror("socket"); exit(1); > // заполнить IP -адрес и номер порта, который я хочу подключить struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(6666); inet_aton("192.168.66.66",&addr.sin_addr); // подключаться с сервером int r = connect(lfd,(struct sockaddr*)&addr,sizeof(addr)); if(r == -1) perror("connect"); exit(1); > char buf[1024] = >;// Читать буферную зону printf("Успешно подключено к серверу \ n"); while(fgets(buf,1024,stdin) != NULL) // Читать с клавиатуры до BUF, и это не пусто write(lfd,buf,strlen(buf));// записать в LFD memset(buf,0x00,sizeof(buf)); r = read(lfd,buf,1024);// Читать из LFD if(r == 0) // представляет соединение отключение close(lfd); break; > printf("%s\n",buf); memset(buf,0x00,sizeof(buf)); > return 0; >
Результат работы
Откройте сторону обслуживания
Откройте клиент
Чтение и обработка данных
Ссылка: Unix Network Programming Том 1: Упаковка Word Network API (3 -е издание)