Docker 容器网络:C++ 客户端 — 服务器应用程序。

news2024/11/17 2:53:35

一、说明

        在下面的文章中, 将向您概述 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 5555

int 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 5555

int 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1443769.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

桌面显示器应用Type-C接口有什么好处

随着科技的不断发展&#xff0c;桌面显示器作为我们日常工作中不可或缺的设备之一&#xff0c;也在不断更新换代。其中&#xff0c;Type-C接口的应用成为了桌面显示器发展的一个重要趋势。那么&#xff0c;桌面显示器应用Type-C接口究竟有什么好处呢&#xff1f; 首先&#xff…

中文点选识别

中文点选识别 测试网站&#xff1a;https://www.geetest.com/adaptive-captcha-demo 1. 开始验证 # 1.打开首页 driver.get(https://www.geetest.com/adaptive-captcha-demo)# 2.点击【文字点选验证】 tag WebDriverWait(driver, 30, 0.5).until(lambda dv: dv.find_elemen…

MySQL篇----第十八篇

系列文章目录 文章目录 系列文章目录前言一、SQL 语言包括哪几部分?每部分都有哪些操作关键二、完整性约束包括哪些?三、什么是锁?四、什么叫视图?游标是什么?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,…

AI新工具(20240210) Osam - Osam是一个启用本地运行的开源llm;Whishper - Whishper是一个开源的语音工具

Osam - Osam是一个启用本地运行的开源“一切分割”模型工具&#xff0c;支持多种接口和自定义视觉模型。 Osam是一个开源工具&#xff0c;它允许本地运行“可对任何内容进行分割”的模型(Segment-Anything Models)&#xff0c;灵感来源于Ollama。使用Osam&#xff0c;用户可以…

网络报文处理流程

报文处理流程 WLAN网络中的数据包括管理报文和业务数据报文。管理报文必须采用CAPWAP隧道进行转发&#xff0c;而业务数据报文除了可以采用CAPWAP隧道转发之外&#xff0c;还可以采用直接转发方式和Soft-GRE转发方式。 管理报文用来传送AC与AP之间的管理数据&#xff0c;存在于…

酷开科技荣获消费者服务平台黑猫投诉“消费者服务之星”称号

什么是优质服务&#xff1f;既是以客户为中心的庄严承诺&#xff0c;又是对服务能力提升的深耕细作&#xff1b;既是对服务标准的敬畏&#xff0c;也是对服务创新的不断探索……服务是多维的&#xff0c;每个企业都有自己独到的诠释&#xff0c;或事无巨细环环严控&#xff0c;…

VR和AR傻傻分不清,一句话给你讲明白。

不说废话&#xff0c;直接说结论&#xff0c;虚拟现实&#xff08;Virtual Reality&#xff0c;VR&#xff09;和增强现实&#xff08;Augmented Reality&#xff0c;AR&#xff09;。如果现实是A&#xff0c;虚拟是B&#xff0c;那么VRB&#xff0c;ARAB&#xff0c;就这简单&…

Qt 常见容器类用法(一)

目录 QMap类 QHash类 QVector类 QMap类 QMap<key,T>提供一个从类型为Key的键到类型为T的值的映射。通常&#xff0c;QMap存储的数据形式是一个键对应一个值&#xff0c;并且按照键Key的次序存储数据。为了能够支持一键多值的情况&#xff0c;QMap提供QMap<key,T&g…

吹响AI PC号角!微软在Windows中不断增加“Copilot含量”

2024&#xff0c;会是AI PC元年吗&#xff1f;至少微软正在往这个方向努力。 本周&#xff0c;微软开始在Windows中测试Copilot的“新体验”&#xff0c;其中包括任务栏中的Copilot图标&#xff0c;当用户复制文本或图片时&#xff0c;Copilot操作菜单就会自动出现。 有媒体在…

C++ dfs 的状态表示(五十一)【第十一篇】

今天我们接着学习dfs&#xff08;状态表示&#xff09;。 1.抽象形式的dfs 前面用到的 DFS 算法都是比较容易想象出搜索过程的&#xff0c;接下来我们看一些不那么容易想象搜索过程的 DFS 过程&#xff0c;这些问题我们称为抽象形式的 DFS。 来回顾一下上节课遇到的一个问题&a…

CVE-2022-0760 漏洞复现

CVE-2022-0760 NSS [HNCTF 2022 WEEK2]ohmywordpress 【CVE-2022-0760】 题目描述&#xff1a;flag在数据库里面。 开题&#xff1a; 顺着按钮一直点下去会发现出现一个按钮叫安装WordPress 安装完之后的界面&#xff0c;有一个搜索框。 F12看看network。 又出现了这个Wor…

Netty应用(四) 之 Reactor模型 零拷贝

目录 6.Reactor模型 6.1 单线程Reactor 6.2 主从多线程Reactor (主--->Boss | 从--->Worker | 一主多从机制) 7.扩展与补充 8.Reactor模型的实现 8.1 多线程Reactor模型的实现&#xff08;一个Boss线程&#xff0c;一个Worker线程&#xff09; 8.2 多线程Reactor模…

postgresql 手动清理wal日志的101个坑

新年的第一天&#xff0c;总结下去年遇到的关于WAL日志清理的101个坑&#xff0c;以及如何相对安全地进行清理。前面是关于WAL日志堆积的原因分析&#xff0c;清理相关可以直接看第三部分。 首先说明&#xff0c;手动清理wal日志是一个高风险的操作&#xff0c;尤其对于带主从的…

AS自治系统的路由协议--BGP

BGPV4 --- IPV4 --- BGPV4 --- MPBGP --- 支持多种不同的地址组 重发布替代BGP的缺陷&#xff1a; 1&#xff0c;选路不佳 2&#xff0c;ASBR的归属问题 BGP --- 无类别路径矢量协议 1&#xff0c;无类别 --- 在传递路由信息的时候携带子网掩码 2&#xff0c;路径矢量 ---…

【Algorithms 4】算法(第4版)学习笔记 06 - 2.3 快速排序

文章目录 前言参考目录学习笔记1&#xff1a;基本算法1.1&#xff1a;快速排序 demo 演示1.2&#xff1a;快速排序切分代码实现1.3&#xff1a;实现细节1.4&#xff1a;案例分析1.4.1&#xff1a;最佳案例1.4.2&#xff1a;最坏案例1.4.3&#xff1a;平均案例分析1.5&#xff1…

ChatGPT高效提问—prompt常见用法(续篇十)

ChatGPT高效提问—prompt常见用法(续篇十) 1.1 使用引导词 ​ 除了利用prompt引导ChatGPT回答问题,另一种重要的应用场景是让ChatGPT根据需求生成各种内容,比如诗词创作、故事续写、招聘信息编写,甚至是舞台剧剧本创作等。在这些场景中,我们可以采取一个巧妙的策略,那…

使用deepspeed继续训练LLAMA

目录 1. 数据训练配置 2. 模型载入 3. 优化器设置 4. DeepSpeed 设置 5. DeepSpeed 初始化 6. 模型训练 LLAMA 模型子结构&#xff1a; 1. 数据训练配置 利用 PyTorch 和 Transformers 库创建数据加载器&#xff0c;它支持单机或多机分布式训练环境下的数据加载与采样。涉…

C# CAD交互界面-自定义面板集-添加快捷命令(五)

运行环境 vs2022 c# cad2016 调试成功 一、引用 using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Windows; using System; using System.Drawing; using System.Windows.Forms; 二、代码说明 [CommandMethod("Cre…

2-8 单链表+双链表+模拟栈+模拟队列

今天给大家用数组来实现链表栈和队列 单链表&#xff1a; 首先要明白是如何用数组实现&#xff0c; 在这里需要用到几个数组&#xff0c;head表示头节点的下标&#xff0c;e[i]表示表示下标为i的值&#xff0c;ne[i]表示当前节点下一个节点的下标。idx表示当前已经用到那个点…

qt-C++笔记之判断一个QLabel上有没有load图片

qt-C笔记之判断一个QLabel上有没有load图片 code review! 在Qt框架中&#xff0c;QLabel是用来显示文本或者图片的一个控件。如果你想判断一个QLabel控件上是否加载了图片&#xff0c;你可以检查它的pixmap属性。pixmap属性会返回一个QPixmap对象&#xff0c;如果没有图片被加…