Linux下多任务编程(网络编程)

前言

        本文记录OSI7层模型、TCP\IP模型、socket在UDP、TCP使用。

网络

        网络:多个计算机之间相互通信
        网络协议:多个计算机之间通信用的语言(是有一定规范的)

OSI 7层模型

        应用层 表示层 会话层 传输层 网络层 链路层 物理层

面向应用应用层应用程序:FTP、E-mail、Telnet
面向服务表示层数据格式定义、数据转换/加密
会话层建立通信进程的逻辑名字与物理名字之间的联系
面向通信传输层差错处理/恢复,流量控制,提供可靠的数据传输
通信子网网络层数据分组、路由选择
链路层数据组成可发送、接收的帧
物理层传输物理信号、接口、信号形式、速率

TCP/IP协议

        四层(IBM公司推出的)

应用层http:超文本传输协议
ftp:文件传输协议
smtp:简易邮件传输协议
dhcp:动态ip分配协议
dns:域名解析协议(www.baidu.com->192.168.11.111)
传输层TCP:流式套接字
UDP:数据报套接字,可靠,但是慢
网络层

ip:网络层最重要的协议(IPV4、IPV6)
icmp:ping命令使用的协议(判断对方是否在线)
arp:地址解析协议(ip地址转换成物理地址)

网络接口层ether(以太网):常用的所有物理介质(网线、WIFI)

        基于TCP协议:http、ftp、smtp 保证数据不能丢失,允许慢一些。 
        基于UDP协议:dhcp、dns 数据可以丢,但是快

查看ip地址和物理地址的记录
arp -a

        物理地址(mac):网卡出厂时,自带编号,不可更改
        IP地址:由路由器分配的唯一标识,连接上不同的网络,IP地址也会发生改变

交换机和路由器的区别(重点)

        交换机:根据mac地址(物理地址)进行数据的交换,不能分配ip地址,仅限于局域网使用。
        路由器:根据IP地址进行数据的交互,能分配ip地址,作用于互联网和局域网。

网络管理相关命令(重点)

       (1) 查看ip地址

ifconfig

        (2)nc 模拟服务器

TCP通信
启动服务器
nc -l 8888
启动客户端
nc 127.0.0.1 8888 (整数1-65535之间)UDP通信
启动接收端
nc -ul 9999
启动发送端
nc -u 127.0.0.1 9999

Linux下的网络编程

IP地址的存储方式

        (1)点分制        192.168.1.111        每个数的取值范围是0-255
        (2)整数形式        0xc0a8016f

sizeof("192.168.1.111");    //14个字节
sizeof(0xc0a8016f);         //4个字节

        区别:点分制可读性强,占用空间大;整数形式可读性差,占用空间小。

inet_addr函数

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp);

        功能: 将点分制(字符串)的IP地址转成整数的IP地址

        参数:点分制(字符串)的IP地址

        返回值:整数的IP地址

大端序和小端序

        大端序(网络字节序):低地址存高字节,高地址存低字节;
        小端序:低地址存低字节,高地址存高字节。

验证操作系统采用的是小端序还是大端序

指针方式验证

int main(int argc, char const *argv[])
{int a = 0xc0a8016f;char *p = (char *)&a;printf("%02x %p\n", *p, p);printf("%02x %p\n", *(p+1), p+1);printf("%02x %p\n", *(p+2), p+2);printf("%02x %p\n", *(p+3), p+3);return 0;
}6f 0x7ffcbc0fde7c
01 0x7ffcbc0fde7d
a8 0x7ffcbc0fde7e
c0 0x7ffcbc0fde7f
验证之后我的主机是小端序

 共用体方式验证

union addr
{int a;char b[4];
};
int main(int argc, char const *argv[])
{union addr num;num.a = 0xc0a8016f;printf("%x\n",num.b[0]);return 0;
}

网络字节序和主机字节序

 h:host 主机        to:转        n:network 网络        l:long 四字节        s:short 二字节

htonl

主机转网络,转四字节变量

htons主机转网络,转二字节变量
ntohl网络转主机,转四字节
ntons网络转主机,转二字节

端口号 

         区分一台电脑上的应用程序的,也就是网络数据包应该给哪个应用。同一台电脑上,同一个端口号在同一时刻只能被一个应用程序绑定。

        一些有固定端口号的应用
        ftp        21
        http        80
        dns        53
        dhcp        67

        端口号(1-65535),1-1024分配给一些固定的服务

Socket 编程

        套接字编程,也叫网络编程,进程间通信中唯一一个可以跨主机的通信

UDP通信

        传输速度快,但是不可靠
        应用:局域网,对数据的实时性要求较高的互联网

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);

        参数1:族协议 通常为AF_INET(ipv4)
        参数2:SOCK_DGRAM 使用UDP Socket
                     SOCK_STREAM 使用TCP Socket
        参数3:网络层协议,为0即可

        返回值:≥0 Socket的文件描述符(open的返回值类似),<0 出错

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{//int socket(int domain, int type, int protocol);int sock_fd = socket(AF_INET,SOCK_DGRAM,0);printf("%d\n",sock_fd);close(sock_fd);return 0;
}
接收端 
bind函数
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

recvfrom函数
#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);
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{// 1.创建套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);// 2.绑定自己的IP地址和端口号struct sockaddr_in myaddr;myaddr.sin_family = AF_INET;myaddr.sin_port = htons(8888);myaddr.sin_addr.s_addr = inet_addr("127.0.0.1");int ret = bind(sockfd, (struct sockaddr *)&myaddr, sizeof(struct sockaddr));// 3.接收数据char buf[128];struct sockaddr_in your_addr;int len = sizeof(your_addr);recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&your_addr, &len);printf("buf is %s\n", buf);// 4.关闭close(sockfd);return 0;
}
发送端 
sendto函数
#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);
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{// 1.创建Socketint sockfd = socket(AF_INET, SOCK_DGRAM, 0);// 2.指定对方的ip地址和端口号struct sockaddr_in your_addr;your_addr.sin_family = AF_INET;your_addr.sin_port = htons(8888);your_addr.sin_addr.s_addr = inet_addr("127.0.0.1");// 3.发送数据char buf[128] = "hello";sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&your_addr, sizeof(your_addr));// 4.关闭close(sockfd);return 0;
}

 

 TCP通信

        可靠,但是慢

        完成可靠的方法:
        (1)发送之前,先建立连接;
        (2)发送时,有应答机制,如果中间数据丢失,会重新发送。

TCP通信流程

服务器端
socket函数(略)
bind函数(略)
listen函数
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd, int backlog);

        设置最大监听数(设置最大同时连接数):指正在连接的客户端,已经建立连接的客户端(在接收数据的客户端)不算在内。

        参数1:socket的返回值
        参数2:设置的最大监听数

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

        阻塞等待客户端的连接

        参数1:socket的返回值;
        参数2:连接的客户端的ip地址和端口号的结构体的地址(一般为NULL,代表不关心,和recvfrom的最后两个参数一样);
        参数3:结构体长度的地址(一般为NULL)。

        返回值:newfd代表这个链接成功客户端的连接通道的编号;后续与这个客户端进行通信时,使用newfd。

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

        发送数据,如果无人发数据,则阻塞等待数据的发送

        参数1:accept函数的返回值
        参数2:发送数据的首地址
        参数3:缓存区长度
        参数4:0

        返回值:大于0 实际接收数据的长度;≤0 连接断开

实例代码
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{// 1.创建socketint sockfd = socket(AF_INET, SOCK_STREAM, 0);// 2.绑定IP地址和端口号struct sockaddr_in myaddr;myaddr.sin_family = AF_INET;myaddr.sin_port = htons(8888);myaddr.sin_addr.s_addr = htonl(INADDR_ANY);int ret = bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr));// 3.设置最大监听数listen(sockfd, 5);// 4.阻塞等待客户端的连接int newfd = accept(sockfd, NULL, NULL);// 5.接收char buf[128] = {0};ret = recv(newfd, buf, sizeof(buf), 0);printf("ret %d ,buf is %s\n", ret, buf);// 6.关闭close(newfd);close(sockfd);return 0;
}

客户端

1.创建socket
2.指定对方的ip地址和端口号
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(atoi(argv[2]));
client_addr.sin_addr.s_addr = inet_addr(argv[1]);
3.连接客户端
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

        参数1:socket返回值
        参数2:结构体地址
        参数3:结构体长度

        返回值:0 成功,-1 失败

4.收发数据

        客户端只能连接一个服务器,所以没有newfd,所以recv/send的第一个参数用socket返回值

5.关闭close
实例代码
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/inet.h>
int main(int argc, char const *argv[])
{// 1.创建socket套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);// 2.指定对方的ip地址和端口号struct sockaddr_in your_addr;your_addr.sin_family = AF_INET;your_addr.sin_port = htons(8888);your_addr.sin_addr.s_addr = inet_addr("127.0.0.1");// 3.连接int ret = connect(sockfd, (struct sockaddr *)&your_addr, sizeof(your_addr));// 4.收发数据char buf[128] = {0};scanf("%s", buf);send(sockfd, buf, sizeof(buf), 0);// 5.关闭close(sockfd);return 0;
}

循环服务器

缺点:
        (1)newfd会被覆盖
        (2)accept和recv 会互相阻塞

        A客户端连接成功后,accept解除阻塞,代码运行到recv,等待A客户端发送的数据;若A一直不发送数据,会recv处一直阻塞,无法运行到accept,其它客户端无法进行连接。

TCP和UDP通信的区别

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

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

相关文章

在数字电路实验的测试中,示波器的输入耦合为什么要选用直流耦合?

示波器输入耦合的作用及其在数字电路测试中的选择 概述 示波器是电子工程师进行各种信号测量和分析的关键工具。无论是在模拟电路还是数字电路中&#xff0c;示波器都能提供对信号状态的直观展示。然而&#xff0c;在使用示波器进行测量时&#xff0c;输入耦合的选择至关重要…

搭建Web环境、初识JSP

搭建Web环境、初识JSP 1.B/S架构工作原理 B/S架构采用请求/响应模式进行交互 2.URL 计算机通过统一资源定位符实现资源访问 URL&#xff1a;Uniform Resource Locator的缩写 唯一能识别Internet上具体的计算机、目录或文件夹位置的命名约定 3.Web服务器 Web服务器 是可以向…

电子木鱼解压小程序源码系统 带源代码包以及搭建部署教程 源码开源可二开

系统概述 电子木鱼解压小程序源码系统是一款基于现代Web技术开发的轻量级应用程序&#xff0c;旨在为用户提供一种简单、高效的解压方式。该系统通过模拟传统木鱼的敲击效果&#xff0c;结合优美的音效和动画&#xff0c;帮助用户达到放松身心的效果。同时&#xff0c;系统还提…

基于SSM的朋辈帮扶系统

文未可获取一份本项目的java源码和数据库参考。 一、本课题研究意义 随着市场经济发展的不断深入&#xff0c;高校学生面临着新的问题和挑战。在全球一体化、价值观多元化、信息网络化的大背景下&#xff0c;越来越多的学生承受着来自社会、家庭与自身方方面面的压力&#xf…

【Linux】嵌入式Linux系统的组成、u-boot编译

Linux—嵌入式Linux系统的组成、u-boot编译 前言一、嵌入式Linux系统的组成1.1 嵌入式Linux系统和PC完整的操作系统的对比如下&#xff1a;1.2 PC机—Windows系统启动流程&#xff08;PC机—Linux系统、嵌入式ARM—linux系统的启动流程类似&#xff09; 二、编译u-boot2.1 u-bo…

【动手学电机驱动】 TI InstaSPIN-FOC(2)Lab01 闪灯实验

【动手学电机驱动】 TI InstaSPIN-FOC&#xff08;2&#xff09;Lab01 闪灯实验 1. 硬件连接与设置2. Lab01&#xff1a;闪灯实验2.1 项目简介2.2 导入项目2.3 调试和运行 3. 修改程序&#xff1a;改变闪灯频率4. 程序解读4.1 软件流程图4.2 包含文件、变量和函数声明4.3 中断服…

Java Mail腾讯企业邮箱或其他邮箱发送邮件失败bug记录

问题出现情况 邮件发送时debug用F8逐步运行可以成功发送邮件&#xff0c;但是用F9或者直接运行程序却发送失败未开启mail的debug模式的报错日志是下面这个&#xff1a;org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is java…

Chainbase :链原生的 Web3 AI 基建设施

“随着 Chainbase 在生态系统和市场方面的进一步拓展&#xff0c;其作为链原生 Web3 AI 基建设施的价值将愈发显著。” 算法、算力和数据是 AI 技术的三大核心要素。实际上&#xff0c;几乎所有的 AI 大模型都在不断革新算法&#xff0c;以确保模型能够跟上行业的发展趋势&…

CUDA Graphs学习与实验

CUDA Graphs学习与实验 一.参考链接二.测试方案三.测试代码 CUDA图&#xff08;CUDA Graphs&#xff09;为CUDA引入了一种全新的工作提交模型。它允许将一系列操作&#xff08;如内核启动&#xff09;以图的形式表示&#xff0c;并通过依赖关系将这些操作连接起来。这种图的定义…

C语言—双链表

一、双向链表的结构 注意&#xff1a;这⾥的“带头”跟前⾯我们说的“头节点”是两个概念&#xff0c;实际前⾯在单链表阶段称呼不严谨&#xff0c;带头链表⾥的头节点&#xff0c;实际为“哨兵位”&#xff0c;哨兵位节点不存储任何有效元素&#xff0c;只是站在这⾥“放哨的”…

【C++】C++的引用

一.引用 1.引用的概念和定义 引用不是新定义⼀个变量&#xff0c;而是给已存在变量取了⼀个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同⼀块内存空间。 类型& 引用别名 引用对象; 2.引用的特征 a.引用在定义时必须初始化 …

Visual Studio--VS安装配置使用教程

Visual Studio Visual Studio 是一款功能强大的开发人员工具&#xff0c;可用于在一个位置完成整个开发周期。 它是一种全面的集成开发环境 (IDE)。对新手特别友好&#xff0c;使用方便&#xff0c;不需要复杂的去配置环境。用它学习很方便。 Studio安装教程 Visual Studio官…

详解前端开发都需要掌握的十个 JavaScript 基本数组函数

假设你正在开发一个复杂的 Web 项目。你的数据来自许多 API&#xff0c;你的工作是高效地处理、过滤和分析这些数据。你的时间很紧张&#xff0c;所以每一行代码都很重要。 这时学习高级 JavaScript 数组方法就会对你有所帮助。 这些函数不仅可以减少代码量&#xff0c;还可以…

阻塞socket 和非阻塞socket的区别(浅显易懂版)

什么是阻塞socket&#xff0c;什么是非阻塞socket。 对于这个问题&#xff0c;我们要先弄清什么是阻塞/非阻塞。 阻塞与非阻塞是对一个文件描述符指定的文件或设备的两种工作方式。 阻塞的意思是指&#xff0c;当试图对该文件描述符进行读写时&#xff0c;如果当时没有东西可…

基于Feign的远程调用

目录 前言 RestTemplate方式调用存在的问题 存在的问题 Feign Feign介绍 Feign的使用步骤 引入依赖 添加注解 编写Feign客户端 使用客户端&#xff08;修改orderService&#xff09; 原代码 修改后 总结 前言 RestTemplate方式调用存在的问题 以前利用RestTempla…

【Unity 100个实用小技巧】 UI分辨率适配

UI分辨率适配 学习实际项目中&#xff0c;分辨率适配的方案&#xff0c;基础版本。 以下适配以720*1680为基准适配 具体操作 Canvas Scaler的Screen Match Model 设置为Match Width Or Height&#xff0c;Match设置为0 这个设置&#xff0c;是以宽为基准进行分辨率适配 其实在…

uniapp__微信小程序使用秋云ucharts折线图双轴

1、子组件 <template><view class"charts-box"><qiun-data-charts type"line":opts"computedOpts":chartData"chartData"/></view> </template><script> export default {props: {chartData: {t…

【优选算法】(第三十五篇)

目录 验证栈序列&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 N叉树的层序遍历&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 验证栈序列&#xff08;medium&#xff09; 题目解析 1.题目链接&#xff1a;. - 力扣&#xff08;L…

只需5步,就可以使用大语言模型(LLM)打造高效的应用

01 概述 随着人工智能技术的飞速发展&#xff0c;大型语言模型&#xff08;LLM&#xff09;正逐渐成为各个领域的得力助手。从最初的文本理解、生成到翻译&#xff0c;这些模型在自然语言处理&#xff08;NLP&#xff09;中的出色表现&#xff0c;让它们在聊天机器人、虚拟助…

98. UE5 GAS RPG 实现技能眩晕效果

我们在技能伤害基类上面设置了对应的负面效果应用的配置项&#xff0c;用来实现技能的负面效果应用。 在之前实现火球术的负面效果时&#xff0c;我们我们在创建火球时&#xff0c;通过伤害基类上的创建技能配置用于后续应用。 在火球攻击到敌人时&#xff0c;通过函数库书写…