Docker 容器网络:C++ 客户端 — 服务器应用程序。
一、说明
在下面的文章中, 将向您概述 docker 容器之间的通信。docker 通信的验证将通过运行 C++ 客户端-服务器应用程序和标准“ping”命令来执行。将构建并运行两个单独的 Docker 映像。
由于我会关注 docker 网络方面,因此不会提供 C++ 详细信息。有一个文件和易于理解的程序。我还假设读者了解 docker 的主要概念。在本文中,我不会穷尽 docker 网络的完整概念。为了进一步学习,我建议使用文档,可以在此处找到。
简单来说,Docker 概念是一个开放平台,允许软件工程师在容器的帮助下开发、集成和运行应用程序,并根据 Dockerfile 中的规范进行构建。
Docker 开发策略使用户能够将应用程序与基础设施分离,有效利用资源并按构建和计划交付应用程序。
首先,我将解释并为您提供有关通信两个 docker 映像的完整信息,这些映像可以部署在一台主机上(这种类型的 docker 网络通信将使用 docker BRIDGE)。
其次,我将展示 docker 概念OVERLAY NETWORK,其中 docker 映像将部署在单独的主机(和单独的网络)上。
通信方法将由同一客户端 — 服务器 C++ 应用程序或命令 ping 进行验证。
请注意,网络配置(在下一篇文章中描述)必须被视为一个简单的示例。通常,在每种情况下,网络架构都可以以不同的方式组织并连接许多不同的容器。
我还验证了云中的覆盖网络,将云 Linode 服务器上的主机与我的本地计算机连接起来(本文中未描述,因为我必须发布所有 IP 地址)。
二、Docker 中的桥接网络
2.1 网络构建
考虑下图,请注意,当连接在一台 Host上运行的容器时,会使用这种类型的通信。在我们的示例中,我们将在一个容器中运行 C++ 客户端,在另一个容器中运行 C++ 服务器(本文中包含的程序)。通过支持 docker 桥(通信管道)可以实现容器之间的通信,该桥可以关联为内部 ETH 网络(仅适用于在同一主机上运行的映像)。
您可以根据 Dockerfile 构建容器(一个用于客户端,一个用于服务器)。在检查容器通信时,您需要启动第一个服务器(运行服务器容器)。服务器将等待客户端,您从第二个容器启动客户端。
客户端向服务器发送 0-100 之间的随机数。服务器收集从客户端发送的接收信息并(作为字符串)添加:3.1415 并将包重新发送到客户端。
以下示例(docker 图像和 C++ 文件管理器)代表了我对软件和硬件的具体设置。您必须(或不必)更改客户端中的 IP 地址。我使用的端口是5555(你可以根据自己的喜好调整)。
按作者
2.2 客户端C++
// Client inspired by GeeksforGeeks#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>#define PORT 5555int main()
{int sock = 0, valread;struct sockaddr_in serv_addr;srand(time(NULL));char buffer[1024] = {0};if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){std::cout << "Socket creation error" << std::endl;return -1;}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(PORT);if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) //LOCAL//if(inet_pton(AF_INET, "172.17.0.2", &serv_addr.sin_addr)<=0) //CLIENT DOES NOT RUN IS CONTAINER//if(inet_pton(AF_INET, "172.21.0.1", &serv_addr.sin_addr)<=0) //CONTAINER//if(inet_pton(AF_INET, "10.0.9.1", &serv_addr.sin_addr)<=0) //OVERLAY{std::cout << "Address is invalid ... " << std::endl;return -1;}if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){std::cout << "Connection Failed. Try again! ..." << std::endl;return -1;}int number = rand() % 100;std::cout << "check : " << number << std::endl;std::string str = std::to_string(number);char *cstr = &str[0];send(sock, cstr, strlen(cstr), 0);std::cout << "Message sent " << std::endl;valread = read(sock, buffer, 1024);std::cout << buffer << std::endl;return 0;
}
Dockerfile 客户端
FROM ubuntu:bionic #pull ubuntu
FROM gcc:latest #pull gcc
#just in case, you can install gcc and cmake
#RUN apt-get update && apt-get -y install build-essentials gcc cmake
ADD . /usr/src # add (copy) all from local folder to /usr/src
WORKDIR /usr/src
EXPOSE 5555
RUN g++ medium_client.cpp -o medium_client
# comment this and un - comment other if you would like to run your # program manually from shell
CMD ["./medium_client"]
#CMD ["/bin/bash"]
在终端(构建容器)上执行以下命令。
sudo docker build . -t client:1
2.3 服务器C++
// Server side C/C++ program to demonstrate Socket programming
// Server - inspired by GeeksforGeeks
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string>
#include <string.h>#define PORT 5555int main()
{int server_fd, new_socket, valread;struct sockaddr_in address;int opt = 1;int addrlen = sizeof(address);char buffer[1024] = {0};if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0){std::cout << "socket failed" << std::endl;exit(EXIT_FAILURE);}if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,&opt, sizeof(opt))){std::cout << "socket failed" << std::endl;exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);if (bind(server_fd, (struct sockaddr *)&address,sizeof(address)) < 0){std::cout << "bind failed" << std::endl;exit(EXIT_FAILURE);}if (listen(server_fd, 3) < 0){std::cout << "listen" << std::endl;exit(EXIT_FAILURE);}if ((new_socket = accept(server_fd, (struct sockaddr *)&address,(socklen_t *)&addrlen)) < 0){std::cout << "accept" << std::endl;exit(EXIT_FAILURE);}double pi = 3.1415;std::string str1 = "server => ";std::string str2 = std::to_string(pi);valread = read(new_socket, buffer, 1024);std::cout << buffer << std::endl;std::string str = str1 + " : " + str2 + " and " + buffer;char *cstr = &str[0];send(new_socket, cstr, strlen(cstr), 0);std::cout << "Message hass been sent!" << std::endl;return 0;
}
服务器 Dockerfile
FROM ubuntu:bionic
FROM gcc:latest
ADD . /usr/src
WORKDIR /usr/src
EXPOSE 5555
RUN g++ medium_server.cpp -o medium_server
# comment this and un - comment other if you would like to run your # program manually from shell
CMD ["./medium_server"]
#CMD ["/bin/bash"]
在终端上执行以下命令(构建容器)。
sudo docker build . -t server:1
执行以下命令创建桥接并检查通信。我假设您在容器(客户端和服务器)之前构建。
// inspect available docker networks (here is my setup) - see bridge is running as default
sudo docker network ls
接下来,您需要检查您的网桥并捕获网桥(容器)的 IP 地址。子网网络是您的服务器 cpp 程序内部需要的网络。如果您有其他的,请更改并重新运行容器构建。
现在你需要创建自己的网络(bridge是一个提供者)并指定你的名字,这里我使用home_net。
sudo docker network create –-driver bridge home_net
// confirm creation running again
sudo docker network ls
您的网络已创建,但为了为容器提供通信,两个容器都必须连接(到网络)。执行以下命令以运行容器并附加到您的网络 home_net。
请注意,您应该为 /bin/bash 构建两个容器(请参阅 Dockerfile 中的注释),以便首先使用命令行运行容器(而不运行构建容器时已编译的程序)。
sudo docker run -it -p 5555:5555 --network=home_net server:1
接下来再次检查您的网络。查看您的容器已连接到您的网络。
sudo docker network inspect home_net
对其他容器执行相同操作。
sudo docker run -it --network=home_net client:1
并检查(运行以下命令)。
sudo docker network inspect home_net
现在您的两个容器正在运行并连接到您的网络。
现在,执行以下命令(在正在运行的容器中)。从服务器启动表单。
./server_medium # container with server
./client_medium # container with client
现在您可以看到容器之间的一些通信。
三、Docker 中的覆盖网络
当您想要运行的 docker 容器位于不同的物理位置(在不同的物理主机上运行)时,您仍然可以将容器连接到其他容器。这里我们将在 Docker 中使用覆盖网络概念。
您可以想象,docker 容器可以与桥接通信类似,跨独立的虚拟网络(称为覆盖网络)发送和接收信息。
这意味着我们可以为容器构建私有虚拟网络,并且可以完全透明地交互。请考虑下图。在此示例中,我们可以重用图像和 C++ 客户端-服务器应用程序(IP 地址必须相应更改)。
请注意,在这两种情况下(桥接网络和覆盖网络),容器之间的通信也可以通过运行命令来验证:ping <host_IP_address>。对于当前网络(覆盖网络)将执行此类测试。然而,作者也在这种类型的 docker 架构中运行 C++ 应用程序(客户端 - 服务器)。当主机服务器部署在云端(Linode服务器)时,也验证了有关应用程序的验证。
对于这两种情况(桥接、覆盖),您有 4 种可能的选择来运行您的应用程序(取决于客户端的“位置”)。
在构建客户端映像之前,请考虑以下需要为medium_client.cpp 提供的IP 地址规范。
//CLIENT AND SERVER RUN LOCAL (NOT IN CONTAINERS)
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
//CLIENT DOES NOT RUN IN CONTAINER. SERVER IN CONTAINER
//if(inet_pton(AF_INET, "172.17.0.2", &serv_addr.sin_addr)<=0)
//BRIDGE COMMUNICATION
//if(inet_pton(AF_INET, "172.21.0.1", &serv_addr.sin_addr)<=0)
//OVERLAY COMMUNICATION
//if(inet_pton(AF_INET, "10.0.9.1", &serv_addr.sin_addr)<=0)
使用覆盖网络的容器之间的通信将通过命令 ping 进行验证,但是正如我之前提到的,之前的 C++ 应用程序也可以工作。
运行以下命令(#Host 1 和 #Host 2)
3.1 主机1
首先使用主机 1 网络的 IP 地址初始化网络管理器。
sudo docker swarm init --advertise-addr 192.168.0.101
就我而言,我收到的输出如下。
3.2 主机1(内部主持人)
复制并运行命令:
docker swarm join --token SWMTKN-1-4pmk157a83i2nungc6jdtmh7vp4ujqich1pho141kox1dzxeiu-c6usd1wik2kl6p3ot7fhx4pd1 192.168.0.101:2377
您应该收到如下信息。
3.2 #主机1(其它)
运行以下命令并验证 swarm 管理器(上图之一显示了 swarm 和网桥)
sudo docker network ls
现在创建覆盖网络,这里我们的名字是overnet。
sudo docker network create -d overlay overnet
检查您创建的网络。验证身份等
sudo docker network inspect overnet
拉取两个 Ubuntu 映像(副本),激活网络并创建一个新服务 myservice。以下命令还发送 # Host 2 的图像
sudo docker service create --name myservice --network overnet --replicas 2 ubuntu sleep
运行以下命令确认您已完成的操作。
sudo docker service ls
sudo docker service ps myservice
现在确认您是否正确创建了覆盖网络并且两个容器都已连接。# 主机 1 的 IP 地址为 10.0.1.4。
运行命令
sudo docker network inspect overnet
3.3 主机2
运行相同的操作(我不显示图像,因为它与上面类似)。该主机收到地址IP 10.0.1.5
sudo docker network inspect overnet
3.4 #主机1和#主机2
运行以下命令来安装“ping 命令”。
apt-get update && apt-get install -y iputils-ping
在 #Host 1 和 2 上运行命令来捕获容器名称
sudo docker ps
并连接到 docker shell 以运行 ping
sudo docker exec -it 94835734987 sh
ping 10.0.1.5 # from host 1
ping 10.0.1.4 # from host 2
感谢您的阅读。
四、参考资源
凡本文遇到的代码资源可在下述地址下:
Networking overview | Docker Docs
相关文章:

Docker 容器网络:C++ 客户端 — 服务器应用程序。
一、说明 在下面的文章中, 将向您概述 docker 容器之间的通信。docker 通信的验证将通过运行 C 客户端-服务器应用程序和标准“ping”命令来执行。将构建并运行两个单独的 Docker 映像。 由于我会关注 docker 网络方面,因此不会提供 C 详细信息。…...

Android 识别车牌信息
打开我们心爱的Android Studio 导入需要的资源 gradle //开源车牌识别安卓SDK库implementation("com.github.HyperInspire:hyperlpr3-android-sdk:1.0.3")button.setOnClickListener(v -> {Log.d("Test", "");try (InputStream file getAs…...

C#在窗体正中输出文字以及输出文字的画刷使用
为了在窗体正中输出文字,需要获得输出文字区域的宽和高,这使用MeasureString方法,方法返回值为Size类型; 然后计算输出的起点的x和y坐标,就可以输出了; using System; using System.Collections.Generic; …...

二十、K8S-1-权限管理RBAC详解
目录 k8s RBAC 权限管理详解 一、简介 二、用户分类 1、普通用户 2、ServiceAccount 三、k8s角色&角色绑定 1、授权介绍: 1.1 定义角色: 1.2 绑定角色: 1.3主体(subject) 2、角色(Role和Cluster…...

【PTA|期末复习|编程题】数组相关编程题(一)
目录 7-1 乘法口诀数列 (20分) 输入格式: 输出格式: 输入样例: 输出样例: 样例解释: 代码 7-2 矩阵列平移(20分) 输入格式: 输出格式: 输入样例: 输出样例: …...

[office] 怎么在Excel2003菜单栏自定义一个选项卡 #其他#微信#知识分享
怎么在Excel2003菜单栏自定义一个选项卡 怎么在Excel2003菜单栏自定义一个选项卡 ①启动Excel2003,单击菜单栏--工具--自定义。 ②在自定义界面,我们单击命令标签,在类别中选择新菜单,鼠标左键按住新菜单,拖放到菜单栏…...
面试 JavaScript 框架八股文十问十答第六期
面试 JavaScript 框架八股文十问十答第六期 作者:程序员小白条,个人博客 相信看了本文后,对你的面试是有一定帮助的!关注专栏后就能收到持续更新! ⭐点赞⭐收藏⭐不迷路!⭐ 1)use strict是什么…...

【Web】小白友好的Java内存马基础学习笔记
目录 简介 文件马与内存马的比较 文件马原理 内存马原理 内存马使用场景 内存马分类 内存马注入方式 这篇文章主要是概念性的,具体技术细节不做探究,重点在祛魅。 简介 内存马(Memory Shellcode)是一种恶意攻击技术&…...
Rust猜数字游戏
Rust进阶:猜数字游戏 Rust是一门现代的系统级编程语言,注重内存安全、并发性能以及表达力。在这篇博客中,我们将深入介绍一个更加复杂的猜数字游戏代码,展示Rust语言的一些高级特性。 代码示例 以下是一个升级版的Rust猜数字游…...
.gitlab-ci.yml文件参数配置和使用
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
Go语言从基础到高级-目录
一、编程入门和Go语言简介 什么是编程和为什么要学习编程计算机编程的基本概念Go语言简介为什么选择Go语言 二、设置Go语言开发环境 如何安装Go语言设置环境变量Go语言的工作空间配置 三、Go语言基础 Hello, World!初体验变量和常量数据类型(整数、浮点数、字符…...
Linux CentOS stream 9 alias
alias命令在Linux中用于创建命令别名。它允许用户为常用的命令或命令组合创建短而易记的别名,从而提高工作效率。 alias命令与windows中的快捷方式相同,执行别名时,终端解释器就进行查询与转换,进而执行原来的完整命令。 熟练使用alias命令可以使我们将一长串命令或者一些…...
WebSocketServer+redis实时更新页面数据
redis 实现发布订阅功能具体实现_redis convertandsend-CSDN博客 主要看上面这个 使用redis做websocket分布式消息推送服务_websocket redis-CSDN博客 ClassCastException: java.lang.String cannot be cast to com.alibaba.fastjson.JSONObject 的解决办法_java.lang.class…...
快速掌握Vue.js框架:从入门到实战
一、引言 Vue.js,作为一款广受欢迎的渐进式JavaScript框架,以其轻量级、易用性和高效性在前端开发领域占据了一席之地。Vue.js遵循MVVM(Model-View-ViewModel)设计模式,它通过双向数据绑定机制简化了开发者对用户界面与底层数据模型之间关系的处理,使得构建现代Web应用变…...

###C语言程序设计-----C语言学习(11)#数据的存储和基本数据类型
前言:感谢您的关注哦,我会持续更新编程相关知识,愿您在这里有所收获。如果有任何问题,欢迎沟通交流!期待与您在学习编程的道路上共同进步。 一. 数据的存储 1.整型数据的存储 计算机处理的所有信息都以二进制形式表示…...
机器学习案例1:利用 Python 将语音转换为文本
目录 内容简介 基本环境配置 Python库安装 麦克风语音识别 音频文件的语音识别 长音频源语音识别 内容简介 语音识别是机器或程序识别口语中的单词和短语并将其转换为文本信息的能力。 大多数对于语音识别技术的应用场景就是Siri、Cortana和Google Assistant等个人助理,…...

杨辉三角的变形(数学)
题目 import java.util.Scanner;public class Main {public static void main(String[] args) { // 1 // 1 1 1 // 1 2 3 2 1 // 1 3 6 7 6 3 1 // 1 4 10 16 19 16 10 4 1Scanner sc new Scanner(System.in);int n sc.nextInt();int[][] res new int[n1][2*n];for(i…...
YOLOv5改进 | 融合改进篇 | 华为VanillaNet + BiFPN突破涨点极限
一、本文介绍 本文给大家带来的改进机制是华为VanillaNet主干配合BiFPN实现融合涨点,这个主干是一种注重极简主义和效率的神经网络我也将其进行了实验, 其中的BiFPN不用介绍了从其发布到现在一直是比较热门的改进机制,其主要思想是通过多层级的特征金字塔和双向信息传递来提…...

C++初阶篇----新手进村
目录 一、什么是C二、C关键字三、命名空间3.1命名空间的定义3.2命名空间的使用 四、C输入和输出五、缺省参数5.1缺省参数的概念5.2缺省参数的分类 六、函数重载6.1函数重载的概念6.2函数重载的原理----名字修饰 七、引用7.1引用概念7.2引用特性7.3常引用7.4引用的使用7.5传值、…...

假期刷题打卡--Day26
1、MT1212乘法表 请编写一个简单程序,输出九九乘法表。输入n,就输出乘法表到n的地方。 格式 输入格式: 输入整型 输出格式: 输出整型。形式如:1*11 样例 1 输入: 5输出: 1*11 2*12 …...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...

热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...