0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux应用开发【第六章】网络编程应用开发

weidongshan 来源:weidongshan 作者:weidongshan 2021-12-10 19:17 次阅读

文章目录

6 网络编程应用开发

6.1 网络编程简介

6.1.1 五层因特网协议栈

6.1.2 传输层和应用层的常见协议

6.2 网络编程之TCP/UDP比较

6.2.1 TCP和UDP 原理上的区别

6.2.2 为何存在UDP协议

6.2.3 TCP/UDP网络通信大概交互图

6.3 网络编程主要函数介绍

6.3.1 socket函数

6.3.2 bind函数

6.3.3 listen函数

6.3.4 accept函数

6.3.5 connect函数

6.3.6 send函数

6.3.7 recv函数

6.3.8 recvfrom函数

6.3.9 sendto函数

6.4 TCP编程简单示例

6.4.1 服务器端代码

6.4.2 客户端代码

6.4.3 Makefile文件

6.4.4 执行

6.5 UDP编程简单示例

6.5.1 服务器端代码

6.5.2 客户端代码

6.5.2.1 客户端程序1

6.5.2.2 客户端程序2

6.5.3 Makefile文件

6.5.4 执行

6 网络编程应用开发

6.1 网络编程简介

要编写通过计算机网络通信的程序,首先要确定这些程序同通信的协议(protocol),在设计一个协议的细节之前,首先要分清程序是由哪个程序发起以及响应何时产生。

举例来说,一般认为WEB服务器程序是一个长时间运行的程序(守护进程deamon),它只在响应来自网络的请求时才发送网络消息。协议的另一端是web客户程序,如某种浏览器,与服务器进程的通信总是由客户进程发起。大多数网络应用就是按照划分为客户(clinet)和服务器(server)来组织的。

6.1.1 五层因特网协议栈

为了给网络协议的设计提供一个结构,网络设计者以分层(layer)的方式组织协议以及实现这些协议的网络硬件和软件。

分层提供了一种结构化方式来讨论系统组件。模块化使更新系统组件更为容易。

协议栈是各层所有协议的总和。

poYBAGGzNzWAdICbAAATy_4rwtM378.png

五层因特网协议栈

应用层:应用层是网络应用程序及它们的应用层协议存留的地方。

运输层:因特网的运输层在应用程序端点之间传从应用层报文。

网络层:因特网呃网络层负责将称为数据包(datagram)的网络层分组从一台主机移动到另一台主机。

链路层:因特网的网络层通过源和目的地之间的一系列路由器路由数据报。

物理层:虽然链路层的任务是将整个帧从一个网络元素移动到临近的网络元素,而物理层的任务是将该帧的一个一个比特从一个节点移动到下一个节点。

6.1.2 传输层和应用层的常见协议

我们重点介绍和应用层编程关系密切的应用层和运输层。

应用层:

因特网的应用层包含很多协议,例如HTTP,SMTP,和 FTP。我们看到的某些网络功能,比如将www.baidu.com这样对人友好的端系统名字转换为32比特网络地址,也是借助于特定的应用层协议即域名系统(DNS)完成的。

应用层的协议分布在多个端系统上,一个端系统中的应用程序使用协议与另一个端系统中的应用程序交换信息分组。

运输层:

在英特网中有两个运输协议,即TCP和UDP,利用其中的任何一个都能运输应用层报文。我们写应用程序的时候具体选择哪个运输层协议应该根据实际情况来确定(后面会具体讲解)。

6.2 网络编程之TCP/UDP比较

6.2.1 TCP和UDP 原理上的区别

TCP向它的应用程序提供了面向连接的服务。这种服务包括了应用层报文向目的地的确保传递和流量控制(即发送方/接收方速率匹配)。这种服务包括了应用层报文划分为短报文,并提供拥塞控制机制,因此当网络拥塞时源抑制其传输速率。

UDP协议向它的应用程序提供无连接服务。这是一种不提供不必要服务的服务,没有可靠性,没有流量控制,也没有拥塞控制。

6.2.2 为何存在UDP协议

既然TCP提供了可靠数据传输服务,而UDP不能提供,那么TCP是否总是首选呢?答案是否定的,因为有许多应用更适合用UDP,原因有以下几点:

a. 关于何时发送什么数据控制的更为精细。

采用UDP时只要应用进程将数据传递给UDP,UDP就会立即将其传递给网络层。而TCP有重传机制,而不管可靠交付需要多长时间。但是实时应用通常不希望过分的延迟报文段的传送,且能容忍一部分数据丢失。

b. 无需建立连接,不会引入建立连接时的延迟。

c. 无连接状态,能支持更多的活跃客户。

d. 分组首部开销较小。

6.2.3 TCP/UDP网络通信大概交互图

下面我们分别画出运用TCP协议和运用UDP协议的客户端和服务器大概交互图。

pYYBAGGzNzuAa_SNAABSurUuxzU563.png

面向连接的TCP流模式

poYBAGGzN0GAaiaoAAAz9Vs51Gs694.png

UDP用户数据包模式

6.3 网络编程主要函数介绍

6.3.1 socket函数

int socket(int domain, int type,int protocol);

此函数用于创建一个套接字。

domain是网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等)。

AF_UNIX只能够用于单一的Unix 系统进程间通信,而AF_INET是针对Internet的,因而可以允许远程通信使用。

type是网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等)。

SOCK_STREAM表明用的是TCP 协议,这样会提供按顺序的,可靠,双向,面向连接的比特流。

SOCK_DGRAM 表明用的是UDP协议,这样只会提不可靠,无连接的通信。

关于protocol,由于指定了type,所以这个地方一般只要用0来代替就可以了。

此函数执行成功时返回文件描述符,失败时返回-1,看errno可知道出错的详细情况。

6.3.2 bind函数

int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

从函数用于将地址绑定到一个套接字。

sockfd是由socket函数调用返回的文件描述符。

my_addr是一个指向sockaddr的指针。

addrlen是sockaddr结构的长度。

sockaddr的定义:

struct sockaddr{ unisgned short as_family; char sa_data[14]; };

不过由于系统的兼容性,我们一般使用另外一个结构(struct sockaddr_in) 来代替。

sockaddr_in的定义:

struct sockaddr_in{ unsigned short sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }

如果使用Internet所以sin_family一般为AF_INET。

sin_addr设置为INADDR_ANY表示可以和任何的主机通信。

sin_port是要监听的端口号。

bind将本地的端口同socket返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket一样。

6.3.3 listen函数

int listen(int sockfd,int backlog);

此函数宣告服务器可以接受连接请求。

sockfd是bind后的文件描述符。

backlog设置请求排队的最大长度。当有多个客户端程序和服务端相连时,使用这个表示可以介绍的排队长度。

listen函数将bind的文件描述符变为监听套接字,返回的情况和bind一样。

6.3.4 accept函数

int accept(int sockfd, struct sockaddr *addr,int *addrlen);

服务器使用此函数获得连接请求,并且建立连接。

sockfd是listen后的文件描述符。

addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了, bind,listen和accept是服务器端用的函数。

accept调用时,服务器端的程序会一直阻塞到有一个客户程序发出了连接。 accept成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了,失败时返回-1 。

6.3.5 connect函数

int connect(int sockfd, struct sockaddr * serv_addr,int addrlen);

可以用connect建立一个连接,在connect中所指定的地址是想与之通信的服务器的地址。

sockfd是socket函数返回的文件描述符。

serv_addr储存了服务器端的连接信息,其中sin_add是服务端的地址。

addrlen是serv_addr的长度

connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符,失败时返回-1。

6.3.6 send函数

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

sockfd指定发送端套接字描述符;

buf指明一个存放应用程序要发送数据的缓冲区;

len指明实际要发送的数据的字节数;

flags一般置0。

客户或者服务器应用程序都用send函数来向TCP连接的另一端发送数据

6.3.7 recv函数

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

sockfd指定接收端套接字描述符;

buf指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;

len指明buf的长度;

flags一般置0。

客户或者服务器应用程序都用recv函数从TCP连接的另一端接收数据。

6.3.8 recvfrom函数

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

recvfrom通常用于无连接套接字,因为此函数可以获得发送者的地址。

src_addr是一个struct sockaddr类型的变量,该变量保存源机的IP地址及端口号。

addrlen常置为sizeof (struct sockaddr)。

6.3.9 sendto函数

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

sendto和send相似,区别在于sendto允许在无连接的套接字上指定一个目标地址。

dest_addr表示目地机的IP地址和端口号信息,

addrlen常常被赋值为sizeof (struct sockaddr)。

sendto函数也返回实际发送的数据字节长度或在出现发送错误时返回-1。

6.4 TCP编程简单示例

服务器首先进行初始化操作:调用函数socket创建一个套接字,函数bind将这个套接字与服务器的公认地址绑定在一起,函数listen将这个套接字换成倾听套接字,然后调用函数accept来等待客户机的请求。过了一段时间后,客户机启动,调用socket创建一个套接字,然后调用函数connect来与服务器建立连接。连接建立之后,客户机和服务器通过读、写套接字来进行通信。

6.4.1 服务器端代码

参考:TCP/server_line.c

1#include 2#include 3#include 4#include 5#include 6#include 7#include 8#include 9#include 10 11#define SERVER_PORT 8180 12#define C_QUEUE 10 13 14/************************************************************ 15*函数功能描述:从8180端口接收客户端数据 16*输入参数:无 17*输出参数:打印客户IP以及发来的信息 18*返回值:无 19*修改日期 版本号 修改人 修改内容 20*2020/05/13 v1.0.0 zonghzha reat 21*************************************************************/ 22 23int main(int argc, char **argv) 24{ 25 char buf[512]; 26 int len; 27 int duty_socket; 28 int customer_socket; 29 struct sockaddr_in socket_server_addr; 30 struct sockaddr_in socket_client_addr; 31 int ret; 32 int addr_len; 33 34 signal(SIGCHLD, SIG_IGN); 35 36 /* 服务器端开始建立socket描述符 */ 37 duty_socket = socket(AF_INET, SOCK_STREAM, 0); 38 if (duty_socket == -1) 39 { 40 printf("socket error"); 41 return -1; 42 } 43 44 /* 服务器端填充 sockaddr_in结构 */ 45 socket_server_addr.sin_family = AF_INET; 46 /* 端口号转换为网络字节序 */ 47 socket_server_addr.sin_port = htons(SERVER_PORT); 48 /* 接收本机所有网口的数据 */ 49 socket_server_addr.sin_addr.s_addr = INADDR_ANY; 50 memset(socket_server_addr.sin_zero, 0, 8); 51 52 /* 捆绑sockfd描述符 */ 53 ret = bind(duty_socket, (const struct sockaddr *)&socket_server_addr, sizeof(struct sockaddr)); 54 if (ret == -1) 55 { 56 printf("bind error!n"); 57 return -1; 58 } 59 ret = listen(duty_socket, C_QUEUE); 60 if (ret == -1) 61 { 62 printf("listen error!n"); 63 return -1; 64 } 65 66 while (1) 67 { 68 addr_len = sizeof(struct sockaddr); 69 /* 服务器阻塞,直到客户程序建立连接 */ 70 customer_socket = accept(duty_socket, (struct sockaddr *)&socket_client_addr, &addr_len); 71 if (customer_socket != -1) 72 { 73 /*inet_ntoa的作用是将一个32位Ipv4地址转换为相应的点分十进制数串*/ 74 printf("Get connect from %sn", inet_ntoa(socket_client_addr.sin_addr)); 75 } 76 if (!fork()) 77 { 78 while (1) 79 { 80 memset(buf, 512, 0); 81 /*接收数据*/ 82 len = recv(customer_socket, buf, sizeof(buf), 0); 83 buf[len] = ''; 84 if (len <= 0) 85 { 86 close(customer_socket); 87 return -1; 88 } 89 else 90 { 91 printf("Get connect from %s, Msg is %sn", inet_ntoa(socket_client_addr.sin_addr), buf); 92 } 93 } 94 } 95 } 96 97 close(duty_socket); 98 return 0; 99}

6.4.2 客户端代码

参考:TCP/client_line.c

1#include 2#include 3#include 4#include 5#include 6#include 7#include 8#include 9 10#define SERVER_PORT 8180 11/************************************************************ 12*函数功能描述:向指定IP的8180端口发送数据 13*输入参数:点分十进制服务器IP 14*输出参数:无 15*返回值:无 16*修改日期 版本号 修改人 修改内容 17*2020/05/13 v1.0.0 zonghzha creat 18*************************************************************/ 19 20int main(int argc, char **argv) 21{ 22 unsigned char buf[512]; 23 int len; 24 struct sockaddr_in socket_server_addr; 25 int ret; 26 int addr_len; 27 int client_socket; 28 29 30 if (argc != 2) 31 { 32 printf("Usage:n"); 33 printf("%s n", argv[0]); 34 return -1; 35 } 36 37 /* 客户程序开始建立 sockfd描述符 */ 38 client_socket = socket(AF_INET, SOCK_STREAM, 0); 39 if (client_socket == -1) 40 { 41 printf("socket error"); 42 return -1; 43 } 44 45 /* 客户程序填充服务端的资料 */ 46 socket_server_addr.sin_family = AF_INET; 47 /*主机字节序转换为网络字节序*/ 48 socket_server_addr.sin_port = htons(SERVER_PORT); 49 if (inet_aton(argv[1], &socket_server_addr.sin_addr) == 0) 50 { 51 printf("invalid server ipn"); 52 return -1; 53 } 54 memset(socket_server_addr.sin_zero, 0, 8); 55 /* 客户程序发起连接请求 */ 56 ret = connect(client_socket, (const struct sockaddr *)&socket_server_addr, sizeof(struct sockaddr)); 57 if (ret == -1) 58 { 59 printf("connect error!n"); 60 return -1; 61 } 62 63 64 while (1) 65 { 66 if (fgets(buf, sizeof(buf), stdin)) 67 { 68 len = send(client_socket, buf, strlen(buf), 0); 69 if (len <= 0) 70 { 71 close(client_socket); 72 return -1; 73 } 74 } 75 } 76 77 close(client_socket); 78 return 0; 79}

6.4.3 Makefile文件

all:server client server:server.c gcc $^ -o $@ client:client.c gcc $^ -o $@ clean: rm server client -f (注意:命令语句的开头要用“Tab”键。)

6.4.4 执行

服务器端:

./server

客户端:

./client 127.0.0.1

客户端输入:

good night

服务器端显示:

Get connect from 127.0.0.1 Get connect from 127.0.0.1, Msg is good night

6.5 UDP编程简单示例

UDP服务器首先进行初始化操作:调用函数socket创建一个数据报类型的套接字,函数bind将这个套接字与服务器的公认地址绑定在一起。然后调用函数recvfrom接收UDP客户机的数据报。UDP客户机首先调用函数socket创建一个数据报套接字,然后调用函数sendto向服务器发送数据报。在结束通信后,客户机调用close关闭UDP套接字,服务器继续使用这个UDP套接字接收其它客户机的数据报。

6.5.1 服务器端代码

参考UDP/server_line.c

1#include 2#include 3#include 4//#include 5#include 6#include 7#include 8#include 9#include 10 11/*服务器端口为8180*/ 12#define SERVER_PORT 8180 13 14/************************************************************ 15*函数功能描述:从8180端口接收客户端数据 16*输入参数:无 17*输出参数:打印客户IP以及发来的信息 18*返回值:无 19*修改日期 版本号 修改人 修改内容 20*2020/05/13 v1.0.0 zonghzha creat 21*************************************************************/ 22 23 24int main(int argc, char **argv) 25{ 26 unsigned char buf[512]; 27 int len; 28 int duty_socket; 29 int customer_socket; 30 struct sockaddr_in socket_server_addr; 31 struct sockaddr_in socket_client_addr; 32 int ret; 33 int addr_len; 34 35 /* 创建数据报套接字 */ 36 duty_socket = socket(AF_INET, SOCK_DGRAM, 0); 37 if (duty_socket == -1) 38 { 39 printf("socket error"); 40 return -1; 41 } 42 43 /* 服务器端填充 sockaddr_in结构 */ 44 socket_server_addr.sin_family = AF_INET; 45 socket_server_addr.sin_port = htons(SERVER_PORT); 46 socket_server_addr.sin_addr.s_addr = INADDR_ANY; 47 memset(socket_server_addr.sin_zero, 0, 8); 48 49 /*绑定套接字*/ 50 ret = bind(duty_socket, (const struct sockaddr *)&socket_server_addr, sizeof(struct sockaddr)); 51 if (ret == -1) 52 { 53 printf("bind error!n"); 54 return -1; 55 } 56 57 58 while (1) 59 { 60 addr_len = sizeof(struct sockaddr); 61 /* 接收客户端数据报,返回的为接收到的字节数 */ 62 len = recvfrom(duty_socket, buf, sizeof(buf), 0, (struct sockaddr *)&socket_client_addr, &addr_len); 63 if (len > 0) 64 { 65 buf[len] = ''; 66 printf("Get Msg from %s : %sn", inet_ntoa(socket_client_addr.sin_addr), buf); 67 } 68 69 } 70 71 close(duty_socket); 72 return 0; 73} 74

6.5.2 客户端代码

6.5.2.1 客户端程序1

参考UDP/client_line_1.c

1#include 2#include 3#include 4#include 5#include 6#include 7#include 8 9#define SERVER_PORT 8180 10 11/************************************************************ 12*函数功能描述:向指定IP的8180端口发送数据 13*输入参数:点分十进制服务器IP 14*输出参数:无 15*返回值:无 16*修改日期 版本号 修改人 修改内容 17*2020/05/13 v1.0.0 zonghzha creat 18*************************************************************/ 19 20int main(int argc, char **argv) 21{ 22 unsigned char buf[512]; 23 int len; 24 struct sockaddr_in socket_server_addr; 25 int ret; 26 int addr_len; 27 int client_socket; 28 29 30 if (argc != 2) 31 { 32 printf("Usage:n"); 33 printf("%s n", argv[0]); 34 return -1; 35 } 36 37 /*创建套接字*/ 38 client_socket = socket(AF_INET, SOCK_DGRAM, 0); 39 if (client_socket == -1) 40 { 41 printf("socket error"); 42 return -1; 43 } 44 45 /* 填充服务端的资料 */ 46 socket_server_addr.sin_family = AF_INET; 47 socket_server_addr.sin_port = htons(SERVER_PORT); 48 if (inet_aton(argv[1], &socket_server_addr.sin_addr) == 0) 49 { 50 printf("invalid server ipn"); 51 return -1; 52 } 53 memset(socket_server_addr.sin_zero, 0, 8); 54 55 56 57 58 while (1) 59 { 60 if (fgets(buf, sizeof(buf), stdin)) 61 { 62 // len = send(client_socket, buf, strlen(buf), 0); 63 /*向服务器端发送数据报*/ 64 addr_len = sizeof(struct sockaddr); 65 len = sendto(client_socket, buf, sizeof(buf), 0, (struct sockaddr *)&socket_server_addr, addr_len); 66 if (len <= 0) 67 { 68 close(client_socket); 69 return -1; 70 } 71 } 72 } 73 74 close(client_socket); 75 return 0; 76} 77

问:用UDP协议写网络通讯程序不可以用connect函数吗?

答:非也。

6.5.2.2 客户端程序2

参考UDP/client_line_2.c

1#include 2#include 3#include 4#include 5#include 6#include 7#include 8 9/*服务器端口为8180*/ 10#define SERVER_PORT 8180 11 12/************************************************************ 13*函数功能描述:向指定IP的8180端口发送数据 14*输入参数:点分十进制服务器IP 15*输出参数:无 16*返回值:无 17*修改日期 版本号 修改人 修改内容 18*2020/05/13 v1.0.0 zonghzha creat 19*************************************************************/ 20 21int main(int argc, char **argv) 22{ 23 unsigned char buf[512]; 24 int len; 25 struct sockaddr_in socket_server_addr; 26 int ret; 27 int addr_len; 28 int client_socket; 29 30 31 if (argc != 2) 32 { 33 printf("Usage:n"); 34 printf("%s n", argv[0]); 35 return -1; 36 } 37 38 /*创建数据报套接字*/ 39 client_socket = socket(AF_INET, SOCK_DGRAM, 0); 40 if (client_socket == -1) 41 { 42 printf("socket error"); 43 return -1; 44 } 45 46 socket_server_addr.sin_family = AF_INET; 47 socket_server_addr.sin_port = htons(SERVER_PORT); 48 if (inet_aton(argv[1], &socket_server_addr.sin_addr) == 0) 49 { 50 printf("invalid server ipn"); 51 return -1; 52 } 53 memset(socket_server_addr.sin_zero, 0, 8); 54 55 ret = connect(client_socket, (const struct sockaddr *)&socket_server_addr, sizeof(struct sockaddr)); 56 if (ret == -1) 57 { 58 printf("connect error!n"); 59 return -1; 60 } 61 62 63 while (1) 64 { 65 if (fgets(buf, sizeof(buf), stdin)) 66 { 67 len = send(client_socket, buf, strlen(buf), 0); 68 if (len <= 0) 69 { 70 close(client_socket); 71 return -1; 72 } 73 } 74 } 75 76 close(client_socket); 77 return 0; 78} 79

在客户端代码2中,connect函数并非真的在协议层建立了连接,它只是指定了服务器的地址和端口号信息。

因为在connect中指定了服务器的地址和端口号信息,所以后面的send就可以直接发送了,而不用再次指定地址和端口号。

6.5.3 Makefile文件

all:server client_1 client_2 server:server.c gcc $^ -o $@ client_1:client_1.c gcc $^ -o $@ client_2:client_2.c gcc $^ -o $@ clean: rm server client_1 client_2 -f (注意:命令语句的开头要用“Tab”键。)

6.5.4 执行

服务器端执行:

./server

客户端执行:

./client_1 127.0.0.1

客户端输入:

good night

服务器端显示:

Get Msg from 127.0.0.1 : good night

审核编辑 黄昊宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 网络
    +关注

    关注

    14

    文章

    7565

    浏览量

    88775
  • 编程
    +关注

    关注

    88

    文章

    3615

    浏览量

    93731
收藏 人收藏

    评论

    相关推荐

    《DNESP32S3使用指南-IDF版_V1.6》第六章 新建基础工程

    第六章 新建基础工程 在前面的章节中,我们已经简要介绍了ESP32-S3的基础知识和ESP-IDF的基本概念,并详细阐述了VS Code IDE环境的搭建以及Espressif插件的安装流程。现在
    发表于 12-02 14:43

    Linux应用编程的基本概念

    Linux应用编程涉及到在Linux环境下开发和运行应用程序的一系列概念。以下是一些涵盖Linux应用
    的头像 发表于 10-24 17:19 229次阅读

    【北京迅为】i.mx8mm嵌入式linux开发指南第四篇 嵌入式Linux系统移植篇第六十九章uboot移植

    【北京迅为】i.mx8mm嵌入式linux开发指南第四篇 嵌入式Linux系统移植篇第六十九章uboot移植
    的头像 发表于 10-22 14:46 620次阅读
    【北京迅为】i.mx8mm嵌入式<b class='flag-5'>linux</b><b class='flag-5'>开发</b>指南第四篇 嵌入式<b class='flag-5'>Linux</b>系统移植篇<b class='flag-5'>第六</b>十九章uboot移植

    《DNK210使用指南 -CanMV版 V1.0》第六章 Kendryte K210固件烧录

    第六章 Kendryte K210固件烧录 本章将为读者介绍Kendryte K210的固件烧录,以及Kendryte K210外部NOR Flash的空间分布。本章分为如下几个小节:6.1 外部
    发表于 09-12 14:20

    【北京迅为】《stm32mp157开发板嵌入式linux开发指南》第五 Ubuntu使用apt-get下载

    【北京迅为】《stm32mp157开发板嵌入式linux开发指南》第五 Ubuntu使用apt-get下载
    的头像 发表于 09-03 16:26 788次阅读
    【北京迅为】《stm32mp157<b class='flag-5'>开发</b>板嵌入式<b class='flag-5'>linux</b><b class='flag-5'>开发</b>指南》第五<b class='flag-5'>章</b> Ubuntu使用apt-get下载

    linux开发板与树莓派的区别

    操作系统的微型计算机,主要用于教育、编程、媒体播放等领域。 硬件配置 Linux开发板:Linux开发板的硬件配置因厂商和型号而异,通常包括
    的头像 发表于 08-30 15:34 964次阅读

    linux开发板和单片机开发的区别

    、PIC等,处理能力和内存容量相对较低。 操作系统 Linux开发板通常使用Linux操作系统,具有丰富的软件资源和开发工具。单片机开发则通
    的头像 发表于 08-30 15:30 777次阅读

    Linux 驱动开发与应用开发,你知道多少?

    一、Linux驱动开发与应用开发的区别开发层次不同:Linux驱动开发主要是针对硬件设备进行
    的头像 发表于 08-30 12:16 789次阅读
    <b class='flag-5'>Linux</b> 驱动<b class='flag-5'>开发</b>与应用<b class='flag-5'>开发</b>,你知道多少?

    SK海力士开发第六代10纳米级DDR5 DRAM

    SK海力士宣布了一项重大技术突破,成功开发出全球首款采用第六代10纳米级(1c)工艺的16Gb DDR5 DRAM。这一里程碑式的成就标志着SK海力士在半导体存储技术领域的领先地位。
    的头像 发表于 08-29 16:39 673次阅读

    【「ARM MCU嵌入式开发 | 基于国产GD32F10x芯片」阅读体验】+书籍整体概况

    ,这里包含系统滴答定时器SysTick,RTC实时时钟,看门狗(独立看门狗与窗口看门狗),定时器(基本定时器、通用定时器、高级定时器),以及PWM实现呼吸灯效果实验。第六章为通用同步/异步串行通信
    发表于 08-25 22:48

    第六章-电机驱动和PWM STM32项目

    万字笔记、12多个小时视频、20多章节代码手把手教会你如何开发和调试。让你更快掌握嵌入式系统开发。** V3.3.0-STM32智能小车 视频: https
    的头像 发表于 08-21 16:46 629次阅读
    <b class='flag-5'>第六章</b>-电机驱动和PWM STM32项目

    双麒麟系统!迅为RK3588开发板+银河麒麟/开放麒麟

    Build root系统功能测试 第四 Ubuntu系统功能测试 第五 Debian系统功能测试 第六章 openkylin系统功能测试 第七 银河麒麟系统功能测试
    发表于 07-15 10:35

    第3_UART 开发基础

    第3_UART 开发基础
    的头像 发表于 06-29 14:27 688次阅读
    第3<b class='flag-5'>章</b>_UART <b class='flag-5'>开发</b>基础

    搭配100教学实验案例,轻松解决老师备课难题!

    Linux系统使用实验第三Linux设备驱动程序开发实验第四基于ARM基础外设实验第五Li
    的头像 发表于 05-01 08:31 409次阅读
    搭配100教学实验案例,轻松解决老师备课难题!

    fpga开发板与linux开发板区别

    (Field-Programmable Gate Array)是一种可编程逻辑器件,它可以通过编程改变硬件逻辑电路的功能和结构。FPGA采用了可编程的门极,可以根据需要重新配置内部电路,从而实现不同的功能和逻辑关系。而
    的头像 发表于 02-01 17:09 2259次阅读