UBUNTU22.04下Docker制作TCP服务端镜像

1.安装ubuntu的几种方式

方法一:VMWARE安装虚拟机,通过官网下载IOS镜像,通过镜像安装虚拟机

方法二(推荐):如果是windows系统,建议可以装双系统,准备U盘下载UBUNTU镜像,通过U盘安装UBUNTU

若使用第一种方式安装则需要进行网络配置,第二种方式则忽略

修改/etc/netplan/00-installer-config.yaml文件,若不存在则可以通过sudo nano来创建并编辑新文件,加入如下内容

network:

  ethernets:

    ens33:

      dhcp4: true

  version: 2

应用配置:sudo netplan apply

修改/etc/network/interfaces

auto lo

iface lo inet loopback

auto ens33

iface ens33 inet dhcp

重启网络:systemctl restart NetworkManager

2.安装VMtools

sudo apt-get update

sudo apt-get install open-vm-tools-desktop

附UBUNTU22.04阿里云镜像源

修改以下文件添加镜像源

sudo nano /etc/apt/source.list

deb https://mirrors.aliyun.com/debian/ bullseye main non-free contrib

deb-src https://mirrors.aliyun.com/debian/ bullseye main non-free contrib

deb https://mirrors.aliyun.com/debian-security/ bullseye-security main

deb-src https://mirrors.aliyun.com/debian-security/ bullseye-security main

deb https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib

deb-src https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib

deb https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib

deb-src https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib

3.安装Docker

①添加软件源密钥:curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

添加docker软件源:

echo \

  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian \

  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

③sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

4.编写Dockerfile

sudo nano Dockerfile

FROM gcc:4.9

COPY server.c /usr/src/app/

WORKDIR /usr/src/app

RUN gcc server.c -o server -pthread

CMD ["./server"]

5.编写server.c和client.c

server.c

#include <strings.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
 
void *send_data(void *arg)
{
    int connfd = *(int*)arg;
    char s[64] = {0};
    while(1)
    {
        fgets(s, 64, stdin);
        s[strlen(s)-1] = '\0';
        write(connfd, s, 64);
        memset(s, 0, 64);
    }
 
}
 
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
        perror("socket");
        return -1;
    }
    
    //端口复用函数
    int on = 1;
    int k = setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, &on, sizeof(on));
    if(k == -1)
    {
        perror("setsockopt");
        return -1;
    }
    
    
    struct sockaddr_in ser;
    ser.sin_family = AF_INET;
    ser.sin_port = htons(8090);
    ser.sin_addr.s_addr = inet_addr("172.17.0.2");
 
    int ret = bind(sockfd, (struct sockaddr *)&ser, sizeof(ser));
    if(ret == 0)
    {
        printf("绑定成功\n");
    }
    else
    {
        perror("bind");
        return -1;
    }
 
    ret = listen(sockfd, 5);
    if(ret == 0)
    {
        printf("监听成功\n");
    }
    else
    {
        perror("listen");
        return -1;
    }
 
    struct sockaddr_in client;
    int n = sizeof(client);
 
    int connfd;
    while(1)
    {
        connfd = accept(sockfd, (struct sockaddr *)&client, &n);
        if(connfd == -1)
        {
            perror("accept");
            return -1;
        }
        else
        {
            printf("连接成功\n");
        }
 
        printf("client ip:%s\nclient port:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
 
        pthread_t pid;
        pthread_create(&pid, NULL, send_data, (void *)&connfd);
        pthread_detach(pid);
 
        
 
while(1)
{
    char buf[64] = {0};
        ret = read(connfd, buf, 64);
        if(ret < 0)
        {
            perror("read");
            return -1;
        }
        else if(ret == 0)
        {
            close(connfd);
            break;
        }
            printf(">>:%s\n", buf);
       
 
            if(strcmp(buf, "time") == 0)
            {                  
               
                time_t now = time(NULL);
                char *p = ctime(&now);
                char data[64];
                strcpy(data, p);
                write(connfd, data, strlen(data));
                 
                memset(buf, 0, 64);
                memset(data, 0, 64);
            }
 
           else if(strncmp(buf, "get", 3) == 0)
            {
                
                int i, j = 0;
                char str[64] = {0};
                for(i = 4; i <= strlen(buf)-1; i++)
                {
                    str[j] = buf[i];
                    j++;
                }
                memset(buf, 0, 64);
                int fd = open(str, O_RDONLY);
                while((ret = read(fd, buf, 64)) != 0)
                {
                    write(connfd, buf, ret);
                    memset(buf, 0, 64);
                }
   
                write(connfd, "over", 64);
                memset(buf, 0, 64);
                 memset(str, 0, 64);
                close(fd);
            }
            else
            {
            char arr[64];
             
            sprintf(arr, "%ld", strlen(buf));
            write(connfd, arr, strlen(arr));
            memset(buf, 0, 64);
            memset(arr, 0, 64);
             
            }
 
    }
    }
 
    close(sockfd);
    
 
    return 0;

client.c

#include <strings.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
 
void *recv_data(void *arg)
{
    int sockfd = *(int *)arg;
    char s[64] = {0};
    while(1)
    {
        int ret = read(sockfd, s, 64);
        if(ret < 0)
        {
            perror("read");
            return NULL;
        }
        printf("%s\n", s);
        memset(s, 0, 64);
    }
 
}
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
        perror("socket");
        return -1;
    }
    
    pthread_t pid;
    pthread_create(&pid, NULL, recv_data, (void *)&sockfd);
    pthread_detach(pid);
 
    struct sockaddr_in ser;
    ser.sin_family = AF_INET;
    ser.sin_port = htons(8090);
    //ser.sin_addr.s_addr = inet_addr("主机网络地址");
    ser.sin_addr.s_addr = htonl(INADDR_ANY);
 
 
    int ret = connect(sockfd, (struct sockaddr *)&ser, sizeof(ser));
    if(ret == -1)
    {
        perror("connect");
        return -1;
    }
 
    char buf[64];
    while(1)
    {
        fgets(buf, 64, stdin);
        buf[strlen(buf)-1] = '\0';
        write(sockfd, buf, 64);
        
        if(strcmp(buf, "time") == 0)
        {
            char data[64];
            read(sockfd, data, 64);
            printf(">>:%s\n", data);
            memset(buf, 0, 64);
            memset(data, 0, 64); 
        }
        else if(strncmp(buf, "get", 3) == 0)
        {
            char str[64];
            while(read(sockfd, str, 64) != 0)
            {
            if(strcmp(str, "over") == 0)
            {
         memset(str, 0, 64);        
             break;
            }
            printf(">>:%s\n", str);
            memset(buf, 0, 64);
            memset(str, 0, 64); 
            }
        }
        else
        {    char arr[64] = {0};
            read(sockfd, arr, 64);
            printf(">>:%s\n", arr);
            memset(buf, 0, 64);
            memset(arr, 0, 64); 
        }
    }
    close(sockfd);
 
    return 0;
}

注意服务端IP地址一般为Docker的虚拟地址,若要实现多机通信,客户端连接的是虚拟机或者主机的地址,不是Docker虚拟地址

执行命令:docker build -it tcp:first

则会生成一个名为tcp:first的镜像,可通过docker images 查看

执行命令:docker run -p 8090:8050 -it --name test tcp:first

通过上述命令会使得服务端在容器中运行

在另一台主机上通过gcc client.c -o client即可生成客户端可执行文件,执行可执行文件可得到如下结果

 服务端端(手机拍的^.^):

客户端:

简单的tcp通信构建完成,server.c和client.c来源于TCP通信模型(C语言实现)_c语言实现tcp_昆工第一ikun的博客-CSDN博客

欢迎大家来讨论一起进步,如有错误之处请指出,谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值