嵌入式学习-网络编程

1.网络编程作用

程序能够通过网络与其他计算机上的程序进行数据交换、通信和协作

2.关键概念

两个对象:服务器(被动响应请求),客户端(主动发起请求)。浏览器看b站视频时,浏览器就是客户端,B站那边就是服务器。

两种传输方式(运输层):TCP,面向连接的(三次握手建立连接),数据传输的单位是用户数据报(有序列号、确认号等控制信息)。UDP,无连接的(不确定服务器是否可以接受数据),数据传输的单位是用户数据报(标头中没有确认号等控制信息),不保证可靠的交互。UDP适用于对数据准确性要求不高的场合(游戏,视频通话),丢失几帧数据不影响使用。

数据传输三要素:源(数据发送方),目的(数据接收方),长度

ip:IP地址是一组数字,用于唯一标识互联网上的每个设备。通过IP地址,网络可以找到你的电脑等设备。

端口:进程与外界数据交互的中间接口。范围0-65535,其中0-1023是系统保留端口(一些特定应用预留端口),1024-65535是动态或私有端口。80端口是http服务,22是ssh服务,https默认端口是443。https://zhuanlan.zhihu.com/p/225777212

socket:一种通用传输层网络接口(实际代码),方便实现TCP、UDP等连接。

僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。僵尸进程还会消耗一定的系统资源。解决方法:具体做法是接管SIGCHLD信号。子进程死后,会发送SIGCHLD信号给父进程,父进程收到此信号后,执行waitpid()函数为子进程收尸。

孤儿进程:父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”此时的子进程叫做孤儿进程。Linux避免系统存在过多的孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程。僵尸进程将会导致资源浪费,而孤儿则不会。

3.实现流程

服务器端

1.创建套接字:socket

2.配置网络传输参数:sockaddr_in结构体

3.将地址绑定到套接字:bind

4.监听服务器端连接请求:listen,所有连接请求是保存到一个队列中

5.接收客户端连接请求:accept

6.接发收数据:send/recv

7.关闭套接字:close

客户端

1.创建套接字:socket

2.请求连接服务器:sonnect

3.接发收数据:send/recv

4.代码示例

服务器端

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


/* socket
 * bind
 * listen
 * accept
 * send/recv
 */

//需要输入参数客户端ip

#define SERVER_PORT 8888//服务器监听端口号
#define BACKLOG     10//

int main(int argc, char **argv)
{
	int iSocketServer;//服务器端描述
	int iSocketClient;//客户端描述
	struct sockaddr_in tSocketServerAddr;//服务器端地址信息结构体
	struct sockaddr_in tSocketClientAddr;//客户端地址信息结构体
	int iRet;
	int iAddrLen;

	int iRecvLen;//服务器接收数据长度
	unsigned char ucRecvBuf[1000];//接收客户端数据

	int iClientNum = -1;

	signal(SIGCHLD,SIG_IGN);//防止子进程成为僵尸进程
	//1.配置socket参数
	iSocketServer = socket(AF_INET, SOCK_STREAM, 0);//创建一个套接字,AF_INET表示使用IPv4,SOCK_STREAM表示使用TCP协议
	if (-1 == iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}
	//2.配置网络传输参数ip、端口等
	tSocketServerAddr.sin_family      = AF_INET;//使用IPv4
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* 端口号 */
 	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;//绑定到本地任意 IP 地址
	memset(tSocketServerAddr.sin_zero, 0, 8); //将 tSocketServerAddr.sin_zero 数组中的前 8 个字节全部设置为 0。
	
	//3.将套接字绑定到刚才配置的地址和端口
	iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
	if (-1 == iRet)
	{
		printf("bind error!\n");
		return -1;
	}

	//4.开始监听连接请求,会将接收到的请求存到一个队列中,队列最大长度为BACKLOG
	iRet = listen(iSocketServer, BACKLOG);
	if (-1 == iRet)
	{
		printf("listen error!\n");
		return -1;
	}

	while (1)
	{
		iAddrLen = sizeof(struct sockaddr);
		//5.接受客户端连接请求,队列中多个请求不确定连接哪一个,没有监听到请求会阻塞程序(程序不会执行后面内容)
		iSocketClient = accept(iSocketServer, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
		if (-1 != iSocketClient)//连接成功
		{
			iClientNum++;
			//输出连接客户端编号,ip
			printf("Get connect from client %d : %s\n",  iClientNum, inet_ntoa(tSocketClientAddr.sin_addr));//inet_ntoa将网络字节序ip从二进制转化为十进制
			//fork复制出一个进程,
			if (!fork())
			{
				/* 子进程的源码,主进程会执行else的代码(此处主进程不执行) */
				while (1)
				{
					/* 6.获得客户端数据并显示 */
					iRecvLen = recv(iSocketClient, ucRecvBuf, 999, 0);//接收客户端的数据并保存到ucRecvBuf中,最长为999字节,通过特定字符判断一次数据是否接收完成
					if (iRecvLen <= 0)
					{
						close(iSocketClient);
						return -1;
					}
					else
					{
						ucRecvBuf[iRecvLen] = '\0';
						printf("Get Msg From Client %d: %s\n", iClientNum, ucRecvBuf);
					}
				}				
			}
		}
	}
	
	//7.关闭套接字
	close(iSocketServer);
	return 0;
}


客户端

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

/* socket
 * connect
 * send/recv
 */

//使用时需要输入参数ip
#define SERVER_PORT 8888

int main(int argc, char **argv)
{
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
	
	int iRet;
	unsigned char ucSendBuf[1000];
	int iSendLen;

	//需要传入服务器ip参数
	if (argc != 2)
	{
		printf("Usage:\n");
		printf("%s <server_ip>\n", argv[0]);
		return -1;
	}
	//1.创建套接字,AF_INET表示使用IPv4,SOCK_STREAM表示使用TCP
	iSocketClient = socket(AF_INET, SOCK_STREAM, 0);

	//2.填充服务器地址信息
	tSocketServerAddr.sin_family      = AF_INET;//使用IPv4
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* 将端口号由主机字节序转化为网络字节序 */
 	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
 	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))//将点分十进制的IP地址转换为网络字节序
 	{
		printf("invalid server_ip\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);// 清空填充字段

	//2.连接服务器
	iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));	
	if (-1 == iRet)
	{
		printf("connect error!\n");
		return -1;
	}

	while (1)
	{
		if (fgets(ucSendBuf, 999, stdin))//从标准输入里获取数据并保存到usSendBuf中,最长为999
		{
			//3.发送数据给客户端
			iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);
			if (iSendLen <= 0)
			{
				//4.关闭套接字
				close(iSocketClient);
				return -1;
			}
		}
	}
	
	return 0;
}

5.问题总结

1.端口、程序、进程关系,多进程监听同一端口(多个网络应用进程监听80端口)如何区分是那个进程的数据

2.IP地址是如何被分配的

3.如何解决僵尸进程问题

添加语句signal(SIGCHLD,SIG_IGN)

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

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

相关文章

基于springboot创建mybatis

第一步&#xff1a;创建项目 第二步&#xff1a;添加依赖 第三步&#xff1a;连接MySQL 第四步&#xff1a;添加MySQL配置 #驱动类名称 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver #数据库连接的url spring.datasource.urljdbc:mysql://localhost:3306/myb…

cmake指定不同版本的mingw编译

cmake指定不同版本的mingw编译&#xff0c;实现思路&#xff1a; 通过指定编译链的方式实现即可。 案例如下&#xff1a; mingw530的archi686&#xff0c;mingw810的archx86_64&#xff0c;通过指定不同版本的mingw编译链&#xff0c;实现程序的32bit和64bit的编译。 # 使用mi…

【爬虫】– 抓取原创力文档数据

使用RPA工具&#xff0c;实现针对于原创力中不可下载文档的抓取&#xff0c;可延用于其他类似文库 1 使用工具、环境 影刀RPA、WPS Office、谷歌浏览器&#xff08;非指定&#xff09; 2 代码流程 3 关键点 此方案只适合抓取非VIP即可预览全文的文档&#xff0c;抓取下来的数…

程序人生——Java异常使用建议

目录 引出异常建议110&#xff1a;提倡异常封装&#xff1b;建议111&#xff1a;采用异常链传递异常 建议112&#xff1a;受检异常尽可能转化为非受检异常建议113&#xff1a;不要在finally块中处理返回值 建议114&#xff1a;不要在构造函数中抛异常建议115&#xff1a;使用Th…

镜像制作实战篇

“ 在失控边缘冲杀为&#xff0c;最终解脱” CMD与EntryPoint实战 EntryPoint 与 CMD都是docker 镜像制作中的一条命令&#xff0c;它们在概念上可能有些相似&#xff0c;但在使用中&#xff0c;两者是有明显的区别的。比如&#xff0c;执行一个没有调用EntryPoint、CMD的容器会…

Linux系统部署DolphinScheduler任务调度系统并实现无公网IP远程访问

文章目录 前言1. 安装部署DolphinScheduler1.1 启动服务 2. 登录DolphinScheduler界面3. 安装内网穿透工具4. 配置Dolphin Scheduler公网地址5. 固定DolphinScheduler公网地址 前言 本篇教程和大家分享一下DolphinScheduler的安装部署及如何实现公网远程访问&#xff0c;结合内…

常用加密算法解析

对称加密算法 所谓对称&#xff0c;就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥是控制加密及解密过程的指令。算法是一组规则&#xff0c;规定如何进行加密和解密。 分类 常用的算法有&#xff1a;DES、3DES、AES等。 DES 全称为Data Encryption…

代码随想录阅读笔记-字符串【替换数字】

题目 给定一个字符串 s&#xff0c;它包含小写字母和数字字符&#xff0c;请编写一个函数&#xff0c;将字符串中的字母字符保持不变&#xff0c;而将每个数字字符替换为number。 例如&#xff0c;对于输入字符串 "a1b2c3"&#xff0c;函数应该将其转换为 "anu…

地下电缆频繁被挖断!智能地钉保卫电缆不马虎

随着城市规模的不断扩大和环境美化的高需求&#xff0c;越来越多管道线路转战地下&#xff0c;然而在城市建设过程中&#xff0c;却经常发生地下电缆、燃气管道、水管被破坏或挖断的事故&#xff0c;对居民生活和社会生产造成严重影响。以下是几起地下管线外破事故&#xff1a;…

实体门店加盟全解析:如何选择加盟项目与避免风险

对于想要开实体店或创业的人来说&#xff0c;拥有一个全面的运营方案是成功的关键。作为一名开鲜奶吧5年的创业者&#xff0c;我将为大家详细分享从选址到日常管理的实体店运营要点&#xff0c;帮助创业者少走弯路。 一、选择加盟项目 1.行业前景&#xff1a;选择一个有发展前…

CrossEntropyLoss 和NLLLoss的关系

交叉熵损失在做一件什么事? 看公式: x是预测(不需要softmax归一化),y是label, N是batch维度的数量,交叉熵损失,干了三件事. 1. 对输入在类别维度求softmax 2. 多softmax后的数,求log 3. 对(样本数, 类别数)为shape的tensor计算NLLLoss. 其中,NLLloss做的就是log取负, 和o…

WanAndroid(鸿蒙版)开发的第四篇

前言 DevEco Studio版本&#xff1a;4.0.0.600 WanAndroid的API链接&#xff1a;玩Android 开放API-玩Android - wanandroid.com 其他篇文章参考&#xff1a; 1、WanAndroid(鸿蒙版)开发的第一篇 2、WanAndroid(鸿蒙版)开发的第二篇 3、WanAndroid(鸿蒙版)开发的第三篇 …

(三)OpenOFDM符号对齐

符号对齐 模块&#xff1a;sync_long.v输入&#xff1a;I (16), Q (16), phase_offset (32), short_gi (1)输出&#xff1a;long_preamble_detected (1), fft_re (16), fft_im (16) 检测到数据包后&#xff0c;下一步是精确确定每个 OFDM 符号的起始位置。在802.11中&#xf…

基于大语言模型(LLM)的表格理解任务探索与实践

大语言模型&#xff08;LLMs&#xff09;的发展日新月异&#xff0c;为表格理解任务带来了新的可能性。表格理解任务&#xff0c;如基于表格的问答和表格事实验证&#xff0c;要求从自由形式的文本和半结构化的表格数据中提取深层次的语义信息。与泛化的文本推理任务不同&#…

数字电子技术实验(八)

单选题 1.3线-8线译码器74138&#xff0c;当输入时&#xff0c;输出有效的是哪路信号 答案&#xff1a;D 评语&#xff1a;0分 单选题 2.用74161计数器实现十进制计数器&#xff0c;置数端的输入信号为&#xff1f; 答案&#xff1a;C 评语&#xff1a;0分 单选题 3.电路中…

《ElementPlus 与 ElementUI 差异集合》el-input 多包裹一层 el-input__wrapper

差异 element-ui el-input 中&#xff0c;<div class"el-input"> 下一级就是 <input> 标签 &#xff1b;element-plus el-input中&#xff0c;<div class"el-input"> 和 <input> 标签之间多了一层 <div class"el-input__…

【LabVIEW FPGA入门】FPGA中的数据流

LabVIEW 以数据流方式执行代码。 当节点的所有输入上都存在数据时&#xff0c;该节点就会执行。 当节点完成执行时&#xff0c;节点的输出将数据传递到下游的下一个节点。 LabVIEW FPGA 使用三个组件来维护这种数据流范例。 节点具有与其功能相对应的逻辑 同步&#xff0c;该组…

直播预告 | 同立海源联合景达生物、星奕昂生物共话“NK细胞药物研发进展及工艺开发策略”!

2023年&#xff0c;免疫细胞治疗领域的产业化步伐显著加快&#xff0c;多种新型细胞治疗药物的上市进程不断推进&#xff0c;为市场带来了多元化和差异化的发展机遇。通用型免疫细胞产品、TCR-T、TIL等创新药物的涌现&#xff0c;不仅丰富了治疗选择&#xff0c;还推动了整个行…

redis学习-redis介绍

目录 1.redis介绍 2.redis常用命令&#xff08;可以在官网的命令中查看redis的所有命令&#xff09; 2.1终端命令 2.2 redis通用命令 2.3五大基本类型的命令以及特殊情况分析 &#xff08;导航&#xff09; 3.事务 4. redis实现消息订阅 5. redis的两种持久化策略 …
最新文章