第三天:实现网络编程基于tcp/udp协议在Ubuntu与gec6818开发板之间双向通信

news2025/1/11 4:00:54

互联网地址

每一台设备接入互联网后,都会举报一个唯一的地址编号

IP地址 INTERNET地址

internet地址 :它是协议上的一个逻辑地址

目前来说,我们主要的IP地址有两类 IPV4 IPV6

IPV4 其实就是使用一个32bit整数作为IP

IPV6 其实就是使用一个128bit整数作为IP

ipv4

1010 1100 0000 0010 0000 0001 0000 0001 人类是看不到的

172.2.1.1 给人看的"点分式"

每8bit组成一个十进制数,以 ‘.’ 隔开

2^32 个地址

这么多地址,怎么去管理?

类似电话号码 =区号+主机号

+86 0731 12345678

+86 中国大陆

0731 长沙

12345678 具体那个电话的号码

同理,ip地址也分为两个部分

ip地址=网络号+主机号

网络号:用于标识网络中的某个子网,占ip地址中的高x位

主机号:用于标识同一个子网内的不同主机,占地址中低的(32-x)位

也叫做 子网号 子网主机号

所占的bit位x又怎么确定呢?

netmask 子网掩码,用来确定一个ip地址中,网络号与主机号的占比

IP地址的bit位在子网掩码中对应的bit为1,就是网络号

在子网掩码中为0,就是主机号

比如:

ip 172.2.1.1

netmask 255.255.255.0

网络号 ip&netmask 172.2.1.0

主机号的范围 172.2.1.0 ~ 172.2.1.255

目前ip地址主要分为5类

在这里插入图片描述

我们常用的是C类网络

端口号

在网络中,可以提供ip地址来区分不同的网络设备

如果两个设备的IP相同 —》ip冲突,只有一台能够接入网络

问题;一台设备上,或许会运行多个网络应用

比如:我打开QQ给你们传文件,同时还在直播上课

那么网络中,怎么知道传递的数据,是由哪个网络应用发起的呢?

ip只能区分是那一台主机,不能区分是那一个应用

为了区分哪个网络应用传输的数据,需要用到端口号

TCP和UDP都是采用16bit无符号整数来作为端口号标识网络应用

IP —>标识网络中的某个设备

端口 —》标识设备上的某个网络应用

一台主机上的网络应用由:

ip地址+传输层协议(TCP/UDP)+端口号来确定

端口号 由 IANS 来管理

1-1023 众所周知的端口

比如 HTTP应用 80

FTP服务 20

1024-49151 注册端口,提供注册端口

49151-65536 动态或者私有端口,可以随便用

字节序

大端模式

高地址存储低字节 低地址存储高字节

小端模式

低地址存储低字节 高地址存储高字节

比如: int a = 0x12345678

&a = 0x4000

内存地址大端模式存储内容小端模式存储内容
0x40000x120x78
0x40010x340x56
0x40020x560x34
0x40030x780x12

不同的系统对于内存的管理方法不同,可能采用大端模式,可能采用小端模式

练习:尝试写一个程序,判断自己的Linux系统是大端模式还是小端模式,并且输出结果

int a = 1; //0x00 00 00 01
char *p = &a
if(*p == 1)
{
	printf("小端模式\n");
}
else
{
	printf("大端模式\n");
}

网络字节序采用的是大端模式

网络接口 socket

网络通信接口 socket是一个简单易上手,功能强大的接口

有以下特点:

1.socket是一个编程接口(网络编程接口)

所有的网络程序,都需要基于socket

2.socket也是一个特殊的文件描述符

特殊:可以利用系统文件接口

比如 read write close

但是不能用lseek

它的内容不在文件系统中,也不在内核中,而是在"网络"中

3.socket 是TCP/IP协议的一种代码实现

但是它不仅限于TCP/IP协议,它还支持蓝牙协议,wifi协议,unix域协议

socket独立于具体协议的网络程序接口,位于应用层与传输层之间,负责衔接应用层与传输层

网络通信

网络通信的实现—》 API(应用程序编程接口)

1.socket 创建一个套接字

2.bind 不动,将一个地址(网络应用地址:IP+传输协议+端口)与套接字绑定

3.listen 监听,用于设定服务器监听套接字(监听后就可以获得客户端的请求)

4.accpet 等待连接请求的到来

5.connect 用于发起连接请求

6.通信 数据收发

​ read/write

​ recv/send

​ recefrom/send_to

7.关闭套接字

close 套接字也就是一个文件描述符罢了

思考 在网络通信在,服务器和客户端 双方的通信流程图

在这里插入图片描述

1 socket

NAME
       socket - create an endpoint for communication

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
		socket用来创建一个通信接口
       int socket(int domain, int type, int protocol);
			@domain:指定域,协议族
            AF_UNIX, AF_LOCAL   Local communication              unix(7)
                unix域协议/本地协议栈
            AF_INET             IPv4 Internet protocols          ip(7)
                IPV4协议族
            AF_INET6            IPv6 Internet protocols          ipv6(7)
                IPV6协议族
            @type:指定套接字类型(选择传输层协议)
				SOCK_STREAM 流式套接字,面向TCP传输层协议
                SOCK_DGRAM  数据报套接字,面向UDP传输层协议
                SOCK_RAW	原始套接字
			@protocol:协议,指定具体那个协议
                一般为0,表示默认
                
             返回值:成功返回一个整数,是一个套接字文件描述符
                失败返回-1,并且errno被设置

2 bind

用于绑定服务器地址(IP+传输层协议+端口号)

NAME
       bind - bind a name to a socket

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
		bind 绑定一个"名字”给socket(套接字描述符)
       int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
			@sockfd:指定套接字描述符,就是socket的返回值
            @addr:指向struct sockaddr 结构体指针,保存的是要绑定的地址
            @addrlen:地址长度,即参数addr的长度,sizeof (struct sockaddr)
		返回值:成功返回0,失败返回-1,并且errno被设置

关于网络应用的地址 =IP+传输层协议+端口号

在 头文件<sys/socket.h>中,定义了一个通用的网络应用地址结构体

struct sockaddr {
               sa_family_t sa_family;//指定协议栈,和socket函数的参数domain相同
    
               char        sa_data[14];
    		//数组保存网络应用地址(IP+传输层协议+端口号)
           }

上面这个结构体,并不是很好赋值和使用,一般在网络编程中,网络应用地址赋值可以采用定义在

/usr/include/netinet/in.h中的结构体 struct sockaddr_in

Structure describing an Internet socket address

以太网地址结构体

struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);//协议栈   sin_family
    in_port_t sin_port;			/* 端口号,网络上一般是大端模式,计算机一般是小端模式  */
    struct in_addr sin_addr;		/* 指定ip地址. 
                        typedef uint32_t in_addr_t;
                        struct in_addr
                          {
                            in_addr_t s_addr;
                          };
    */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
			   __SOCKADDR_COMMON_SIZE -
			   sizeof (in_port_t) -
			   sizeof (struct in_addr)];
  };

eg:某个网络应用

ip 172.2.1.11

端口 6666

struct sockaddr_in addr;//定义一个网络应用地址结构体addr
addr.sin_family=AF_INET;//协议族
addr.sin_port = htons(6666);//端口号是网络字节序,短整型
addr.sin_addr.s_addr = inet_addr(172.2.1.11);//点分式IP转为32bit整数
int ret = 0;//返回值
ret = bind(sockfd,(struct sockaddr)&addr,sizeof(addr));
if(ret == -1)
{
    perror("bind error");
    return -1;
}
//bind 之后,进程就有了一个网络应用地址,能够进行网络通信

端口本地字节序转网络字节序

h host 主机

to 转换成

n network 网络

s short 16bit

l long 32bit

NAME
       htonl, htons, ntohl, ntohs - convert values between host and network byte order

SYNOPSIS
       #include <arpa/inet.h>

       uint32_t htonl(uint32_t hostlong);
		将本地字节序转换成网络长整型
       uint16_t htons(uint16_t hostshort);
		将本地字节序转换成网络短整型
       uint32_t ntohl(uint32_t netlong);
		将网络字节序转换成本地长整型
       uint16_t ntohs(uint16_t netshort);
		将网络字节序转换成本地短整型
            
        参数就是需要转换的数据
        返回值就是转换之后的数据

点分式ip与32bit ip的转换

NAME
       inet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation routines

SYNOPSIS
       #include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>

		inet_addr是用来将cp指定的点分式ip转换成32bit整数ip返回
       in_addr_t inet_addr(const char *cp);
			@cp 指针,指向要转换的点分式字符串ip
                成功返回转换后的32bit整数

网络通信

网络通信的实现—》 API(应用程序编程接口)

1.socket 创建一个套接字

2.bind 不动,将一个地址(网络应用地址:IP+传输协议+端口)与套接字绑定

3.listen 监听,用于设定服务器监听套接字(监听后就可以获得客户端的请求)

4.accpet 等待连接请求的到来

5.connect 用于发起连接请求

6.通信 数据收发

​ read/write

​ recv/send

​ recefrom/send_to

7.关闭套接字

close 套接字也就是一个文件描述符罢了

思考 在网络通信在,服务器和客户端 双方的通信流程图

在这里插入图片描述

1 socket

NAME
       socket - create an endpoint for communication

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
		socket用来创建一个通信接口
       int socket(int domain, int type, int protocol);
			@domain:指定域,协议族
            AF_UNIX, AF_LOCAL   Local communication              unix(7)
                unix域协议/本地协议栈
            AF_INET             IPv4 Internet protocols          ip(7)
                IPV4协议族
            AF_INET6            IPv6 Internet protocols          ipv6(7)
                IPV6协议族
            @type:指定套接字类型(选择传输层协议)
				SOCK_STREAM 流式套接字,面向TCP传输层协议
                SOCK_DGRAM  数据报套接字,面向UDP传输层协议
                SOCK_RAW	原始套接字
			@protocol:协议,指定具体那个协议
                一般为0,表示默认
                
             返回值:成功返回一个整数,是一个套接字文件描述符
                失败返回-1,并且errno被设置

2 bind

用于绑定服务器地址(IP+传输层协议+端口号)

NAME
       bind - bind a name to a socket

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
		bind 绑定一个"名字”给socket(套接字描述符)
       int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
			@sockfd:指定套接字描述符,就是socket的返回值
            @addr:指向struct sockaddr 结构体指针,保存的是要绑定的地址
            @addrlen:地址长度,即参数addr的长度,sizeof (struct sockaddr)
		返回值:成功返回0,失败返回-1,并且errno被设置

关于网络应用的地址 =IP+传输层协议+端口号

在 头文件<sys/socket.h>中,定义了一个通用的网络应用地址结构体

struct sockaddr {
               sa_family_t sa_family;//指定协议栈,和socket函数的参数domain相同
    
               char        sa_data[14];
    		//数组保存网络应用地址(IP+传输层协议+端口号)
           }

上面这个结构体,并不是很好赋值和使用,一般在网络编程中,网络应用地址赋值可以采用定义在

/usr/include/netinet/in.h中的结构体 struct sockaddr_in

Structure describing an Internet socket address

以太网地址结构体

struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);//协议栈   sin_family
    in_port_t sin_port;			/* 端口号,网络上一般是大端模式,计算机一般是小端模式  */
    struct in_addr sin_addr;		/* 指定ip地址. 
                        typedef uint32_t in_addr_t;
                        struct in_addr
                          {
                            in_addr_t s_addr;
                          };
    */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
			   __SOCKADDR_COMMON_SIZE -
			   sizeof (in_port_t) -
			   sizeof (struct in_addr)];
  };

eg:某个网络应用

ip 172.2.1.11

端口 6666

struct sockaddr_in addr;//定义一个网络应用地址结构体addr
addr.sin_family=AF_INET;//协议族
addr.sin_port = htons(6666);//端口号是网络字节序,短整型
addr.sin_addr.s_addr = inet_addr(172.2.1.11);//点分式IP转为32bit整数
int ret = 0;//返回值
ret = bind(sockfd,(struct sockaddr)&addr,sizeof(addr));
if(ret == -1)
{
    perror("bind error");
    return -1;
}
//bind 之后,进程就有了一个网络应用地址,能够进行网络通信

端口本地字节序转网络字节序

h host 主机

to 转换成

n network 网络

s short 16bit

l long 32bit

NAME
       htonl, htons, ntohl, ntohs - convert values between host and network byte order

SYNOPSIS
       #include <arpa/inet.h>

       uint32_t htonl(uint32_t hostlong);
		将本地字节序转换成网络长整型
       uint16_t htons(uint16_t hostshort);
		将本地字节序转换成网络短整型
       uint32_t ntohl(uint32_t netlong);
		将网络字节序转换成本地长整型
       uint16_t ntohs(uint16_t netshort);
		将网络字节序转换成本地短整型
            
        参数就是需要转换的数据
        返回值就是转换之后的数据

点分式ip与32bit ip的转换

NAME
       inet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation routines

SYNOPSIS
       #include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>

		inet_addr是用来将cp指定的点分式ip转换成32bit整数ip返回
       in_addr_t inet_addr(const char *cp);
			@cp 指针,指向要转换的点分式字符串ip
                成功返回转换后的32bit整数

3 listen

设置监听,用于监听网络上是否有客户端向“我”(服务器)发起链接请求

NAME
       listen - listen for connections on a socket

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>
		
       int listen(int sockfd, int backlog);
			@sockfd:指定要监听的套接字描述符
            @backlog:监听数量,大于0就行了
            返回值:成功返回0  
                失败返回-1,并且errno被设置

listen设置去监听套接字描述符,以便知道是否有人(客户端)向我(服务器)发起链接请求

但是listen只监听,不处理链接

Eg:

int ret = 0;
ret = listen(sockfd,10);
if (ret == -1)
{
	perror("listen error");
}

4 accept

用于等待链接请求,并且处理链接请求

accpet会阻塞进程的运行,直到客户端向服务器发起了链接请求(客户端调用了connect)

NAME
       accept, accept4 - accept a connection on a socket

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
			@sockfd:指定套接字描述符
            @addr:指向struct sockaddr 结构体空间地址
             		用于存储客户端的地址
            @addrlen:socklen_t空间地址
                addrlen参数在使用前,需要先赋值 参数addr的长度
                因为在函数内部,会先利用addrlen的值来确保捕获导致内存溢出
                
            返回值:成功返回一个非负数,该值是一个文件描述符===》链接套接字描述符
                用于 服务器与链接的客户端的通信接口
                也就是说服务器是提供accept的返回值 来收发客户端的消息
                失败 返回-1,并且errno被设置

eg:

struct sockaddr_in caddr;//用于保存客户端的地址
socklen_t caddr_len = sizeof(caddr);//保存客户端地址长度,使用前保存该地址空间的长度
int connfd = 0;//用于保存 链接套接字描述符
connfd = accept(sockfd,(struct sockaddr*)&caddr,$caddr_len);
if(connfd == -1)
{
    perror("accept error");
    return -1;
}

如果accept指向成功,则connfd就是服务器与客户端之间的通信接口

如果我们是多次调用accept,那么九年允许多个客户端连接,并且每个客户端连接上来后

服务器上都有一一对应的connfd

5 connect

用于客户端向服务器发起链接请求

NAME
       connect - initiate a connection on a socket

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

       int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);
			@sockfd:指定套接字描述符
            @addr:指定要连接的服务器的地址
            @addrlen:addr的长度
            返回值:成功返回0
                失败返回-1,并且errno被设置

客户端调用 connect发起连接请求后,服务器的acceot接收到连接请求,并返回一个connfd用于服务器与客户端的通信接口

此时,客户端写入/发送数据给sockfd的数据就会通过网络传递给服务器的connfd

服务器就可以从connfd中读取/接收 这些数据

eg:

int ret = 0;
struct sockaddr_in saddr;
saddr.sin_family=AF_INET;//IPV4协议族
saddr.sin_port = htons(6666);//端口号是网络字节序,短整型
saddr.sin_addr.s_addr = inet_addr(172.2.1.110);//客户端的ip
ret = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
if (ret == -1)
{
    perror("connect error");
    return -1;
}

6 数据收发

1 read/write

socket的网络通信,其利用的是文件描述符(符合Linux的设计哲学)

2 recv/send 接收/发送

recv 结束

NAME
       recv, recvfrom, recvmsg - receive a message from a socket

SYNOPSIS
       #include <sys/types.h>
       #include <sys/socket.h>
			recv用于从指定的套接字描述符中接收数据(同read)
       ssize_t recv(int sockfd, void *buf, size_t len, int flags);
			@sockfd:指定套接字描述符,即从那个接收输入
            @buf:指向一块缓存区,用于存储接收到的数据
            @len:指定要接收的字节数
            @flags:接收标志位
                0 默认接收,带阻塞接收
                如果能接收到数据就接收数据
                如果不能接收到数据,就一直等待,直到接收到数据
                MSG_DONTWAIT  不阻塞接收
                如果能够接收到数据,则接收数据
                如果不能接收到数据,则直接返回
                
                返回值:
                >0 成功返回实际接收到的字节数
                0 什么都没有接收到
                -1 接收失败,并且errno被设置

send 发送

NAME
       send, sendto, sendmsg - send a message on a socket

SYNOPSIS
       #include <sys/types.h>
       #include <sys/socket.h>
		send 用于向套接字描述符中发送数据
       ssize_t send(int sockfd, const void *buf, size_t len, int flags);
				@sockfd:指定套接字描述符,即发送到那里去
                @buf:指向要发送的数据
                @len:要发送的数据大小,单位字节
                @flags:发送标志位
                    0 阻塞发送
                    MSG_DONTWAIT 非阻塞发送
                    
                返回值 成功返回实际发送的字节数(>=0)
						失败返回-1 并且errno被设置

3 recvfrom/sendto

从哪里接收/发送给谁

特点

recvfrom 可以保存是谁发送过来的数据(保存发送者的地址)

sendto 可以指定发送的对象(地址),定向发送

一般用于UDP通信,很少使用在TCP通信中?WHY?

因为TCP面向连接的通信,在通信前就已经要求通信双方建立连接

UDP是非连接的通信,所以他需要指定发送给谁,要保留发送者的地址

recvfrom

NAME
       recv, recvfrom, recvmsg - receive a message from a socket

SYNOPSIS
       #include <sys/types.h>
       #include <sys/socket.h>
 
       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);
		@前面四个参数 同recv
        @src_addr:指向一个 struct sockaddr缓存区(地址),用于存储对方的地址
        @addrlen:指向一个 socklen_t缓存区(地址)用于存储对方地址的长度
            src_addr和addrlen的使用,参考accept函数

sendto

NAME
       send, sendto, sendmsg - send a message on a socket

SYNOPSIS
       #include <sys/types.h>
       #include <sys/socket.h>

       ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);
		@前四个参数 同send
        @dest_addr:指向一个 struct sockaddr缓存区(地址),表示发送给谁
        @addrlen:即dest_addr的长度

4 recvmsg/sendmsg

以结构体的形式 发送数据/接收数据

7 关闭套接字

套接字: socket 套接字描述符

服务器:用于监听,看是否有客户端发起连接请求

客户端:用于客户端与服务器的通信接口

close 关闭套接字

shutdown

NAME
       shutdown - shut down part of a full-duplex connection

SYNOPSIS
       #include <sys/socket.h>
		shutdown用于关闭一个链接通道
       int shutdown(int sockfd, int how);
		@sockfd:指定套关闭那个链接通道
        @how:怎样关闭
            SHUT_RD 关闭读
            SHUT_WR 关闭写
            SHUT_RDWR 关闭读写
		
            返回值:成功返回0
            	失败返回-1,并且errno被设置

eg:我们搭建的服务器,只获取客户端的信息,而不用给客户端发送信息

则可以关闭链接套接字的写功能

shutdown(connfd,SHUT_WR); //connfd 就变成了只读

结合已有函数和示例代码,查看流程图

尝试搭建一个TCP服务器

create_tcpserver 创建TCP服务器

1 创建socket套接字 网络通信接口

2 bind 绑定网络应用地址(便于其他应用找到本程序的通信接口)

3 listen 设置监听(内核监听是否有客户端向服务器发起连接请求)

mian

1 创建服务器 create_tcpserver

2 等待客户端的连接请求,并于客户端建立连接 accept的返回值connfd就是一个用来与客户端通信的描述符

(链接套接字描述符)

3 根据需求,编写与客户端的通信

案例:实现Ubuntu与开发板互相通信

点此跳转查看案例源码

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

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

相关文章

#循循渐进学51单片机#实例练习与经验累积#not.9

1、掌握不同类型变量转换的规则与字节操作进行位修改的技巧。 unsigned char a;unsigned int b;unsigned int c; 1)自动类型转换 2&#xff09;强制类型转换C &#xff08;unsigned long&#xff09;a*bl; C (unsigned long)(a*b); 3&#xff09;不同类型变量的赋值b a …

BabelEdit 5.0.1 Crack

BabelEdit加强软件本地化。BabelEdit 是处理 json、yaml、php、arb、vue、properties、resx 或 xliff 翻译文件的可靠解决方案。 旨在使开发过程更加简化和高效。 下载BabelEdit 5.0.0 对于Windows 也适用于macOS 和 Linux BabelEdit - 适用于 Web 和应用程序的翻译编辑器 (…

ps智能填充功能平替:alpaca的安装和使用

为了解决ps beta 智能填充无法使用的问题&#xff0c;需要用alpaca来平替&#xff0c;下面是安装教程&#xff1a; 安装方法&#xff1a; 1、下载插件。 alpaca插件汉化-夸克网盘https://pan.quark.cn/s/1168b447a44e#/list/share 2、 根据使用的PS版本&#xff0c;选择对应文件…

如何从外网远程控制企业内网电脑?

在企业中&#xff0c;保护公司机密和数据安全是至关重要的。为了确保员工在使用公司电脑时遵守相关规定&#xff0c;许多公司会采取外网监控员工电脑的方法。本文将介绍一些真实有效的方法和具体的操作步骤&#xff0c;以帮助您更好地监控员工电脑。 一、什么是外网监控&#x…

【Redis】Redis 的学习教程(十一)之使用 Redis 实现分布式锁

1. 分布式锁概念 在多线程环境下&#xff0c;为了保证数据的线程安全&#xff0c;锁保证同一时刻&#xff0c;只有一个可以访问和更新共享数据。在单机系统我们可以使用 synchronized 锁、Lock 锁保证线程安全。 synchronized 锁是 Java 提供的一种内置锁&#xff0c;在单个 …

北工大汇编——综合题(1)

题目要求 统计字符数。从键盘输入一行字符&#xff0c;统计字母、空格、数字、其他宇符的个数&#xff0c;并显示。要求&#xff1a;提示输入一行宇符串&#xff1b;键盘输入宇符串&#xff0c;Enter 键结束输入&#xff0c;并换行显示结果。 题目代码 DATAS SEGMENT;此处输…

Node.js 调用 fluent-ffmpeg

最近开发H5资源在线裁剪&#xff0c;最终在资源合成的步骤&#xff0c;选择 ffmpeg 作为合成的插件&#xff0c;记录下使用方式。 一、介绍 ffmpeg 一款跨平台多媒体处理工具&#xff0c;可以进行视频转码、裁剪、合成、音视频提取、推流等操作。 二、安装 Node js 可以利用…

qt+ffmpeg视频播放器实现音视频倍速功能

目录 一、前言 二、开发环境参考源码 开发环境&#xff1a; 参考源码&#xff1a; 三、添加倍速控件 四、倍速调节代码 五、视频倍速调节 六、音频倍速方案一 七、音频倍速方案二 八、最终效果 九、参考文献 十、结语 一、前言 参考了云天之巅的FFMPEG Qt视频播放器…

Tomcat常见报错以及手动实现Tomcat

一.Tomcat的简单启动 1.安装Tomcat 2.Tomcat启动 1. 双击 bin 目录下的 startup.bat 文件 2. 输入 http://localhost:8080/&#xff0c;显示如下界面代表安装成功, 默认在 8080 端口 3. 注意&#xff0c;不要关闭黑窗口&#xff0c;关闭了&#xff0c;tomcat 服务就停止了…

LabVIEW开发基于物联网的多功能功率分析仪

LabVIEW开发基于物联网的多功能功率分析仪 根据技术规则&#xff0c;电气元件网络中的单个被创建为在标称正弦波振动制造频率下运行。失真顺序的电流和电压波与正弦波不同&#xff0c;它们或多或少地扭曲成形状。它是由交流网络中非线性组件的存在引起的&#xff0c;例如静态转…

R语言进行孟德尔随机化+meta分析(1)---meta分析基础

目前不少文章用到了孟德尔随机化meta分析&#xff0c;今天咱们也来介绍一下&#xff0c;孟德尔随机化meta其实主要就是meta分析的过程&#xff0c;提取了孟德尔随机化文章的结果&#xff0c;实质上就是个meta分析&#xff0c;不过多个孟德尔随机化随机化的结果合并更加加强了结…

月木学途开发 4.公告模块

概述 效果图 数据库设计 DROP TABLE IF EXISTS announcement; CREATE TABLE announcement (announcementId int(11) NOT NULL AUTO_INCREMENT,announcementTitle varchar(255) DEFAULT NULL,announcementTime varchar(255) DEFAULT NULL,announcementContent longtext,PRIMAR…

计算机组成原理——基础入门总结(二)

上一期的路径&#xff1a;基础入门总结&#xff08;一&#xff09; 目录 一.输入输出系统和IO控制方式 二.存储系统的基本概念 三.cache的基本概念和原理 四.CPU的功能和基本结构 五.总线概述 一.输入输出系统和IO控制方式 IO设备又可以被统一称为外部设备~ IO接口&…

Jetpack:在数据变化时如何优雅更新Views数据

本文讲的是关于Jetpack的架构组件LiveData&#xff0c;LiveData是Lifecycle-aware 组件的一个应用&#xff0c;这意味着LiveData遵守Activity、Fragment和Service等组件的生命周期&#xff0c;在它们生命周期处于活跃状态&#xff08;CREATED和RESUMED&#xff09;才进行更新Vi…

《计算机视觉中的多视图几何》笔记(8)

8 More Single View Geometry 本章主要讲述除了点以外的几何体&#xff0c;在投影变换下的性质。这些几何体包括&#xff1a;平面&#xff0c;线&#xff0c;圆锥曲线&#xff0c;二次曲线。 讲到这里就明白了&#xff0c;为什么投影几何这么重要&#xff0c;因为摄像机就是一…

VLANIF配置

目录 实验原理&#xff1a; 案例&#xff1a; 设备配置 用ping验证不同vlan之间实现相互通信 实验原理&#xff1a; VLANIF接口是一种第三层的逻辑接口&#xff0c;用于在第三层实现不同VLAN 之间的通信。 每个VALN有一个VLANIF接口&#xff0c;并通过该接口在网络层转发…

【操作系统笔记】缓存一致性

CPU 核心之间数据如何传播 高速缓存中的值被修改了&#xff0c;那么怎么同步到内存中呢&#xff1f; ① 写直达&#xff08;Write-Through&#xff09;② 写回&#xff08;Write-Back&#xff09; 写直达&#xff08;Write-Through&#xff09; 简单&#xff0c;但是很慢&am…

《Kubernetes部署篇:Ubuntu20.04基于containerd二进制部署K8S 1.25.14集群(多主多从)》

一、架构图 如下图所示&#xff1a; 二、部署说明 2.1、部署流程 1、系统环境初始化&#xff0c;主要包括 主机名设置、主机hosts解析、关闭防火墙、关闭swap分区、修改系统参数、时间时区同步、修改内核参数、启用ipvs模式。 2、使用一键生成K8S集群证书工具创建证书文件。…

vue页面嵌入飞书网页组件,用于在类似ERP,OA等系统中展示在线文档

先展示最终效果(就是在vue页面中,内嵌了一块ifream页面): 1. 注册进入飞书开放平台,地址为: 飞书开放平台 2.进入开放平台后,选择--创建企业自建应用--创建网页应用,然后在主页面记住该应用的appId和appSecret参数,后面要用 3.然后注意一点的是,因为后面的授权等逻辑我们一般…

Android设计支持库

本文所有的代码均存于 https://github.com/MADMAX110/BitsandPizzas 设计支持库&#xff08;Design Support Library&#xff09;是 Google 在 2015 年的 I/O 大会上发布的全新 Material Design 支持库&#xff0c;在这个 support 库里面主要包含了 8 个新的 Material Design …