Linux网络编程
2020-09-28 15:55:14 3 举报
AI智能生成
登录查看完整内容
Linux网络编程
作者其他创作
大纲/内容
Socket编程
套接字概念
socket本身有“插座”的意思,再Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件
再网络通信中,套接字一定是成对出现的,一个文件描述符,对应两个缓冲区
预备知识
网络字节序
网络数据流应采用大端字节序(即低地址高字节)
网络字节序和主机字节序的转换
#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong);uint16_t htons(uint16_t hostshort);uint32_t ntohl(uint32_t netlong);uint16_t ntohs(uint16_t netshort);
IP地址转换函数
点分十进制-->网络字节序 inet_pton();
网络字节序-->点分十进制 inet_ntop();
sockaddr数据结构
sudo grep -r \"struct sockaddr_in {\" /usr 可查看struct sockaddr in 结构体定义
需要强制类型转换
网络套接字函数
socket模型创建流程图
socke函数
建立套接字
domain:\tAF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址\tAF_INET6 与上面类似,不过是来用IPv6的地址\tAF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用
type:\tSOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。\tSOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。\tSOCK_SEQPACKET该协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。\tSOCK_RAW socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)\tSOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包的顺序
protocol:\t传0 表示使用默认协议。
返回值
成功:返回指向新创建的socket的文件描述符
失败:返回-1,设置errno
bind函数
绑定IP、端口
sockfd:\tsocket文件描述符
addr:\t构造出IP地址加端口号
addrlen:\tsizeof(addr)长度
listen函数
指定最大同时发起连接数
查看系统默认backlogcat /proc/sys/net/ipv4/tcp_max_syn_backlog
sockfd:socket文件描述符backlog:排队建立3次握手队列和刚刚建立3次握手队列的链接数和
成功返回0,失败-1
accept函数
阻塞等待客户端发起连接请求
sockdf:\tsocket文件描述符
addr:\t传出参数,返回链接客户端地址信息,含IP地址和端口号
返回值:\t成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno
connect函数
发起连接
addr:\t传入参数,指定服务器端地址信息,含IP地址和端口号
返回值:\t成功返回0,失败返回-1,设置errno
客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址。connect()成功返回0,出错返回-1。
C/S模型下
server
socket()-->bind()-->listen()-->accept()-->( )-->close
client
socket()-->bind()-->connect()-->( )-->close()
客户端可以“隐式绑定”
出错处理函数
wrap.c
将原本函数加上出错处理代码包装成新的函数
eg:read 返回值:\t\t1. > 0 实际读到的字节数 buf=1024 1. == buf 1024 2. < buf 56;\t\t2. = 0 数据读完(读到文件、管道、socket 末尾--对端关闭) \t\t3. -1 异常 1. errno == EINTR 被信号中断 重启/quit 2. errno == EAGAIN (EWOULDBLOCK) 非阻塞方式读,并且没有数据 3. 其他值 出现错误。--perror exit。readn\eadline
高并发服务器
多进程并发服务器
需要考虑以下几点:1.父进程最大文件描述符个数(父进程需要close关闭accept返回的新文件描述符)2.系统内创建进程个数(与内存大小相关)3.进程创建过多是否降低整体服务器性能(进程调度)
fork、signal/sigcation
多线程并发服务器
需要考虑以下几点:1.调整进程内最大文件描述符上限2.线程如有共享数据,考虑线程同步3.服务于客户端线程退出时,退出处理(退出值,分离态)4.系统负载,随着链接客户端增加,导致其他线程不能及时得到CPU
线程分离detach修改线程属性
多路I/O转接服务器(多任务IO服务器)
主要思想
不再由应用程序自己监视客户端连接,取而代之由内核应用程序监视文件
select
1.select能监听的文件描述符个数受限于FD_SETSIZE,一般为1024,单纯改变进程打开的文件描述符个数并不能改变select监听文件个数
2.解决1024以下客户端时使用select是很合适的,但如果连接客户端过多,select采用的是轮询模型,会大大降低服务器相应效率,不应再用select
struct timeval {\t\tlong tv_sec; /* seconds */\t\tlong tv_usec; /* microseconds */\t};
select函数原型分析
select分析
select2
poll
select的升级:不用自行维护文件描述符集合
struct pollfd { int fd; /* 文件描述符 */ short events; /* 监控的事件 */ short revents; /* 监控事件中满足条件返回的事件 */\t};
POLLOUT\t\t普通或带外数据可写
POLLERR \t\t发生错误
nfds \t\t\t监控数组中有多少文件描述符需要被监控
timeout \t\t毫秒级等待\t\t-1:阻塞等,#define INFTIM -1 \t\t\t\tLinux中没有定义此宏\t\t0:立即返回,不阻塞进程\t\t>0:等待指定毫秒数,如当前系统时间精度不够毫秒,向上取值
poll函数
epoll
是select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,原因:1.复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合 2.获取事件时,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行
epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边沿触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。
API
1.\t创建一个epoll句柄,参数size用来告诉内核监听的文件描述符的个数,跟内存大小有关。#include <sys/epoll.h>\tint epoll_create(int size)\t\tsize:监听数目
epfd:\t为epoll_creat的句柄
op:\t\t表示动作,用3个宏来表示:\t\t\tEPOLL_CTL_ADD (注册新的fd到epfd),\t\t\tEPOLL_CTL_MOD (修改已经注册的fd的监听事件),\t\t\tEPOLL_CTL_DEL (从epfd删除一个fd);
event:\t告诉内核需要监听的事件
struct epoll_event {\t\t\t__uint32_t events; /* Epoll events */\t\t\tepoll_data_t data; /* User data variable */\t\t};
typedef union epoll_data {\t\t\tvoid *ptr;\t\t\tint fd;\t\t\tuint32_t u32;\t\t\tuint64_t u64;\t\t} epoll_data_t;
EPOLLIN :\t表示对应的文件描述符可以读(包括对端SOCKET正常关闭)\t\tEPOLLOUT:\t表示对应的文件描述符可以写EPOLLERR:\t表示对应的文件描述符发生错误
events:\t\t用来存内核得到事件的集合,
maxevents:\t告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size
timeout:\t是超时时间\t\t\t-1:\t阻塞\t\t\t0:\t立即返回,非阻塞\t\t\t>0:\t指定毫秒
返回值:\t成功返回有多少文件描述符就绪,时间到时返回0,出错返回-1
事件模型
epoll ET \t\t边沿触发。 event = EPOLLIN | EPOLLET
epoll LT水平触发(缺省的处理方式)
epoll 非阻塞IO\t\t边沿触发 while(read()) fcntl(O_NONBLOCK);
epoll反应堆模型
libevent核心思想实现
libevent--跨平台 精炼--epoll
核心思想
1. epoll --- 服务器 --- 监听 --- fd ----可读 ---- epoll返回 ---- read --- 小写转大写 --- write ---- epoll继续监听
2. epoll 反应堆模型: (\"滑动窗口\
服务器监听,如果客户端在指定的时间内无数据收发,则服务器将其从红黑树上剔除
线程池
1.\t预先创建阻塞于accept多线程,使用互斥锁上锁保护accept2.\t预先创建多线程,由主线程调用accept
线程池思路分析
socket IPC
1. Pipe fifo 实现最简单\t2. mmap \t非血缘关系进程间\t3. 信号\t\t开销小\t4. domain\t稳定性最好
本地套接字domain
只是将应用层数据从一个进程拷贝到另一个进程更有效率,无需金国网络协议栈、打包拆包等
IPC机制本质上是可靠的通讯,网络协议栈是不可靠的通讯设计
与网络socket的不同
结构体sockaddr_un表示地址是一个socket类型的文件在文件系统 中的路径这个文件由bind电泳创建,若文件存在,则bind()错误返回所以在bind前先unlink
struct sockaddr_in {__kernel_sa_family_t sin_family; \t\t\t/* Address family */ \t地址结构类型__be16 sin_port;\t\t\t\t\t \t/* Port number */\t\t端口号struct in_addr sin_addr;\t\t\t\t\t/* Internet address */\tIP地址};struct sockaddr_un {__kernel_sa_family_t sun_family; \t\t/* AF_UNIX */\t\t\t地址结构类型char sun_path[UNIX_PATH_MAX]; \t\t/* pathname */\t\tsocket文件名(含路径)};
len长度
Linux网络编程
网络基础
协议的概念
协议
“规则”
是数据传输和数据解释的规则
典型协议
传输层 常见协议有TCP/UDP协议
TCP传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
UDP用户数据报协议(User Datagram Protocol)是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
应用层 常见的协议有HTTP协议,FTP协议
HTTP超文本传输协议(Hyper Text Transfer Protocol)是互联网上应用最为广泛的一种网络协议
FTP文件传输协议(File Transfer Protocol)
网络层 常见协议有IP协议、ICMP协议、IGMP协议
IP协议是因特网互联协议(Internet Protocol
ICMP协议是Internet控制报文协议(Internet Control Message Protocol)它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息
IGMP协议是 Internet 组管理协议(Internet Group Management Protocol),是因特网协议家族中的一个组播协议。该协议运行在主机和组播路由器之间
网络接口层 常见协议有ARP协议、RARP协议
ARP协议是正向地址解析协议(Address Resolution Protocol),通过已知的IP,寻找对应主机的MAC地址。
RARP是反向地址转换协议,通过MAC地址确定IP地址
网络应用程序设计模式
C/S(客户机/服务器)
优点
较高的数据传输效率
协议选用较为灵活
缺点
对用户安全构成威胁
开发工作量大,调试困难
B/S(浏览器/服务器)
开发量较小
移植性好,不受平台限制
网络应用支持受限
数据缓存不尽人意
协议选择不灵活--http
分层模型
OSI七层模型
物理层
比特
数模转换/模数转换
数据链路层
帧
错误检测和纠正
网络层
数据报
传输层
段
传输协议和端口号
会话层
系统之间发起会话或者接受会话请求
表示层
可确保两系统之间应用层可以实现信息交互
应用层
位用户的应用程序提供网络服务
TCP/IP四层模型
Telnet、FTP、e-mail等
TCP、UDP
IP、ICMP、IGMP
链路层
设备驱动程序及接口卡
模型图
协议格式
数据包封装
数据--应用层--传输层--网络层--链路层
以太网帧格式
MTU:以太网的最大传输单元--1500
ARP数据报格式
ARP缓存表
arp -a
IP段格式
首部长度和数据长度都是可变的,但总是4字节的整数倍
最小20字节,最大60字节
TTL生存时间,经过一跳就减1,为0自动丢弃
UDP数据包格式
TCP数据报格式
NAT映射
私有IP转共有IP
打洞机制
TCP协议
三次握手四次握手
TCP不是不会丢包,是丢包后会重传
三个相关概念
MTU
最大传输单元 受协议限制 以太网1500 IP 65535
mss
表示一个数据包携带数据的上限数
半关闭
滑动窗口(TCP流量控制)
TCP状态转换
2MSL
报文最大生存时间
2MSL等待状态
端口复用
使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1,表示允许创建端口号相同但IP地址不同的多个socket描述符
当TCP链接中A发送FIN请求关闭,B端回应ACK后(A端进入FIN_WAIT_2状态),B没有立即发送FIN给A时,A方处在半链接状态,此时A可以接收B发送的数据,但是A已不能再向B发送数据。
sockfd: 需要关闭的socket的描述符
与close区别:
TCP异常断开
心跳检测机制
使用场景
在TCP网络通信中,经常会出现客户端和服务器之间的非正常断开,需要实时检测查询链接状态
实现机制
Heart-Beat线程这个是最常用的简单方法。在接收和发送数据时个人设计一个守护进程(线程),定时发送Heart-Beat包,客户端/服务器收到该小包后,立刻返回相应的包即可检测对方是否实时在线
乒乓包
可以携带简单的数据
设置TCP属性
SO_KEEPALIVE 保持连接检测对方主机是否崩溃,避免(服务器)永远阻塞于TCP连接的输入
保持存活探测分节
对方接受一切正常:以期望的ACK相应
对方已崩溃且已重新启动:以RST响应套接口的待处理错误被置为ECONNRESET,套接 口本身则被关闭
span style=\"font-size:10.5pt;mso-bidi-font-size:11.0pt;font-family:宋体;mso-ascii-font-family:Calibri;mso-ascii-theme-font:minor-latin;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin;mso-bidi-font-family:"Times New Roman";mso-bidi-theme-font:minor-bidi;mso-font-kerning:1.0pt;mso-ansi-language:EN-US;mso-fareast-language:ZH-CN;mso-bidi-language:AR-SA\"对方无任何响应:源自span lang=\"EN-US\" style=\
UDP协议
发短信--无需建立、维护连接
因此开销较小,数据传输速度快、实时性强
无连接的不可靠报文传递
再应用层添加辅助校验协议来弥补UDP的不足
可能出现的问题
UDP无滑动窗口机制,会出现缓冲区被填满后,再接受数据时丢包的现象
解决方案:1.服务器应用层设计流量控制,控制发送数据速度 2.借助setsockopt函数改变接受缓冲区大小
220*1024在不断实验中发现大小最佳
UDP处理模型
C/S模型-UDP(直接传数据)
TCP与UDP比较
TCP
面向连接的可靠数据包传递 ---完全弥补
稳定
1.数据稳定 --- 丢包回传(回执机制)(丢包率97‰)
2.速率稳定
3.流量稳定 --- 滑动窗口
效率低、速度慢
大文件、重要文件传输
UDP
无连接的不可靠报文传递 ---完全不弥补
不稳定
数据、速率、流量
效率高、速度快
对实时性要求比较高,视频会议、视频电话、广播、飞秋
腾讯
TCP --- TCP + UDP --- UDP+应用层自定义协议弥补UDP的丢包
广播
IP:192.168.42.255(广播)
IP:192.168.42.1(网关)
组播(多播)
永久/临时组播组
官方分配---永久组播组
ip地址不变
组内成员可变化、数量任意
224.0.0.0~224.0.0.255\t\t为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;224.0.1.0~224.0.1.255\t\t是公用组播地址,可以用于Internet;欲使用需申请。224.0.2.0~238.255.255.255\t为用户可用的组播地址(临时组地址),全网范围内有效;239.0.0.0~239.255.255.255\t为本地管理组播地址,仅在特定的本地范围内有效。
ip ad查看网卡编号
if_nametoindex 命令可以根据网卡名,获取网卡序号
分屏软件实现思路
1.屏幕截图模块(24帧 几MB) -- 2.截取帧数(8-12帧) -- 3.压缩图片M->K -- 4.压缩数据包 -- 5.传递(多播) -- 6.解压缩(算法) -- 7.成像
setsockopt
作用总结
1.端口复用
2.设置缓冲区大小
3.开放广播权限
4.开放组播权限
5.加入组播组
0 条评论
回复 删除
下一页