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

    文章

    8130

    浏览量

    93089
  • 编程
    +关注

    关注

    90

    文章

    3707

    浏览量

    96765
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux驱动开发的必备知识

    内核基础知识: 1、熟悉 Linux 内核的架构、模块系统、进程管理、内存管理等。 了解内核的编译和加载过程。 2、C编程技能: 精通 C 语言编程,包括指针操作、内存管理、结构体等
    发表于 12-04 07:58

    【「高速数字设计(基础篇)」阅读体验】第六章 去耦电容的容量需求分析

    去耦电容容量别瞎猜!《高速数字设计》第6教你量化计算,精准选型 在高速数字电路设计中,去耦电容选多大容量是个难点。《高速数字设计》第6“去耦电容的容量需求分析:知己知彼”,把这个问题进行了量化
    发表于 11-19 20:48

    【免费送书】成为硬核Linux开发者:《Linux 设备驱动开发(第 2 版)》

    Linux系统的设备驱动开发,一直给人门槛较高的印象,主要因内核机制抽象、需深度理解硬件原理、开发调试难度大所致。2021年,一本讲解驱动开发的专著问世即获市场青睐,畅销近万册——这便
    的头像 发表于 11-18 08:06 433次阅读
    【免费送书】成为硬核<b class='flag-5'>Linux</b><b class='flag-5'>开发</b>者:《<b class='flag-5'>Linux</b> 设备驱动<b class='flag-5'>开发</b>(第 2 版)》

    【「高速数字设计(基础篇)」阅读体验】+第6阅读体验

    第六章去耦电容容量分析中,作者首先以类比方式给出容易理解的图片: 但是其容值不易测量,于是需要间接计算;CMOS电路本身的功耗与输入信号的脉冲频率密切相关,其动态功耗会随着频率的增加而显著上升
    发表于 11-06 16:33

    第六届1024资管科技开发者大会(ITDC 2025)丨活动预告

    第六届1024资管科技开发者大会(ITDC 2025)丨活动预告
    的头像 发表于 10-15 18:39 286次阅读
    <b class='flag-5'>第六</b>届1024资管科技<b class='flag-5'>开发</b>者大会(ITDC 2025)丨活动预告

    RK3506开发Linux开发板极致性价比之选

    RK3506开发Linux开发板极致性价比之选瑞芯微RK3506开发板,3核Cortex-A7@1.5GHz+Cortex-M0,Linux
    的头像 发表于 09-11 16:26 2782次阅读
    RK3506<b class='flag-5'>开发</b>板<b class='flag-5'>Linux</b><b class='flag-5'>开发</b>板极致性价比之选

    Linux 应用开发手册

    T507linux应用开发手册
    发表于 08-22 17:01 10次下载

    第六章 W55MH32 UDP Multicast示例

    本文介绍了在W55MH32芯片上实现UDP组播的原理、应用场景及回环测试方法,并通过实战代码展示了其具体实现过程。下一篇文章将聚焦DNS例程,讲解其工作原理及实现方法,帮助大家更深入地理解网络通信。敬请期待!
    的头像 发表于 07-24 09:19 650次阅读
    <b class='flag-5'>第六章</b> W55MH32 UDP Multicast示例

    【「DeepSeek 核心技术揭秘」阅读体验】--全书概览

    DeepSeek对人工智能技术格局的一个影响 第六章 DeepSeek开源技术剖析 第七 大模型发展未来展望 全书图文并茂,对专业技术属于进行了讲解,也有对流程、框架、参数的展示,结合案例与应用方面的代入,是非常好的对DeepSeek较深入了解的书籍,后面与大家多多分享
    发表于 07-21 00:04

    电源设计中功率因数校正讲解

    应用的四种不同实现方法中得到的结果的详细分析。提供了按给定准则对各拓扑结构进行比较分析和排名。还包括根据以上章节描述的结果给设计师提供的指南。 第六章为以上章节中提出的拓扑提供了为满足 FCC 关于
    发表于 06-25 15:58

    飞凌嵌入式ElfBoard ELF 1板卡-uboot移植之IOMUX介绍

    此文件夹,就自行创建),并解压缩,准备进行移植。本章uboot移植工作基于eMMC版进行。 经过第六章,我们完整地移植了NXP的内核,相信大家对IOMUX已经很熟悉了,我们再简单地提一下,如果您
    发表于 05-30 09:28

    第六章 外部中断

    本章介绍W55MH32的IO口作为外部中断输入的使用。先阐述了NVIC(嵌套向量中断控制器) 的结构、寄存器、优先级及相关函数,再说明EXTI(外部中断和事件控制器)的功能。框图及IO口与中断线的映射。
    的头像 发表于 05-26 16:27 1003次阅读
    <b class='flag-5'>第六章</b> 外部中断

    第六章 GPIO输入——按键检测

    本篇文章讲述了如何在W55MH32上实现按键输入检测,以及按键输入检测的注意事项、实现方式和代码讲解等。掌握了按键检测方式之后,我们就可以用按键控制我们想要实现的其他功能啦。
    的头像 发表于 05-22 16:41 752次阅读
    <b class='flag-5'>第六章</b> GPIO输入——按键检测

    [迅为]Linux开发小技巧:Remote - SSH插件

    [迅为]Linux开发小技巧:Remote - SSH插件
    的头像 发表于 04-01 15:46 943次阅读
    [迅为]<b class='flag-5'>Linux</b><b class='flag-5'>开发</b>小技巧:Remote - SSH插件

    从零开始驯服Linux(一):ZYNQ-Linux启动文件构建全解析

    hello.c就可以了。 创建Petalinux工程创建Petalinux工程的步骤在《领航者ZYNQ之嵌入式Linux开发指南》第六章Petalinux设计流程实战中已讲解,本章就不细述,也可直接
    发表于 03-20 16:48