嵌入式-----网络编程

计算机网络基础理论

分层结构:
            微信app-->OS-->驱动-->网卡-->  网络   -->网卡-->驱动-->os->微信

        现今有两种主流的分层方式:
                OSI模型:         7层   理论丰满,复杂,但是没人使用 。
                TCP/IP模型:    4层  简单,实用,普遍在使用。
        


        TCP/IP模型:
            应用层       application
                我们自己写的网络应用程序 比如说:邮件 浏览器 淘宝 微信 .....
    
            传输层        TCP: transport control 层
                负责传输的安全性的问题.        数据包:丢失 破坏  乱序
                    如何保证安全问题.后面讲.
                    
                    端口号:   16bit,short类型.      0--65535    0-----1023端口号,有一些知名的大厂才能用   1024------5000,预留给大厂;5001----65535我们自己用
                                                                                            
                        用于区分同一台设备的内部 app.  每个程序都有一个端口号 port
                            平时有默认的.
                    
                    TCP:    
                             面向连接的,  字节流的,安全可靠协议,资源占用大,采用一对一通信,常用于文本,文件,重要信息。

常用tcp的编写流程以及代码案列

下面是一个常用tcp的编写流程以及代码案列:

tcp编程实现服务器与客户端单线接受流程图如下:
             

创建服务器过程如下(server) 


#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>



int main(int argc , char **argv)
{
	if(argc != 3)
	{
		printf("请输入一个端口号,和一个IP地址\n");
		return -1;
	}
	
	if(atoi(argv[1]) > 65535)
	{
		printf("请输入一个5001----65535之间的端口号\n");
		return -1;
	}
	//创建套接字
	int sock_fd = socket(AF_INET,SOCK_STREAM,0); // 创建一个套接字,使用IPv4地址族、流式套接字
	if(-1 == sock_fd)
	{
		perror("创建套接字失败");
		return -1;
	}
	//绑定IP地址+端口号,结构体
	struct sockaddr_in seraddr;
	
	seraddr.sin_family = AF_INET; // 地址族
	seraddr.sin_port = htons(atoi(argv[1])); // 将端口号由字符串转换为网络字节序(大字节序)
	seraddr.sin_addr.s_addr = inet_addr(argv[2]); // 将d点分十进制的IP地址转换为无符号的32位网络字节序
	
	socklen_t addrlen = sizeof(seraddr);
	
	int ret = bind(sock_fd, (struct sockaddr *)&seraddr, addrlen); // 将套接字绑定到指定的IP地址和端口号

	
	//设置监听
	listen(sock_fd, 4); // 设置套接字为监听状态,最大连接数为4
	
	printf("等待连接....\n");
	//等待客户端发起连接
	int con_fd = accept(sock_fd, NULL, NULL); // 阻塞等待客户端发起连接请求,返回一个新的套接字描述符用于与客户端进行通信
	if(-1 == con_fd)
	{
		perror("accept失败\n");
		return -1;
	}
	printf("连接成功!!!!\n");
	
	
	char buf[128]; 
	while(1)
	{
		memset(buf,0,128);
		
		recv(con_fd, buf, 128, 0); // 接收来自客户端的数据
		
		printf("[来自客户端]%s\n",buf);
		
		if(strcmp(buf,"quit\n") == 0)
		{
			break;
		}
		
	}
	
	close(sock_fd); // 关闭套接字
	close(con_fd); // 关闭与客户端的套接字连接
	
	return 0;
}

创建客户端cilent

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>


int main(int argc , char **argv)
{
	
	//创建套接字
	int sock_fd = socket(AF_INET,SOCK_STREAM,0);
	if(-1 == sock_fd)
	{
		perror("creat socket failed");
		return -1;
	}
	//绑定IP地址+端口号,结构体
	struct sockaddr_in seraddr;
	
	seraddr.sin_family = AF_INET;//地址族
	seraddr.sin_port = htons(atoi(argv[1]));//字符串->网络序
	seraddr.sin_addr.s_addr = inet_addr(argv[2]);//点分式IP地址需要转换成无符号的32位网络地址
	
	socklen_t addrlen = sizeof(seraddr);
	
	int ret = bind(sock_fd, (struct sockaddr *)&seraddr, addrlen);
	
	//发起连接
	int con_ret = connect(sock_fd, (struct sockaddr *)&seraddr,addrlen);
	if(-1 == con_ret)
	{
		perror("connect failed");
		return -1;
	}

	
	char buf[128];//buf[0]
	while(1)
	{
		memset(buf,0,128);
		
		fgets(buf,sizeof(buf),stdin);
		
		send(sock_fd, buf, strlen(buf), 0);//发送消息
		
		
		if(strcmp(buf,"quit\n") == 0)
		{
			break;
		}
		
	}
	
	close(sock_fd);
	//close(con_fd);
	
}

关于上述代码所用的函数解析以及声明

1. 创建套接字:

接口声明:int socket(int domain, int type, int protocol);

参数:

domain:域。

AF_INET/PF_INET: 网际协议

AF_UNIX/PF_UNIX:本地协议,可写成 AF_LOCAL/PF_LOCAL

type:类型。

SOCK_STREAM:流式套接字     TCP

SOCK_DGRAM:数据包套接字    UDP

protocol:协议。

一般为 0

返回值:

成功:待连接套接字

失败:-1

备注:在网际协议中,选择流式套接字就代表 TCP 协议,选择数据包套接字就代表 UDP 协议,

第三个参数 protocol 一般都不用。

2、绑定套接字与网络地址

接口声明:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数:

sockfd:待连接套接字

addr:包含本地地址(IP+PORT)的通用地址结构体的指针

addrlen:地址结构体大小

返回值:

成功:0

失败:-1

备注:

通用地址结构体的定义:

struct sockaddr

{

sa_family_t sa_family;

char sa_data[14];};

特殊地址结构体 —— IPv4 地址结构体:

struct sockaddr_in

{

u_short   sin_family; // 地址族

u_short   sin_port; // 端口,0-----1023, 1024-----5000,5000------65535

struct in_addr  sin_addr; // IPV4 地址

char sin_zero[8];

};

struct in_addr

{

in_addr_t s_addr; // 无符号 32 位网络地址sockaddr. sin_addr. s_addr = htons(192.168.124.195)

};

特殊地址结构体 —— IPv6 地址结构体:

struct sockaddr_in6

{

u_short sin6_family; // 地址族

__be16 sin6_port; // 端口

__be32 sin6_flowinfo; // 流信息

struct in6_addr sin6_addr; // IPv6 地址

__u32 sin6_scope_id;

};

特殊地址结构体 ——UNIX 域地址结构体:

struct sockaddr_un

{

u_short sun_family; // 地址族

char sun_path[108]; // 套接字文件路径

};

======================================================

1. 将待连接套接字设置为监听套接字,并设置最大同时接收连接请求个数

接口声明:int listen(int sockfd, int backlog);

参数:

sockfd:待连接套接字

backlog:最大同时接收连接请求个数

返回值:成功:0,并将 sockfd 设置为监听套接字

失败:-1

备注:

由于历史原因,各种系统对 backlog 的理解并不一致,以 LINUX 为例,监听端能同时接收的

最大连接请求个数为 0+4

4、等待对端连接请求

接口声明:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数:

sockfd:监听套接字

addr:通用地址结构体,用以存储对端地址(IP+PORT)

addrlen:参数 addr 的存储区域大小

返回值:

成功:已连接套接字(非负整数)

失败:-1

======================================================

5、连接对端监听套接字

接口声明:int connect(int sockfd, const struct sockaddr *addr, socklen_t

addrlen);

参数:

sockfd:待连接套接字

addr:包含对端地址(IP+PORT)的通用地址结构体的指针

addrlen:地址结构体大小

返回值:

成功:0

失败:-1

======================================================

1. 断开本端连接套接字

接口声明:int close(int fd);参数:

fd:已连接套接字

返回值:

成功:0

失败:-1

备注:

同时断开读端和写端

======================================================

1. 断开本端连接套接字

接口声明:int shutdown(int sockfd, int how);

参数:

sockfd:已连接套接字

how:断开方式。

SHUT_RD:关闭读端

SHUT_WR:关闭写端

SHUT_RDWR:同时关闭读写端

返回值:

成功:0

失败:-1

备注:

在只关闭一端的时候,另一端可以继续使用。

======================================================

7.1、将文本地址转化为二进制地址

Char *src=”192.168.124.115”

接口声明:int inet_pton(int af, const char *src, void *dst);

参数:

af:地址族。

AF_INET:IPv4 地址

AF_INET6:IPv6 地址

src:指向“点分式”IPv4 或 IPv6 地址的指针,例如“192.168.1.100”

dst:类型为 struct in_addr *或者 struct in6_addr *的指针返回值:

成功:1

失败:0 代表地址与地址族不匹配,-1 代表地址不合法

7.2、将二进制地址转化为文本地址

接口声明:const char *inet_ntop(int af, const void *src, char *dst, socklen_t

size);

参数:

af:地址族。

AF_INET:IPv4 地址

AF_INET6:IPv6 地址

src:类型为 struct in_addr *或者 struct in6_addr *的指针

dst:地址缓冲区指针,缓冲区至少

size:地址缓冲区大小,至少要 INET_ADDRSTRLEN 或者 INET6_ADDRSTRLEN 个字节

返回值:

成功:dst

失败:NULL

======================================================

8.1、向 TCP 套接字发送数据

接口声明:ssize_t send(int sockfd, const void *buf, size_t len, int flags);

参数:

sockfd:已连接套接字

buf:即将被发送的数据

len:数据长度

flags:发送标志。

MSG_NOSIGNAL:当对端已关闭时,不产生 SIGPIPE 信号

MSG_OOB:发送紧急(带外)数据,只针对 TCP 连接

返回值:

成功:已发送字节数

失败:-1

备注:

当 flags 为 0 时,send 与 write 作用相同。

从 TCP 套接字接收数据

接口声明: ssize_t recv(int sockfd, void *buf, size_t len, int flags);

参数:

sockfd:已连接套接字

buf:存储数据缓冲区

len:缓冲区大小

flags:接收标志

MSG_OOB:接收紧急(带外)数据

返回值:

成功:已接收字节数

失败:-1

备注:

当 flags 为 0 时,recv 与 read 作用相同。阻塞等待

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
嵌入式系统-从SoC芯片到系统是一本介绍嵌入式系统设计的书籍。嵌入式系统是指集成了计算机处理器、内存、输入输出接口以及其他外设的微型计算机系统,用于在特定的应用领域中完成特定任务。而SoC芯片则是一种集成了多个功能模块的单片集成电路,包含了处理器核心、内存控制器、外设接口以及其他系统组件。 这本书从SoC芯片开始,首先介绍了SoC的基本概念和功能组成。然后详细解释了SoC芯片的架构设计和硬件设计流程,包括处理器选择、内存和外设的设计原则,以及集成电路的物理设计等。此外,还介绍了SoC芯片的性能评估和调试方法,帮助读者理解如何针对具体应用需求对SoC芯片进行调整和优化。 接下来,书籍重点讲解了嵌入式系统的软件设计和开发。从操作系统的选择与配置开始,包括嵌入式Linux、RTOS等不同的选择。然后介绍了嵌入式软件开发工具和编程语言,包括C、C++以及汇编语言等。同时,还讲解了嵌入式系统的驱动程序开发和应用程序设计等方面的知识。 最后,该书还对嵌入式系统的测试和验证、面向网络连接的嵌入式系统以及面向嵌入式系统安全等相关主题进行了介绍。为读者提供了全面而深入的内容,让其了解从SoC芯片到嵌入式系统的设计和开发过程。 总之,嵌入式系统-从SoC芯片到系统是一本全面介绍嵌入式系统设计的书籍,内容涵盖了硬件和软件两个方面。对于学习和了解嵌入式系统的人员来说,是一本相当实用的参考书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值