TCP编程及基础知识

一、端口号

  • 为了区分一台主机接收到的数据包应该转交给哪个进程来进行处理,使用端口号来区分
  • TCP端口号与UDP端口号独立
  • 端口用两个字节来表示    2byte(65535个)

众所周知端口:1~10231~255之间为众所周知端口,256~1023端口通常由UNIX系统占用)
已登记端口:1024~49151    (选1000以上10000以下) 
动态或私有端口:49152~65535

二、字节序  

   小端序(little-endian)  - 低序字节存储在低地址

   大端序(big-endian)    - 高序字节存储在低地址

网络中传输一字节以上的带类型的数据(比如short、int),必须使用网络字节序,即大端字节序。

查看主机是大端序还是小端序。

网络传输中,需要将每个主机的主机字节序(CPU决定),转换为网络中统一顺序的网络字节序

才能供双方主机去识别

只需要转换IP和port就可以,不需要转换传输的数据包的字节序

因为IP和port为 4个字节和2个字节,  而数据报一般都为char类型, 占一个字节

根据字节序的性质,内存存储大于一个字节类型的数据在内存中的存放顺序

所以char类型并不具有字节序的概念

1.主机字节序到网络字节序 (小端序->大端序)

#include <arpa/inet.h>
u_long htonl (u_long hostlong); //host to internet long
功能:将无符号整数hostlong从主机字节顺序转换为网络字节顺序。
#include <arpa/inet.h>
u_short htons (u_short short);  //掌握这个
功能:将无符号短整数hostshort从主机字节顺序到网络字节顺序。

2.网络字节序到主机字节序(大端序->小端序)

#include <arpa/inet.h>
u_long ntohl (u_long hostlong);
功能:将无符号整数netlong从网络字节顺序转换为主机字节顺序。
#include <arpa/inet.h>
u_short ntohs (u_short short);//端口 2byte
功能:将无符号短整数netshort从网络字节顺序转换为主机字节顺序。的

#include <stdio.h>
#include <arpa/inet.h>

int main(int argc, char const *argv[])
{
    int a = 0x12345678;
    //小端转大端
    int b = htonl(a);
    printf("%#x\n", b);
    //大端转小端
    int c = ntohl(b);
    printf("%#x\n", c);
    return 0;
}

三、IP地址转换

1、inet_addr主机字节序转换为网络字节序

#include<sys/socket.h>   
#include<netinet/in.h>               
#include<arpa/inet.h>
in_addr_t  inet_addr(const char *strptr);  //该参数是字符串
 
typedef uint32_t in_addr_t;
struct in_addr 
{
    in_addr_t s_addr;
};
功能:  主机字节序转为网络字节序
参数:  const char *strptr: 字符串
返回值: 返回一个无符号长整型数(无符号32位整数用十六进制表示), 
      否则NULL

2、inet_ntoa 网络字节序转换为主机字节序

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
char *inet_ntoa(struct in_addr inaddr);
功能:   将网络字节序二进制地址转换成主机字节序。 
参数:  struct in_addr in addr  : 只需传入一个结构体变量
返回值:  返回一个字符指针, 否则NULL;

四、TCP编程

C/S   B/S

client/server              browser/server

客户端/服务器 浏览器/服务器

1、套接字工作流程

客户端:   发送请求

服务器端:  相应请求

服务器:

1.创建流式套接字(socket())------------------------>  有手机

2.指定本地的网络信息(struct sockaddr_in)----------> 有号码

3.绑定套接字(bind())------------------------------>绑定手机

4.监听套接字(listen())---------------------------->待机

5.链接客户端的请求(accept())---------------------->接电话

6.接收/发送数据(recv()/send())-------------------->通话

7.关闭套接字(close())----------------------------->挂机

客户端:

1.创建流式套接字(socket())----------------------->有手机

2.指定服务器的网络信息(struct sockaddr_in)------->有对方号码

3.请求链接服务器(connect())---------------------->打电话

4.发送/接收数据(send()/recv())------------------->通话

5.关闭套接字(close())--------------------------- >挂机

服务器端(server):

1) socket(),创建套接字文件,创建出用于连接的套接字文件

2) bind(), 绑定,把socket()函数返回的文件描述符和IP、端口号进行绑定;

3) listen(), 监听,将socket()返回的文件描述符,由主动套接字变为被动套接字;

4) accept(), 阻塞函数,阻塞等待客户端的连接请求, 返回一个用于通信的套接字文件;

5) recv(), 接收客户端发来的数据;(read)    

//6) send(), 发送数据;(write)

  1. close(), 关闭文件描述符; 至少要关闭: 连接、通信

客户端(client):

  1. socket(),创建套接字文件,既用于连接,也用于通信; 

    填充结构体:  填充服务器的ip和端口 , 用于connect连接

2) connect(); 用于发起连接请求,阻塞等待连接服务器;

3) send(), 发送数据;

//4) recv(), 接收数据;

5)close(), 关闭文件描述符;

2、函数接口

1)socket 创建套接字

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
功能:创建套接字
参数:
   domain:协议族
     AF_UNIX, AF_LOCAL  本地通信
     AF_INET            ipv4
     AF_INET6            ipv6
   type:套接字类型
     SOCK_STREAM:流式套接字
     SOCK_DGRAM:数据报套接字
   protocol:协议 - 填0 自动匹配底层 ,根据type系统默认自动帮助匹配对应协议
       传输层:IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP
       网络层:htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL)
 返回值:
    成功 文件描述符 0 -> 标准输入  1->标准输出  2->标准出错 
                  3->socket
    失败 -1,更新errno

2)bind 绑定   ipv4  ip和端口 

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:绑定   ipv4  ip和端口 
参数
   sockfd:文件描述符
   addr:通用结构体,根据socket第一个参数选择的通信方式最终确定这需要真正填充传递的结构体是那个类型。强转后传参数。
   addrlen:填充的结构体的大小   
返回值:成功0 失败-1、更新errno

通用结构体:相当于预留一个空间
struct sockaddr 
{
    sa_family_t sa_family;
    char        sa_data[14];
}

ipv4的结构体 
 struct sockaddr_in 
 {
     sa_family_t    sin_family;  //协议族AF_INET
     in_port_t      sin_port;  //端口号
     struct in_addr sin_addr;  //ip地址
 };
  struct in_addr 11
 {
     uint32_t       s_addr;   //IP地址  
 };
 
 本地址通信结构体:
  struct sockaddr_un 
  {
     sa_family_t sun_family;  //AF_UNIX  
     char        sun_path[108]; //在本地创建的套接字文件的路径及名字
 };
 
ipv6通信结构体:
struct sockaddr_in6 
{
    sa_family_t     sin6_family;   
    in_port_t       sin6_port;     
    uint32_t        sin6_flowinfo; 
    struct in6_addr sin6_addr;     
    uint32_t        sin6_scope_id; 
};
struct in6_addr 
{
    unsigned char   s6_addr[16];   
};
//如果绑定使用通用地址可使用 INADDR_ANY宏(结合代码讲的时候再添加)
含义是自动绑定所有本机网卡的地址,

11.2作业

3)listen 监听,将主动套接字变为被动套接字

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
功能:监听,将主动套接字变为被动套接字
参数:
 sockfd:套接字
 backlog:同时响应客户端请求链接的最大个数,不能写0.
不同平台可同时链接的数不同,一般写6-8
返回值:成功 0   失败-1,更新errno  

4)accept 阻塞函数

#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept(sockfd,NULL,NULL);
阻塞函数,阻塞等待客户端的连接请求,如果有客户端连接,
accept()函数返回,返回一个用于通信的套接字文件描述符(4);
参数:
   Sockfd :套接字
   addr: 链接客户端的ip和端口号
      如果不需要关心具体是哪一个客户端,那么可以填NULL;
   addrlen:结构体的大小
     如果不需要关心具体是哪一个客户端,那么可以填NULL;
     需要查看链接的客户端ip和端口号
     accept(sockfd,NULL,NULL);
     需要查看链接的客户端ip和端口号
     accept(sockfd,(struct sockaddr *)&saddr,&len);
  返回值: 
     成功:文件描述符; //用于通信
失败:-1,更新errno
同时返回客户端的ip和端口号。保存到结构体struct sockaddr *addr中。
通过结构体访问到:inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)
打印时记得使用 inet_ntoa()和ntohs()转换为主机字节序

5)recv 接收数据 

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能: 接收数据 
参数: 
    sockfd: acceptfd ;
    buf  存放位置
    len  大小
    flags  一般填0,相当于read()函数
    MSG_DONTWAIT  非阻塞
返回值: 
   < 0  失败出错  更新errno
   ==0  表示客户端退出
   >0   成功接收的字节个数

发送端协议类型为TCP Client,远程目标ip地址为服务器IP地址

端口号也应该一致

先关闭客户端,再关闭服务器。

6)connect 用于连接服务器;

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:用于连接服务器;
参数:
     sockfd:socket函数的返回值
     addr:填充的结构体是服务器端的;
     addrlen:结构体的大小
返回值 
      -1 失败,更新errno
      正确 0 

7)send 发送数据,用来发送消息到一个套接字中。

#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送数据,用来发送消息到一个套接字中。只能在套接字处于连接状态的时候才能使用。
参数:
    sockfd:socket函数的返回值
    buf:发送内容存放的地址
    len:发送内存的长度
    flags:如果填0,相当于write();
返回值;
    成功 发送的字节数
    失败 -1
可以使用write代替send,  都属于往发送缓存区内写入数据
read代替recv , 都属于往接收缓存区内提取数据

测试注意:

1. 如果使用客户端软件进行连接,必须保证windows和虚拟机在同一个局域网(桥接),并能互相ping通。服务器的IP地址必须指定为虚拟机自己的IP。

2. 必须保证客户端正常退出后在关闭服务器程序,在客户端连接状态情况下强制关闭服务器程序,下次启动服务器程序后会提示bind err。这是因为没有正常释放绑定的端口,等1~2分钟就可以了。

3、代码优化

1。端口和ip地址通过命令行传参到代码中。(如果参数不一致,应该提示并退出)
2。服务器端IP地址可由“0.0.0.0”自动获取,或者由宏定义自动获取

3。客户端发送去掉fgets获取的多余的'\n'.

fgets(实际读到的内容小于等于指定个数-1,自动读到的内容后添加’\0’,会将’\n’也读入)

  if(buf[strlen(buf)-1] == '\n')//去掉fgets获取的'\n'

         buf[strlen(buf)-1] ='\0';

4.设置来电显示功能,获取到请求链接服务器的客户端的ip和端口。

 int acceptfd = accept(sockfd,(struct sockaddr *)&caddr,&len);

打印时记得使用 inet_ntoa()和ntohs()转换为主机字节序

printf("client ip:%s ,port:%d\n", inet_ntoa(saddr.sin_addr),ntohs(saddr.sin_port));

5、当客户端输入quit的时候,客户端退出

   strncmp

6.实现循环服务器,服务器不退出,当链接服务器的客户端退出,服务器等到下一个客户端链接。

  accept处使用while到接受数据结束。

/*服务器创建代码 */
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    if (argc < 2)
    {
        printf("plase input <ip><port>\n");
        return -1;
    }
    //1.创建套接字,用于链接
    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    //文件描述符 0 -> 标准输入  1->标准输出  2->标准出错  3->socket
    printf("sockfd:%d\n", sockfd);

    //2.绑定 ip+port 填充结构体
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;            //协议族ipv4
    saddr.sin_port = htons(atoi(argv[1])); //端口号,htons将无符号短整数hostshort从主机字节顺序到网络字节顺序。
//atoi(),字符串转整型
//saddr.sin_addr.s_addr = inet_addr(argv[1]);//ip地址,转化为16进制表示
#if 0
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");//ip地址,转化为16进制表示
#else
    saddr.sin_addr.s_addr = INADDR_ANY;
#endif
    socklen_t len = sizeof(saddr); //结构体大小
    //bind绑定ip和端口
    if (bind(sockfd, (struct sockaddr *)&saddr, len) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind success\n");
    //3.启动监听,把主动套接子变为被动套接字
    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen success\n");
    //4.阻塞等待客户端的链接请求
    int acceptfd;
    // acceptfd = accept(sockfd,NULL,NULL);
    while (1)
    {
        acceptfd = accept(sockfd, (struct sockaddr *)&saddr, &len);
        //获取客户端的ip和端口,(struct sockaddr *)&saddr:用来存放返回的ip,和端口
        if (acceptfd < 0)
        {
            perror("accept err");
            return -1;
        }
        printf("client ip:%s ,port:%d\n", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
        printf("connect success\n");
    //5.接收数据
    char buf[64];
    int ret;
    while (1)
    {
        ret = recv(acceptfd, buf, sizeof(buf), 0);
        if (strncmp(buf, "quit", 4) == 0) //接收到quit退出
        {
            break;
        }
        if (ret < 0)
        {
            perror("recv err.");
            return -1;
        }
        else if (ret == 0) //客户端退出
        {
            printf("client exit\n");
            break;
        }
        else
        {
            printf("buf:%s\n", buf);
        }
    }
    }
    close(sockfd);
    close(acceptfd);
    return 0;
}

/*客户端创建代码 */
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    if (argc < 3)
    {
        printf("plase input <ip><port>\n");
        return -1;
    }
    //1.创建套接字,用于链接
    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    //文件描述符 0 -> 标准输入  1->标准输出  2->标准出错  3->socket
    printf("sockfd:%d\n", sockfd);
    //2.绑定 ip+port 填充结构体
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;                 //协议族ipv4
    saddr.sin_port = htons(atoi(argv[2]));      //端口号,htons将无符号短整数hostshort从主机字节顺序到网络字节顺序。
    saddr.sin_addr.s_addr = inet_addr(argv[1]); //ip地址,转化为16进制表示
    socklen_t len = sizeof(saddr);              //结构体大小
    //3用于连接服务器;
    if (connect(sockfd, (struct sockaddr *)&saddr, len) < 0)
    {
        perror("connect err");
        return -1;
    }
    //4发送信息
    char buf[64] = {0};
    while (1)
    {
        fgets(buf, sizeof(buf), stdin);   //从终端获取内容存放到数组中
        if (strncmp(buf, "quit", 4) == 0) //输入quit退出客户端
        {
            break;
        }
        if (buf[strlen(buf)] == '\0')
        {
            buf[strlen(buf) - 1] = '\0';
        }                                  //将fgets自动补的\n去掉
        send(sockfd, buf, sizeof(buf), 0); //将数组中的内容发送到主机端
    }
    close(sockfd);
    // close()
    return 0;
}

ftp文件传输协议

tcp实现ftp功能:

模拟FTP核心原理:客户端连接服务器后,向服务器发送一个文件。文件名可以通过参数指定,服务器端接收客户端传来的文件(文件名随意),如果文件不存在自动创建文件,如果文件存在,那么清空文件然后写入。

项目功能介绍:

均有服务器和客户端代码,基于TCP写的。

在同一路径下,将客户端可执行代码复制到其他的路径下,接下来再不同的路径下运行服务器和客户端。

相当于另外一台电脑在访问服务器。

客户端和服务器链接成功后出现以下提示:四个功能

***************list**************//列出服务器所在目录下的文件名(除目录不显示)

***********put filename**********//客户端给服务器上传一个文件

***********get filename**********//客户端从服务器所在路径下载文件

**************quit***************//退出(可只退出客户端,服务器等待下一个客户端链接)

//读文件,读到最后一次,最后再发送end

//粘包:1.延时 2.读多少发多少

服务器

  1. 搭建tcp框架
  2. 服务器接收消息

//list 列出服务器所在目录下的文件名 目录操作 文件属性获取--发送给客户端

//put filename //接收文件 recv --》新建文件---》 写文件 

//get filename //读文件--》发送给客户端

//quit  while(1)accpet;

客户端

  1. 搭建tcp框架
  2. 列出功能
  3. 给服务器发消息

//list 接收--》列出服务器所在目录下的文件名

//put filename 找到文件--》读文件   -》发送

//get filename //接收文件 recv --》新建文件---》 写文件 

//quit   

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu网络IP地址一直显示127.0.0.1

问题描述&#xff1a; 终端输入ip a显示127.0.0.1&#xff0c;原来类似192.168.231.1的地址不见了。 ip a 点击网络配置&#xff08;ubuntu桌面版&#xff09;&#xff0c;发现无线网络模块看不见了 正常情况应该有wired 模块&#xff0c;就是下面标红的 解决方案&#xff1a…

学为贵雅思写作备考

准确通顺&#xff0c;言之有物 两次读不懂&#xff0c;6分以下&#xff0c; 6分没有印象&#xff0c;味同嚼蜡&#xff0c;但是没错&#xff08;书面语过关&#xff09; 英语比较过关 8-9分&#xff0c;很有见地 6-7单个的句子读得懂&#xff0c;前后是贯通的、逻辑是通顺…

发现一款PDF转换成翻页电子书的网站

​随着科技的发展&#xff0c;电子书越来越受到人们的喜爱。而PDF格式的文件也越来越多地被人们使用。那么&#xff0c;如何将PDF文件转换成翻页电子书呢&#xff1f;今天就为大家推荐一款好用的PDF转翻页电子书网站。 一、网站介绍 这款网站是一款非常实用的在线转换工具&…

Devchat AI尝鲜试用:程序员开发提效利器,告别脏活累活

DevChat 简介 在当今的软件开发领域&#xff0c;程序员们每天都要面对海量的代码和复杂的任务。尽管技术不断发展&#xff0c;但程序员们依然需要花费大量时间进行重复性工作&#xff0c;如代码审查、错误排查、文档编写等。这些脏活累活不仅消耗了程序员们大量的时间和精力&am…

draw.io与项目管理——如何利用流程图工具提高项目管理效率

draw.io 是一款强大的图形绘制工具&#xff0c;用于创建各种类型的图表、流程图、组织结构图、网络图和平面设计等。它提供了丰富的绘图工具和预定义的图形库&#xff0c;使用户能够轻松创建专业水平的图形作品。 draw.io具有直观的界面和简单易用的功能&#xff0c;适合各种用…

gradle学习笔记

gradle学习笔记 一、下载安装配置环境变量二、使用gradle管理spring项目1、创建项目2、导入项目至编辑器3、打包部署4、将maven项目转为gradle项目 三、gradle介绍1、常用命令2、Gradle Wrapper包装器3、gradle进阶说明4、gradle插件 四、Groovy 简介 参考博客&#xff1a;http…

VM虚拟机逆向 --- [NCTF 2018]wcyvm 复现

文章目录 前言题目分析 前言 第四题了&#xff0c;搞定&#xff0c;算是独立完成比较多的一题&#xff0c;虽然在还原汇编的时候还是很多问题。 题目分析 代码很简单&#xff0c;就是指令很多。 opcode在unk_6021C0处&#xff0c;解密的数据在dword_6020A0处 opcode [0x08, …

原子化 CSS 真能减少体积么?

前言 最近看到这样一篇文章&#xff1a;《要喷也得先做做功课吧&#xff1f;驳Tailwind不好论》 个人觉得说的还是有一定道理的&#xff0c;就是该作者的语气态度可能稍微冲了点&#xff1a; 不过他说的确实有道理&#xff0c;如果这种原子化工具真的如评论区里那帮人说的那么…

【jvm】虚拟机栈

目录 一、背景二、栈与堆三、声明周期四、作用五、特点&#xff08;优点&#xff09;六、可能出现的异常七、设置栈内存大小八、栈的存储单位九、栈运行原理十、栈帧的内部结构10.1 说明10.2 局部变量表10.3 操作数栈10.4 动态链接10.5 方法返回地址10.6 一些附加信息 十一、代…

明御安全网关任意文件上传漏洞复现

简介 安恒信息明御安全网关(NGFW) 秉持安全可视、简单有效的理念&#xff0c;以资产为视角的全流程防御的下一代安全防护体系&#xff0c;并融合传统防火墙、入侵防御系统、防病毒网关、上网行为管控、VPN网关、威胁情报等安全模块于一体的智慧化安全网关。 较低版本的系统存…

淘宝API技术文档解析,从入门到实战

探索淘宝数据的奥秘&#xff0c;淘宝是目前国内最大的B2C电商平台之一&#xff0c;每天都会产生海量的数据。借助淘宝API技术文档&#xff0c;我们可以轻松地获取到这些数据&#xff0c;从而为电商运营和数据分析提供有力支持。 1.什么是淘宝API&#xff1f; 淘宝API&#xf…

用免费GPU线上优化猫狗识别实践

该部分以“猫狗识别模型”为例&#xff0c;学习如何直接通过平台提供的开发环境调用GPU资源 一.学习准备 获取官方代码文件&#xff1a;https://platform.virtaicloud.com/gemini_web/workspace/space/n9tte8i2aspd/project/list 二.创建项目 1&#xff09;进入趋动云用户工…

轻量封装WebGPU渲染系统示例<12>- 基础3D对象实体(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/PrimitiveEntityTest.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 细节请见&#xff1a;引擎系统设计思路 - 用户态与系统态隔离-CSDN博客 2. 高频调用与低频调用隔…

不会写文档的程序员不是好的程序员

在当今数字化的世界中&#xff0c;软件开发行业正经历着前所未有的繁荣。从移动应用到大型企业系统&#xff0c;软件构建了现代社会的基础。在IT行业中&#xff0c;文档是一种非常重要的沟通工具。它可以帮助程序员和客户及团队成员之间进行有效的沟通和协作&#xff0c;提高工…

基于springboot实现原创歌曲分享平台系统项目【项目源码+论文说明】

基于springboot实现原创歌曲分享平台系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理平台应运而生…

工业自动化工厂PLC远程控制网关物联网应用

远程控制网关在工厂自动化领域中起到了至关重要的作用&#xff0c;特别是在工厂PLC数据通讯方面。它充当着数据传输的桥梁&#xff0c;连接了工厂中的各类设备和系统&#xff0c;实现了远程监控和控制的功能。本文将详细介绍远程控制网关在工厂PLC数据通讯中的应用。 远程控制网…

项目上线前发现严重Bug怎么办?

今天分享一个面试问题&#xff0c;现在有一个面试场景&#xff1a; 项目计划明天发布&#xff0c;但是在今天你作为测试人员发现了一个严重的bug&#xff0c;市场相关人员又在催发布的事情&#xff0c;这个时候你应该怎么办&#xff1f; 这是测试工程师不管是在面试&#xff0…

大数据毕业设计选题推荐-智慧小区大数据平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

gitlab数据备份和恢复

gitlab数据备份 sudo gitlab-rake gitlab:backup:create备份文件默认存放在/var/opt/gitlab/backups路径下&#xff0c; 生成1697101003_2023_10_12_12.0.3-ee_gitlab_backup.tar 文件 gitlab数据恢复 sudo gitlab-rake gitlab:backup:restore BACKUP1697101003_2023_10_12_…

苹果加大对印度的扶持,提高在其生产iphone的比重

KlipC报道&#xff1a;跟踪苹果产业链&#xff0c;有分析师预计2023年全球约12%-14%的iphone在印度生产&#xff0c;预计2024年&#xff0c;印度将生产20%-25%的iphone。 KlipC的合伙人Andi D表示&#xff1a;“近年来随着苹果对中国的以来&#xff0c;印度已经成为高科技制造和…