- C: сокеты и пример модели client-server
- Что такое сокет?
- Socket сервер
- Socket клиент
- Русские Блоги
- Подробное программирование SOCKET в Linux
- 1. Как общаться между процессами в сети
- 4.1, функция socket ()
- 4.2, функция bind ()
- Сетевой порядок байтов и порядок байтов хоста
- 4.3, функции listen (), connect ()
- 4.4, принять () функцию
- 4.5, read (), write () и другие функции
- 4.6, функция close ()
- Интеллектуальная рекомендация
- Используйте Maven для создания собственного архетипа скелета проекта (4)
- Станция интерпретации больших данных B пользуется популярностью среди гигантов района «призрачные животные» Цай Сюкуня.
- Вопрос A: Алгоритм 7-15: алгоритм кратчайшего пути Дейкстры
- Учебный дневник — перелистывание страниц
- Нулевое основание для отдыха-клиента
- Вам также может понравиться
- Подробно объясните, как новички используют sqlmap для выполнения инъекционных атак на базы данных mysql.
- Vue заметки сортируют, пусть вам начать с Vue.js:. 04_3 Сетевое приложение: AXIOS плюс Вью
- Шаблон алгоритма конной повозки
- 35 Line Code, чтобы получить метод исследования событий (ON)
- Образ докера: gitlab
C: сокеты и пример модели client-server
Перевод с дополнениями. Оригинал — тут>>>.
Как правило — два процесса общаются друг с другом с помощью одного из Inter Process Communication (IPC) механизма ядра, таких как:
- pipe
- очереди сообщений (Message queues)
- общая память (shared memory)
Кроме перечисленных IPC — в ядре присутствует много других возможностей, но что если процессам необходимо обмениваться данными по сети?
Тут используется ещё один механизм IPC — сокеты.
Что такое сокет?
Сокеты (англ. socket — разъём) — название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет — абстрактный объект, представляющий конечную точку соединения.
Кратко говоря — существует два типа сокетов — UNIX-сокеты (или сокеты домена UNIX — Unix domain sockets) и INET-сокеты (IP-сокеты, network sockets).
UNIX-сокеты чвляются частью механизма IPC и позволяют обмен данными в обоих направлениях между процессами, работающими на одной машине.
INET-сокеты в свою очередь представляют собой механизм, позволяющий выполнять коммуникацию между процессами по сети.
Грубо говоря — если UNIX-сокет использует файл в файловой системе, то INET-сокет — требует присваивания сетевого адреса и порта.
Больше про сокеты:
Коммуникация в среде TCP/IP происходит по клиент-серверной модели, т.е. — клиент инициализирует связь, а сервер его принимает.
Ниже — пример сервера, который будет работать как демон и ожидать подключения клиента, а при инициализации клиентом соединения — передаст ему дату и время.
Socket сервер
Наш сервер будет выглядеть следующим образом:
Флаг —tcp для netstat указывает на то, что требуется вывести информацию только по INET-сокетам.
Самый простой способ получить данные от нашего сервера — с помощью telnet , проверяем ещё раз:
Теперь — давайте рассмотрим сам код сервера.
- с помощью вызова функции socket() в области ядра создаётся неименованный сокет, и возвращается его socket descriptor
- первым аргументом этой функции передаётся тип домена. Т.к. мы будем использовать сеть — то используем тип сокета AF_INET (IPv4).
- вторым аргументом — SOCK_STREAM , который указывает на тип протокола. Для TCP — это будет SOCK_STREAM , для UDP — SOCK_DGRAM
- третий аргумент оставляем по умолчанию — тут ядро само решит какой тип протокола использовать (т.к. мы указали SOCK_STREAM — то будет выбран TCP)
Далее — вызывается функция bind() :
- bind() создаёт сокет используя параметры из структуры serv_addr (протокол, IP-адрес и порт)
- вызов функции listen() со вторым аргументом 10 указывает на макс. допустимое кол-во подключений. Первым аргументом — передаётся дескриптор сокета, который необходимо прослушивать.
- сервер запускает бесконченый цикл, ожидая входящего соединения, и вызывает accept() , как только соединение установлено. В свою очередь accept() создаёт новый сокет для каждого соединения, вовзращает дескриптор сокета
- как только соединение установлено (т.е. сокет создан) — функция snprintf() вписывает время и дату в буфер, после чего вызывается write() , которая вписывает данные из буфера в сокет
Socket клиент
Перейдём ко второй программе — клиенту.
Код её будет выглядеть следующим образом:
Кратко рассмотрим его:
- аналогично серверу — создаём сокет
- в структуру sockaddr_in с именем serv_addr заносятся протокол, порт (5000) и адрес сервера (первый аргумент — argv[1] )
- функция connect() пытается установить соединение с хостом, используя данные из структуры serv_addr
И в конце-концов — клиент с помощью read() получает данные из своего сокета, в который поступают данные от сокета на сервере.
Собираем клиент, и пробуем подключиться к нашему серверу:
Источник
Русские Блоги
Подробное программирование SOCKET в Linux
1. Как общаться между процессами в сети
Концепция процесса коммуникации возникла из автономной системы. Поскольку каждый процесс выполняется в своем собственном диапазоне адресов, чтобы обеспечить
Оба процесса не мешают друг другу и работают в унисон. Операционная система предоставляет соответствующие средства для взаимодействия процессов, такие как
UNIX BSD имеет: Трубопровод (труба), Именованная труба Мягкий сигнал прерывания (сигнал)
UNIX система V имеет: сообщение, общая область хранения (Общая память) и семафор.
Они ограничены связью между нативными процессами. Связь между сетевыми процессами Это проблема взаимного взаимодействия между различными процессами хоста (может рассматривать взаимодействие одного и того же процесса как особый случай между ними). По этой причине, первое, что нужно решить, это войти в сеть. Проблема идентификации процесса. На одном и том же хосте разные процессы могут быть однозначно идентифицированы по идентификатору процесса (идентификатор процесса). Однако в сетевой среде каждый хост работает независимо Назначенный номер процесса не может однозначно идентифицировать процесс. Например, если хост A назначен процессу № 5, также может быть процесс № 5 в машине B. Следовательно, «№ 5 «Процесс» не имеет смысла. Во-вторых, операционная система поддерживает множество сетевых протоколов: разные протоколы работают по-разному, а форматы адресов разные. Поэтому межпроцессное взаимодействие все еще возвращается. Решить проблему идентификации нескольких протоколов.
Фактически, семейство протоколов TCP / IP помогло нам решить эту проблему. Сетевой уровень »IP-адрес” Можно однозначно идентифицировать хосты в сети, пока Транспортный уровень «Протокол + порт” Может однозначно идентифицировать приложения (процессы) на хосте. Таким образом, триплет (IP-адрес, протокол, порт) может использоваться для идентификации процесса в сети, а обмен данными между процессами в сети может использовать этот флаг для взаимодействия с другими процессами.
Приложения, использующие протокол TCP / IP, обычно используют интерфейсы прикладного программирования: сокеты UNIX для BSD и TLI для системы UNIX V ( Был исключен) для достижения связи между сетевыми процессами. На данный момент почти все приложения используют сокеты, и сейчас настал век сети. Связи процессов в сети нигде нет. здесь нет. Вот почему я говорю: «все является сокетом». «.
2. Что такое TCP / IP, UDP
TCP / IP (Протокол управления передачей / Интернет-протокол) — это набор отраслевых стандартных протоколов, предназначенный для глобальных сетей (WAN).
UDP (User Data Protocol, User Datagram Protocol) — это протокол, соответствующий TCP. Он принадлежит к семейству протоколов TCP / IP. Как показано на рисунке:
Семейство протоколов TCP / IP включает в себя транспортный уровень, сетевой уровень и канальный уровень.
Сокет показан на рисунке ниже. Сокет — это промежуточный уровень абстракции программного обеспечения для связи между прикладным уровнем и семейством протоколов TCP / IP.
3. Что такое сокет
сокет возник из Unix, и одна из основных философий Unix / Linux — «все это файл», вы можете использовать «open open-> read и write write / read-> Закрыть «режим для работы. Сокет является реализацией этого шаблона, сокет — это специальный файл, и некоторые функции сокета являются операциями над ним (чтение / запись IO, open, close).
Проще говоря, Socket — это промежуточный уровень абстрагирования программного обеспечения для прикладного уровня для связи с семейством протоколов TCP / IP. Это набор интерфейсов , В режиме разработки Socket на самом деле является фасадным режимом, скрывающим сложное семейство протоколов TCP / IP за интерфейсом Socket. Для пользователя простой набор интерфейсов — это все, что позволяет Socket организовывать данные в соответствии с заданными параметрами. соглашение.
Примечание: На самом деле, в сокетах нет концепции слоев, это всего лишь приложение шаблона проектирования фасада, которое облегчает программирование. Это программный уровень абстракции. В сетевом программировании мы используем много сокетов.
4. Основные функции интерфейса SOCKET
Сервер сначала инициализирует сокет, затем связывается с портом, прослушивает порт (listen), вызывает accept to block и ожидает подключения клиента. В это время, если клиент инициализирует Socket, а затем подключается к серверу (connect), если соединение становится , то соединение между клиентом и сервером установлено. Клиент отправляет запрос данных, сервер принимает запрос и обрабатывает запрос, затем отправляет данные ответа клиенту, клиент считывает данные и, наконец, закрывает соединение , и одно взаимодействие заканчивается.
4.1, функция socket ()
Функция сокета соответствует обычной операции открытия файла. Обычная операция открытия файла возвращает дескриптор файла, и socket() Используется для создания дескриптора сокета, который однозначно идентифицирует сокет. Этот дескриптор сокета аналогичен дескриптору файла, используется в последующих операциях и используется в качестве параметра для выполнения некоторых операций чтения и записи.
Так же, как вы можете передавать различные значения параметров в 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() Когда система автоматически назначает порт случайным образом.
4.2, функция bind ()
Как упоминалось выше, функция bind () назначает сокету определенный адрес в семействе адресов. Например, переписка AF_INET 、 AF_INET6 Назначить IPv4 или IPv6 адрес и номер порта для сокета.
Три параметра функции:
- sockfd: дескриптор сокета, который создается функцией socket () и однозначно идентифицирует сокет. bind Функция () свяжет имя с этим дескриптором.
- адрес: один const struct Sockaddr * Указатель на адрес протокола для привязки к sockfd. Эта структура адресов зависит от семейства адресных протоколов, когда был создан сокет, например, ipv4 соответствует:
Обычно, когда сервер запускается, он связывает известный адрес (например, IP-адрес + номер порта) для предоставления услуг, и клиенты могут использовать его для подключения к серверу; клиенту не нужно указывать, а система автоматически назначает номер порта. И свой собственный IP-адрес. Вот почему обычно серверная сторона звонит перед прослушиванием bind (), И клиент не будет звонить, но в connect () Случайно генерируется системой.
Сетевой порядок байтов и порядок байтов хоста
Порядок байтов хоста Это то, что мы обычно говорим о режимах с прямым и обратным порядком байтов: разные процессоры имеют разные типы порядковых номеров. Эти порядковые номера относятся к порядку, в котором целые числа хранятся в памяти. Это называется порядком хоста. Определения упомянутых Big-Endian и Little-Endian следующие:
A) Little-Endian — это младший байт, выгружаемый в конец памяти с низким адресом, а старший байт выгружается в конец памяти с высоким адресом.
B) Big-Endian означает, что старшие байты расположены на младшей стороне памяти, а младшие байты расположены на старшей стороне памяти.
Сетевой порядок байтов : 32-битное значение 4 байта передается в следующем порядке: сначала от 0 до 7 бит, затем от 8 до 15 бит, затем от 16 до 23 бит и, наконец, от 24 до 31 бит. Этот порядок передачи называется байтовым порядком с прямым порядком байтов.Поскольку все двоичные целые числа в заголовке TCP / IP передаются в сети в этом порядке, это также называется порядком байтов в сети.Порядок байтов, как следует из его названия, — это порядок, в котором данные, размер которых превышает тип байта, хранятся в памяти. Нет проблем с порядком в одном байте данных.
так : При привязке адреса к сокету сначала преобразуйте порядок байтов хоста в порядок байтов сети и не предполагайте, что порядок байтов хоста используется так же, как порядок байтов сети. Это Big-Endian. Эта проблема вызвала кровопролитие! Из-за этой проблемы в коде проекта компании возникло много необъяснимых проблем, поэтому, пожалуйста, не делайте никаких предположений о порядке байтов хоста, обязательно преобразуйте его в сетевой порядок байтов, а затем Назначен на розетку.
4.3, функции listen (), connect ()
Если в качестве сервера, позвоните socket() 、 bind () Будет вызван после listen() Чтобы прослушать этот сокет, если клиент звонит connect() Сделайте запрос на подключение, и сервер получит запрос.
Первым параметром функции прослушивания является дескриптор отслеживаемого сокета, а вторым параметром является максимальное количество соединений, которое соответствующий сокет может поставить в очередь. Сокет, созданный функцией socket (), по умолчанию является активным типом. Функция listen изменяет сокет на пассивный тип, ожидая запроса клиентского соединения.
Первый параметр функции подключения — это дескриптор сокета клиента, второй параметр — адрес сокета сервера, а третий параметр — длина адреса сокета. Клиент устанавливает соединение с TCP-сервером, вызывая функцию соединения.
4.4, принять () функцию
TCP серверные вызовы socket() 、 bind () 、 listen() После этого указанный адрес сокета будет отслеживаться. TCP клиент звонит по очереди socket() 、 connect() Затем запрос на соединение отправляется на сервер TCP. После того, как TCP-сервер прослушивает этот запрос, он вызовет accept () Функция принимает запрос на получение, и соединение установлено. После этого вы можете начать операции сетевого ввода-вывода, которые аналогичны операциям чтения и записи операций ввода-вывода для обычных файлов.
Параметр sockfd Параметр sockfd является сокетом прослушивания в приведенном выше объяснении. Этот сокет используется для прослушивания порта. Когда клиент подключается к серверу, он использует этот номер порта. В настоящее время номер порта связывается с сокетом. ассоциация. Конечно, клиент не знает этих деталей сокета, он знает только адрес и номер порта. Параметр addr Это параметр результата, он используется для принятия возвращаемого значения, это возвращаемое значение указывает адрес клиента, конечно, этот адрес описывается некоторой структурой адреса, пользователь должен знать, какая структура адреса. Если вас не интересует адрес клиента, вы можете установить это значение в NULL. Параметр len Как все думают, это также параметр результата, используемый для принятия размера вышеупомянутой структуры addr, он указывает количество байтов, занимаемых структурой addr. Он также может быть установлен в NULL.
Если accept возвращается успешно, сервер и клиент установили соединение правильно, и в это время сервер завершает связь с клиентом через сокет, возвращенный accept.
Accept принимает процесс по умолчанию и блокирует его до тех пор, пока не будет установлено клиентское соединение, и не вернется к нему.
На данный момент мы должны различать два типа сокетов,
Слушай сокет: слушай Сокет аналогичен параметру принятия sockfd. Это сокет прослушивания. После вызова функции прослушивания Он генерируется сервером, начинающим вызывать функцию socket (), называемую Дескриптор сокета прослушивания Прослушивающая розетка )
Подключите розетку: Сокет изменится с активно подключенного сокета на слушающий сокет; Функция accept возвращает Подключенные s карманный дескриптор ( Разъем подключения ) Он представляет собой соединение точка-точка, где сеть уже существует.
Сервер обычно создает только один дескриптор сокета прослушивания, который всегда существует в течение жизненного цикла сервера. Ядро создает дескриптор подключенного сокета для каждого клиентского соединения, принятого серверным процессом. Когда сервер завершает обслуживание клиента, соответствующий дескриптор подключенного сокета закрывается.
Естественно, я хочу спросить: почему существуют два типа розеток? Причина очень проста: если используется дескриптор, то у него слишком много функций, что делает его очень неинтуитивным, и в то же время новый дескриптор действительно генерируется в ядре.
Подключить разъем socketfd_new не занимает новый порт для связи с клиентом и по-прежнему использует тот же номер порта, что и сокет прослушивания socketfd
4.5, read (), write () и другие функции
Все в долгу перед Dongfeng. На этом этапе сервер и клиент установили соединение. Сетевой ввод / вывод может быть вызван для операций чтения и записи, то есть реализована связь между различными процессами в сети! Существуют следующие группы операций сетевого ввода-вывода:
Я рекомендую использовать recvmsg()/sendmsg() Эти две функции являются наиболее распространенными функциями ввода / вывода. Фактически, вы можете заменить другие функции выше этими двумя функциями. Их заявления следующие:
Функция чтения отвечает за чтение из fd. Когда чтение успешно, чтение возвращает количество фактически прочитанных байтов. Если возвращаемое значение равно 0, это означает, что конец файла был прочитан, а значение меньше 0 указывает, что произошла ошибка. Если ошибка EINTR, чтение вызвано прерыванием. Если это ECONNREST, это указывает на проблему с сетевым соединением.
Функция write записывает n-байтовые байты в buf в файловый дескриптор fd. В случае успеха возвращает количество записанных байтов . Возвращает -1 при ошибке и устанавливает переменную errno. В сетевой программе есть две возможности, когда мы записываем в дескриптор файла сокета. 1) Возвращаемое значение записи больше 0, что указывает на то, что некоторые или все данные были записаны. 2) Возвращенное значение меньше 0, и произошла ошибка . Мы должны иметь дело с типом ошибки. Если ошибка EINTR, во время записи произошла ошибка прерывания. Если это EPIPE, существует проблема с сетевым подключением (другая сторона закрыла соединение).
В остальном я не буду вводить эти функции ввода / вывода одну за другой. Подробнее см. В документе man или Baidu и Google. В следующих примерах будет использоваться send / recv.
4.6, функция close ()
После того, как сервер установил соединение с клиентом, выполняются некоторые операции чтения и записи.После завершения операций чтения и записи соответствующий дескриптор сокета закрывается. Например, вызывается fclose, чтобы закрыть открытый файл после работы с открытым файлом.
Поведение по умолчанию при закрытии сокета TCP — пометить сокет как закрытый, а затем немедленно вернуться к вызывающему процессу. Этот дескриптор больше не может использоваться вызывающим процессом, то есть его нельзя использовать в качестве первого параметра чтения или записи.
Примечание: Операция close только делает счетчик ссылок соответствующего дескриптора сокета -1. Только когда счетчик ссылок равен 0, клиент TCP будет отправлен на сервер для завершения запроса соединения.
5. Установление TCP в сокете (трехстороннее рукопожатие)
Первое рукопожатие : При установлении соединения клиент отправляет пакет синхронизации (syn = j) на сервер и переходит в состояние SYN_SEND, ожидая подтверждения от сервера; SYN: синхронизировать номера последовательностей.
Второе рукопожатие Сервер получает пакет syn и должен подтвердить SYN клиента (ack = j + 1). В то же время он также отправляет пакет SYN (syn = k), то есть пакет SYN + ACK. В это время сервер переходит в состояние SYN_RECV;
Третье рукопожатие Клиент получает пакет SYN + ACK сервера и отправляет на сервер пакет подтверждения ACK (ack = k + 1). После отправки этого пакета клиент и сервер переходят в состояние ESTABLISHED и завершают трехстороннее рукопожатие.
Полное трехстороннее рукопожатие: Запрос — ответ — подтвердить еще раз 。
Соответствующий интерфейс функции:
Из рисунка видно, что когда клиент звонит connect В это время был инициирован запрос на соединение, и на сервер был отправлен пакет SYN J. В это время соединение переходит в состояние блокировки, сервер прослушивает запрос на соединение, то есть принимает пакет SYN J и вызывает accept Функция получает запрос и отправляет SYN K клиенту, ACK J + 1, затем accept переходит в состояние блокировки, клиент получает SYN K сервера, ACK J + 1 и затем подключается Вернитесь и подтвердите SYN K. Когда сервер получит ACK K + 1, примите возвраты. Пока три рукопожатия завершены, и соединение установлено.
6. Завершение TCP-соединения (четырехстороннее рукопожатие)
Из-за TCP Соединение дуплексное, поэтому каждое направление должно быть закрыто отдельно. Этот принцип заключается в том, что когда одна сторона завершает свою задачу по отправке данных, она может FIN Разорвать соединение в этом направлении. Получил один FIN Это просто означает, что в этом направлении нет потока данных, TCP Соединение получило FIN Можно все еще отправить данные потом. Сторона, которая выполняет отключение, сначала выполняет активное отключение, а другая сторона выполняет пассивное отключение.
( 1 ) Клиент A Отправить один FIN Закрыть клиентов A К серверу B Передача данных (сегмент 4 )。
( 2 ) Сервер B Получил это FIN И он отправляет обратно ACK , Подтвердите серийный номер полученного серийного номера плюс 1 (сегмент 5 ). и SYN То же самое FIN Серийный номер будет занят.
( 3 ) Сервер B Отключение с клиентом A Соединение, отправьте FIN Клиенту A (сегмент 6 )。
( 4 ) Клиент A Отправить обратно ACK Подтвердите сообщение и установите порядковый номер подтверждения на полученный порядковый номер. 1 (сегмент 7 )。
Соответствующий интерфейс функции показан на рисунке:
Процесс выглядит следующим образом:
Таким образом, есть FIN и ACK в каждом направлении.
1 , Почему соглашение о соединении является трехсторонним рукопожатием, а закрытие соединения — четырехсторонним рукопожатием?
Это из-за сервера LISTEN В состоянии SOCKET Когда получил SYN После того, как сообщение устанавливает запрос на соединение, оно может отправить ACK и SYN ( ACK Ответы и SYN (Функция синхронизации), чтобы отправить сообщение. Но при закрытии соединения, при получении другого FIN Когда сообщение уведомляется, это просто означает, что у другой стороны нет данных для отправки вам, но не все ваши данные были отправлены другой стороне, поэтому вы не можете сразу закрыть SOCKET, То есть вам может потребоваться отправить некоторые данные другой стороне перед отправкой FIN Сообщение другой стороне, чтобы указать, что вы согласны, что соединение может быть закрыто сейчас, так что здесь ACK Сообщение и FIN Сообщения отправляются отдельно в большинстве случаев.
2 , почему TIME_WAIT Статус нужно ждать 2MSL Прежде чем вернуться к CLOSED Государство?
Это потому, что хотя обе стороны согласились закрыть соединение, и рукопожатие 4 Все сообщения также координируются и отправляются, и могут быть возвращены напрямую CLOSED Состояние (как SYN_SEND Статус для ESTABLISH Статус), но поскольку мы должны предполагать, что сеть ненадежна, вы не можете гарантировать, что ACK Сообщение должно быть получено другой стороной, поэтому другая сторона находится в LAST_ACK В состоянии SOCKET Не может быть получено из-за тайм-аута ACK Сообщение и отправить FIN Сообщение, так что это TIME_WAIT Роль государства заключается в повторной отправке того, что может быть потеряно ACK Сообщение.
7. Пример программирования сокетов
Сторона сервера: Всегда следите за портом 8000 этого компьютера. Если получен запрос на соединение, он получит запрос, получит сообщение от клиента и вернет сообщение клиенту.
- /* File Name: server.c */
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define DEFAULT_PORT 8000
- #define MAXLINE 4096
- int main( int argc, char ** argv)
- <
- int socket_fd, connect_fd;
- struct sockaddr_in servaddr;
- char buff[4096];
- int n;
- // Init Socket
- if ( (socket_fd = 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); // IP-адрес установлен на INADDR_ANY, чтобы система автоматически получала IP-адрес машины.
- servaddr.sin_port = htons(DEFAULT_PORT); // Установить порт в DEFAULT_PORT
- // Привязать локальный адрес к созданному сокету
- if ( bind(socket_fd, ( struct sockaddr*)&servaddr, sizeof (servaddr)) == -1) <
- printf( «bind socket error: %s(errno: %d)\n» ,strerror(errno),errno);
- exit(0);
- >
- // Начало прослушивания клиентского соединения
- if ( listen(socket_fd, 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 ( (connect_fd = accept(socket_fd, ( struct sockaddr*)NULL, NULL)) == -1) <
- printf( «accept socket error: %s(errno: %d)» ,strerror(errno),errno);
- continue ;
- >
- // Принимаем данные от клиента
- n = recv(connect_fd, buff, MAXLINE, 0);
- // Отправляем данные ответа клиенту
- if (!fork()) < / * Запретный город * /
- if (send(connect_fd, «Hello,you are connected!\n» , 26,0) == -1)
- perror( «send error» );
- close(connect_fd);
- exit(0);
- >
- buff[n] = ‘\0’ ;
- printf( «recv msg from client: %s\n» , buff);
- close(connect_fd);
- >
- close(socket_fd);
- >
- /* File Name: client.c */
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define MAXLINE 4096
- int main( int argc, char ** argv)
- <
- int sockfd, n,rec_len;
- char recvline[4096], sendline[4096];
- char buf[MAXLINE];
- struct sockaddr_in servaddr;
- if ( argc != 2) <
- printf( «usage: ./client \n» );
- exit(0);
- >
- if ( (sockfd = socket(AF_INET, SOCK_STREAM, 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(8000);
- if ( inet_pton(AF_INET, argv[1], &servaddr.sin_addr)
- printf( «inet_pton error for %s\n» ,argv[1]);
- exit(0);
- >
- if ( connect(sockfd, ( struct sockaddr*)&servaddr, sizeof (servaddr))
- 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)
- <
- printf( «send msg error: %s(errno: %d)\n» , strerror(errno), errno);
- exit(0);
- >
- if ((rec_len = recv(sockfd, buf, MAXLINE,0)) == -1) <
- perror( «recv error» );
- exit(1);
- >
- buf[rec_len] = ‘\0’ ;
- printf( «Received : %s » ,buf);
- close(sockfd);
- exit(0);
- >
inet_pton Да Функция преобразования IP-адресов в Linux может преобразовывать IP-адреса между «десятичным числом» и «целым числом». Является расширением inet_addr.
- int inet_pton( int af, const char *src, void *dst); // Преобразовать строку в сетевой адрес:
gcc -o server server.c
======waiting for client’s request======
И подождите, пока клиент подключится.
gcc -o client server.c
Клиент подключается к серверу:
Ожидание входящего сообщения
Отправьте сообщение и введите: c ++
В этот момент сервер видит:
Клиент получает сообщение:
Фактически, вы можете использовать telnet для тестирования без клиента:
telnet 127.0.0.1 8000
При компиляции исходного кода в Ubuntu заголовок type.h может быть не найден.
Просмотрите его с помощью dpkg -L libc6-dev | grep types.h.
Если нет, вы можете использовать
apt-get install libc6-dev.
Если он у вас есть, но его нет в каталоге / usr / include / sys /, вы можете вручную добавить этот файл в этот каталог.
Интеллектуальная рекомендация
Используйте Maven для создания собственного архетипа скелета проекта (4)
Один, базовое введение в Maven Во-вторых, скачайте и настройте Maven Три, настроить домашнее зеркало на Али В-четвертых, создайте содержимое скелета архетипа В-пятых, создайте проект через архетип 6. .
Станция интерпретации больших данных B пользуется популярностью среди гигантов района «призрачные животные» Цай Сюкуня.
Автор | Сюй Линь Ответственный редактор | Ху Вэйвэй Предисловие Недавно Цай Сюкунь отправил письмо юриста на станцию B. Содержание письма юриста показало, что «на станции B имеется большое кол.
Вопрос A: Алгоритм 7-15: алгоритм кратчайшего пути Дейкстры
Название Описание Во взвешенном ориентированном графе G для исходной точки v задача о кратчайшем пути от v до оставшихся вершин в G называется задачей кратчайшего пути с одной исходной точкой. Среди ш.
Учебный дневник — перелистывание страниц
Используйте плагин Layui.
Нулевое основание для отдыха-клиента
Предисловие: статья, обобщенная, когда я только что связался с тестом API, в дополнение к остальному клиенту этот инструмент сам, некоторые из мелких пониманий API, я надеюсь помочь тому же белую белу.
Вам также может понравиться
Подробно объясните, как новички используют sqlmap для выполнения инъекционных атак на базы данных mysql.
Шаг 1. Откройте для себя инъекцию Со мной все было нормально, когда я был свободен, я случайно нажал на чужой блог и обнаружил, что ссылка заканчивается на id, поэтому я проверил его вручную. Результа.
Vue заметки сортируют, пусть вам начать с Vue.js:. 04_3 Сетевое приложение: AXIOS плюс Вью
В предыдущем разделе мы ввели основное использование AXIOS, по сравнению с нативным Ajax, который при условии, что способ является более простым и, а сетевые данные теперь в состоянии получить его ров.
Шаблон алгоритма конной повозки
Блог гангстеров Тележки, запряженные лошадьми, используются для решения проблемы самой длинной подстроки палиндрома. Основное внимание уделяется подстрокам, а не подпоследовательностям. Если вы хотите.
35 Line Code, чтобы получить метод исследования событий (ON)
Об авторе: Чжу Сяою,Личный публичный номер: языковой класс большой кошки Эта проблема научит вас этой большой классе Cat.Как написать наиболее эффективное метод исследования событий с 35 Line R Code C.
Образ докера: gitlab
GitLab Docker images Both GitLab CE and EE are in Docker Hub: GitLab CE Docker image GitLab EE Docker image The GitLab Docker images are monolithic images of GitLab running all the necessary services .
Источник