Linux系统编程-网络编程

osi七层模型:
物-数-网-传-会-表-应
链路层-网络层-传输层-应用层
TCP三次握手和四次挥手全过程及为什么要三次握手解答

链路层:ARP/RARP

获取下一跳mac地址

网络层:IP/ICMP/IGMP

传输层:TCP/UDP

应用层: HTTP/FTP

NAT
两个子网ip同时强求外网相同的资源

打洞机制???

腾讯视频聊天

公-公:直接访问
公-私:NAT映射
私-私:NAT映射、打洞机制

socket

1
2
3
4
5
6
7
8
struct sockaddr_in{
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;//ip地址
}
struct in_addr{
uint32_t s_addr;
}

bind传参需要传sockaddr

网络字节序转换

htonl host–>network
htons

ntohl
ntohs

ip地址转换函数

192.168.1.23–>usnigned int –>htonl
192.168.1.23——————>htonl

int inet_pton();//点分十进制直接转二进制
const char* inet_ntop();//二进制直接转点分十进制

socket()

int socket(int domain,int type,int protocol);

bind() 服务器(客户端不调用系统会自己分配资源)

绑定ip和端口号
int bind(int sockfd,const struct sockaddr* addr,socklen_t addrlen);

listen() 服务器

设置同时允许多少个客户端和我建立链接)
int listen(int sockfd,int backlog)

accept() 服务器(阻塞)

int accept(int sockfd,struct sockaddr addr ,sockleen_t addrlen)
sockfd: socket文件描述符
addr: 传出参数,返回链接客户端地址信息,含IP地址和端口号
addrlen: 传入传出参数,传入sizeof(addr)大小,函数返回时返回真正接受到地址结构体的大小
返回值:成功返回新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno

connect() 客户端

int connnect(int sockfd,const struct sickaddr *addr,socklen_t addrlen)

client

server

socket–>bind–>listen–>accept–>read–>write–>close
socket–>connect–>write–>read–>close

nc 命令

多路I/O转接服务器

服务器的内核帮助 来监听客户端请求

第一种select()

select(),驱使内核来监听,解放应用程序,建立在应用程序与客户端已经链接的前提下

int select(int nfds,fd_set readfds,fd_set writefd,fd_set writefd,fd_set exceptfds,struct timeval* timeout);
参数1:所监听所有文件描述符中,最大的文件描述符+1;
参数2/3/4:所监听的文件描述符“可读”事件集合 readfds()
所监听的文件描述符“可写”事件集合 writefds()
所监听的文件描述符“可读”事件集合 readfds()
参数5:超时时间
返回值:成功:监听的所有文件描述符中满足监听条件(读/写/异常)的总数
失败:

void FD_ZERO(fd_set set)//将set清空
void FD_CLR(int fd,fd_set
set)//将fd从set中清除
int FD_ISSET(int fd,fd_set set);//判断fd是否在集合中
void FD_SET(int fd,fd_set
set)//将fd设置到set集合中

第二种poll()

可以通过修改 /proc/sys/fs/file-max 修改打开文件描述符上限
int poll(struct pollfd* fds,nfds_t nfds,int timeout);
参数一:结构体数组的首地址 监听与返回分离

struct pollfd{
int fd;
short events;
short revents;
}

参数2:数组中有多少文件描述符需要被监听

参数3:-1:永久阻塞等,0:立即返回,>0:等待指定毫秒数

第三种epoll()

select/poll的增强版,它能显著提高程序在大量并发连接中只有少量活跃情况下的系统cpu利用率,因为他会服用文件描述符集合来传递结果,而不用迫使开发者每次等待时间之前都必须重新准备要被监听的文件描述符集合,另一点原因就是获取事件的时候,它无需遍历整个被监听集合,只要遍历哪些被内核I/O事件异步唤醒而加入Ready队列的描述符集合就行了。

epoll_create()

int epoll_create(int size);
//告诉linux内核,你需要给我创建一个多大的epoll模型,底层调用kalloc函数开辟存储空间(size大小的红黑树)
//返回一个文件描述符,这个描述符指向红黑树的树根,(二分查找)

epoll_ctl()

int epoll_ctl(int epfd,int op,int fd,struct epoll_event* event)
//控制红黑树的增删改查
参数2:(红黑树的增删改查)
参数4: 监控文件描述符的结构in,out,error

struct epoll_event{
uint32_t events;
epoll_data_t data;
}

epoll_wait()

阻塞监听
int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout)
参数1;红黑树根节点
参数2:传出符合条件的集合
返回值:返回缩监听文件描述符符合条件的个数

1
2


线程池:

条件变量
pthread_singal()/broadcast()

pthread_cond_wait()

本文标题:Linux系统编程-网络编程

文章作者:Hengliy

发布时间:2018年01月24日 - 04:01

最后更新:2018年03月08日 - 13:03

原始链接:http://hengliy.github.io/2018/01/24/LINUX系统编程-网络编程/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。