Linux网络编程


一、网络基础

1、网络应用程序设计模式

C/S 架构(客户服务器模式)需要下载客户端

优点:1、协议选用灵活
2、可以缓存数据(常用到的图片、视频之内的存放在客户端)速度快
缺点:1、对用户安全构成威胁(窃取用户数据)2、开发工作量大、调试困难

B/S 架构(浏览器服务器模式)

优点:跨平台 安全性
缺点:只能使用HTTP HTTPS 加密过的

不能缓存大量数据 严格遵守http

2、网络分层模型 (只需要管应用层,其他层不需要管,其他有操作系统帮助去处理)

7层OSI模型(物联网输会使用)

在这里插入图片描述

四层TCP/IP 模型

在这里插入图片描述

3、网络传输流程

数据没有封装之前,是不能在网络中传输
数据-应用层-传输层-网络层-链路层

4、协议格式

以太网帧协议(利用)
IP协议 ipv4 ipv6 推是因为实现多边控制
在这里插入图片描述

ARP协议(根据IP地址获取MAC地址)
在这里插入图片描述

TCP协议
在这里插入图片描述

UDP协议
在这里插入图片描述

二、socket编程

1、网络套接(socket)插座 客户端的套接字 服务器端

该套接字内部是由内核借助两个缓冲区实现。
在通信过程中,套接字是成对出现的。
在这里插入图片描述

通信原理
一个文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现。)

2、网络字节序

小端法:高位存高地址,低位存地址
大端法:高位存低地址,低位存高地址
计算机采用的是小端存储,而在网络中采用的大端存储,需要在两者之间进行转换。
地址从低地址到高地址

#include<arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
	uint16_t htonl(uint16_t hostlong);  
	// 以前的话 long  32位 就是 int short就是短字节 16位 用于端口
	uint32_t ntohl(uint32_t hostlong); 
	uint16_t ntohl(uint16_t hostlong);

h表示host,n表示network,l表示32位长整型,s表示16位短整数。
htonl—>本地-网络(IP)
htons—>本地-网络(port)
ntohl—>网络-本地(IP)
ntohs—>网络-本地(port)
192.168.1.1 —> string —>atoi---->int---->htonl—>网络
普通用的是点分十进制 需要先通过atoi函数调用转为int然后再把其转为大端存储
这些写麻烦,系统封装了两个函数
在这里插入图片描述
p理解为ip的意思 n理解为网络
本地的字节序(string Ip)字符串类型 —> 网络字节序
int inet_pton(int af, const char *src, void *dst);
af:
AF_INET 为 ipv4
AF_INET6为ipv6
src:传入 IP地址(点分十进制)
dst:传出 转换后的网络字节序的IP地址
返回值:
成功为 1
异常:0 说明src指向的不是一个有效的Ip地址
失败:-1
const char *inet_ntop(int af, const void *src,
char *dst, socklen_t size);
af:
AF_INET 为 ipv4
AF_INET6为ipv6
src:网络字节序的Ip地址
dst:转换后本地字节序的网络地址(string Ip)字符串类型的,用户能够看懂的
size:dst的大小
返回值:
成功:dst
失败:null

3、sockaddr数据结构

在这里插入图片描述
在这里插入图片描述
bind函数
sockaddr地址结构
现在用的是这个
传入的时候需要初始化,不然传进去也没有用

struct sockaddr_in {
 sa_family_t    sin_family; /* address family: AF_INET */
   in_port_t      sin_port;   /* port in network byte order */
 struct in_addr sin_addr;   /*internet address */
  };

  /* Internet address. */
      struct in_addr {
         uint32_t       s_addr;     /* address in network byte order */
       };


struct sockaddr_in addr;
	addr.sin_family = AF_INET / AF_INET6; // 初始化网络
	addr.sin_port = htons(9527); // 端口 本地字节序---> 网络字节序
	int dst;
	inet_pton(AF_INET, "192.157.22.45", (void*)&dst); // 把主机IP地址转换为网络字节序  这块写void* 是因为传出的时候是void*类型的指针
	
	addr.sin_addr.s_addr = dst;  // 端口 网络字节序
	
	addr.sin_addr.s_addr = htonl(INADDR_ANY); // 取出系统中有效的IP地址,二进制类型
	bind(fd, (struct sockaddr*)&addr, size);  // 传入网络类型,传入sockaddr(需要初始化),结构体的大小

接口那里是struct sockaddr 但是那个定义成为另一个,传的时候需要强转
现在的sockaddr和之前的不太一样,所以需要进行强转
bind函数里面的sockaddr
accpet()函数
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
客户端和服务器端每一个一个套接字 服务器还有一个用于进行监听
服务器端
1、socket() 创建一个套接字
fd=socket(domain,type,protocol)
成功之后,返回一个文件描述符有一个fd(句柄)指向这个套接字, -1错误

2、**绑定Ip地址和端口**  给上面那个socket的绑定ip地址和端口,这个bind里面,它传入了fd,就是进程文件描述表这个表的索引
bind(fd, (struct sockaddr*)&addr, size);  // 传入网络类型,传入sockaddr(需要初始化),结构体的大小
3、设置监听上线 客户端和服务器 同时连接的数量
listen(fd,20)可以同时进行3次握手的客户端数量
4、accpet()阻塞    监听客户端的连接
然后连接上,accpet会返回一个新的socket(),之前的被解放了,进行监听等待其他客户端   两端的socket进行通信
read读到0的话,
会返回读到的字节数 里面写的套接字相当于是一片空间 然后客户端给里面写数据,然后自己读结束,用close()进行关闭

  客户端
  1、创建socket()
  2、调用connect()  绑定服务器的ip地址和端口号 与服务器建立连接,使用现有的socket 服务器的地址结构
  3、write()  
  4、read()

connnect() 函数 第二个参数和accept()函数 一个是传入、一个是传出

三、TCP三次握手

三次握手、四次挥手统一称为通信时序图
服务器端 和 客户端先建立连接 两端各一个套接字,搭这根线就是三次握手

在这里插入图片描述
在这里插入图片描述
滑动窗口
在这里插入图片描述

四、TCP四次挥手

第一次,只关闭一半,另一端可以给另一端还可以发送数据。
套接字里面有两个缓冲区,一个读、一个写
关闭缓冲区指的要不就关闭读,要不就关闭写。
图反着呢
在这里插入图片描述
因为半关闭,所以是四次握手
全双工
发ack不需要缓冲区
在这里插入图片描述
TCP流量控制
MSS:最大报文长度
滑动窗口
往缓冲区里面写,但是服务器端会指定缓冲区大小

TCP建立连接与代码对应:
在这里插入图片描述
在这里插入图片描述

出错处理封装函数(健壮性封装)

封装目的:在server.c编程过程中突出逻辑,将出错处理与逻辑分开,同时也可以跳转man手册
在这里插入图片描述
readn、readline 读n个字节,读一行。

五、并发

1、多进程

在这里插入图片描述
服务器是一个进程,建立连接之后会重新创建出来新的子进程,用于和客户端进行通信在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CPanMirai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值