网络框架

简介:网络分爲5层,软件开发需要用到的主要是上面两层:网络层,和应用层;路由器系统开发的估计需要用到传输层;所以如果研究网络的话,我们需要深入了解的是网络层和应用层;
关键字:网络层,应用层;
关键字解释:网络传输,可以想象成是快递包裹一样,快递有运输车(车里有快递箱,箱子里面有快递包裹,包裹表面有寄件单资讯,收件人根据这个来收到),这一层层的裹起来,就是不同层的职责所在,并非是爲了难爲我们这些学习网络的人;那麽,接下来,解释一下关键字:网络层是tcp/ip包裹的那一层,我们把原来的要发的data看作是物品的话,那麽网络层就是寄件单一样的东西,可以标志谁寄的,谁来收;而应用层是什麽呢?应用层是爲了简化或者说模式化网络层而出现的,更加方便包裹的这一层;
实战举例:我做的项目都是服务业自动化系统,这里会涉及到的最多的是socket,而通常socket编程就是针对网络层的,也就是通讯协议双方,制定protocol,这个protocol的内容是一些十六进制的编码,比如:https://ithelp.ithome.com.tw/upload/images/20210910/20139212zhttwaZqBh.png
也就是在data的前面加上一些协议头,不同的头表示data所属的内容是什麽,这样拆包的那方就知道用什麽方式拆包了,比如我发了一个int过去,协议中説好了,这个是一个4byte的int,那麽对方就可以用int_32来把这个data转成4byte的int了,就拿到数字了;深挖一下:网络中的包都是二进制的,所以我们用十六进制来制定协议,因爲拆包的时候1个byte就是1个char;下面逐步讲解如何发送socket:
关键字:socket,server,client,listen,connect;
建server:首先需要建立一个监听用的server,server需要的是两个ip+port,ip就是我们的网络地址(分爲公网和局域网,往往我们看到的ip是局域网的,由路由器自动分配的,公网ip可以去google直接查,内部通讯可以用局域网ip,但是对外通讯需要用公网ip,一般与其他厂商通讯,都需要公网ip),port是监听端口,这个是因爲我们电脑中有很多程序,到底哪个程序来处理从外部来的data呢?这个就出现了每个程序可以监听一个或多个端口(port),端口从1到几万都可以,但是低位的(几十几百的)往往都是公约端口,这些已经被占了,请不要使用,也就是说,如果我自己写一个程序来监听某个端口的话,最好找个端口值设高一些,比如几千几万等等;设定好之後,就监听这个ip+port就好了;
建一个或者多个client:client端,直接connect到 server端;
收发讯息:read 和 write;一般实际处理的时候,是需要多綫程处理的,因爲主程序还是在跑,当有资讯来的时候,就拆包,当需要发资讯的时候,就封包;
下面看一下代码(c++的,linux系统,vscode,cmake跑的):
server:
打开监听端口:

void CallCarServer::Init()
{
  int listenfd;//万物皆文件,请不要怀疑,所谓的监听端口,就是一个文件标识符(最原始的就是个int哟)

  if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
  {
      ERR_EXIT("ERROR");
  }
  struct sockaddr_in servaddr;
  memset(&servaddr, 0, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(CAR_DRIVING_SERVER_NETWORK_TARGET_PORT);
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  int on = 1;
  if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
  {
      ERR_EXIT("SETSOCKOPT");
  }
  if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
  {
      ERR_EXIT("ERROR");
  }
  if (listen(listenfd, SOMAXCONN) < 0)
  {
      ERR_EXIT("LISTEN");
  }
  struct sockaddr_in peeraddr;
  socklen_t peerlen = sizeof(peeraddr);
  int conn;
  char sendbuf[256];
  while (true)
  {
      conn = accept(listenfd, (struct sockaddr *)&peeraddr, &peerlen);
      if (conn < 0)
      {
          ERR_EXIT("accept");
      }

      printf("ip = %s, port = %d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));
      conn_ = conn;

      std::thread t_receive(&CallCarServer::thread_accept, this);
      t_receive.detach();
  }
  close(listenfd);
}

多执行绪处理数据:

void CallCarServer::thread_accept()
{
    char recvbuf[BUFF_SIZE];
    while (true)
    {
        sleep(1);

        memset(recvbuf, 0, sizeof(recvbuf));

        int num = read(conn_, recvbuf, sizeof(recvbuf));

        if (num <= 0)
        {
            continue;
        }
        printf("message length is %d\n", num);

        //take the length of message
        //int len = Lenth_Message(recvbuf);
        //len = num-4;

        char *message = new char(num - 4);
        for (int i = 0; i < len; i++)
        {
            message[i] = recvbuf[i + 4];
        }

        // DealMessage(message);

        ReceiveBuf *recvbuf = reinterpret_cast<ReceiveBuf *>(message);
        std::cout<< recvbuf->message.iCarID<<std::endl;

        delete (message);
        //SendCarGo(conn);
    }
    close(conn_);
}

client端:

int sock;
    if((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
    {
        ERR_EXIT("ERROR");
    }
    struct sockaddr_in servaddr;
    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(2978);
    servaddr.sin_addr.s_addr = inet_addr("192.168.200.243");
    
    if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
    {
        ERR_EXIT("connect");
    }

    char sendbuf[1024] = {0};
    char recvbuf[1024] = {0};

    while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL)
    {
        write(sock,sendbuf,strlen(sendbuf));
        memset(sendbuf,0,sizeof(sendbuf));
    }
    close(sock);

上面是基本知识,实战中,花更多时间的是制定protocol,下篇再讲解如何制定protocol;
以及可能大部分人使用的是应用层的network program:比如mqtt,http post等;


<<:  [Day09] Tableau 轻松学 - Data Source 页面

>>:  Day 10 实作基本档案

Day 0x12 - 建立 Return URL 的画面

0x1 前言 废话不多说,今日流程如下先观察传进内容,在针对内容刻画面 0x2 建立 Route 跟...

[访谈] APCS x 竞程选手 Colten

今天邀请到来自新化高中的 Colten 来分享他在高中竞程这条路上的种种历程。本次访谈有公开浏览,欢...

【从零开始的 C 语言笔记】第十二篇-Math 函式库介绍与应用

不怎麽重要的前言 上一篇我们介绍了什麽是指标,不晓得大家有没有比较了解地址的概念? 接下来我们来介绍...

追求JS小姊姊系列 Day4 -- 我知道很怪,但你不好奇字串姐变身会怎样吗(下)

前情提要 倒在路边的我,醒来发现人早已不见,只好回家过节。 (时间来到了,回到家中的午餐後) **我...

[Day 04] 眼前的黑不是黑,你说的白是什麽白?(直方图均衡化)

前言 「眼前的黑不是黑,你说的白是什麽白」-- 你是我的眼(萧煌奇) 没错,并非所有图片都是在理想的...