2014年7月1日
1、tcp报头格式 6个标志位syn ack psh rst fin urg
2、半连接下read读到的字节数为0
3、Tcp头部报文最长为60字节,20字节的固定头部,选项信息最多40字节。选项信息可以包含窗口扩大因子的设置,最大报文段的限制,sack的设置,时间戳的设置等8项。
4、Tcp头部中的窗口大小用于流量控制
5、netstat查看当前tcp的状态
6、Tcp状态转移图
终止tcp连接,而不是引用计数减1,用shutdown(int sockfd,int howto)
Tcp数据读写:recv(int sockfd,void *buff,size_t len,int flag)
send(int sockfd,void *buff,size_t len,int flag)
Udp数据读写:recvfrom(int sockfd,void *buff,size_t len,int flag,struct sockaddr*src_addr,socklen_t *addrlen);
sendto(int sockfd,void *buff,size_t len,int flag,struct sockaddr*src_addr,socklen_t *addrlen);
通用数据读写:recvmsg(int sockfd,struct msghdr*msg,int flags);
sendmsg(int sockfd,struct msghdr*msg,int flags);
7、
8、设置tcp发送缓冲区setsockopt(int sock,SO_SOCKET,SO_RCVBUF,int *num,int len);
Getsockopt(int sock,SO_SOCKET,SO_RCVBUF,int *num,socklen_t *len);
设置tcp接收缓冲区setsockopt(int sock,SO_SOCK,SO_SENBUF,int *num,int len);
Getsockopt(int sock,SO_SOCK,SO_SENBUF, int *num,socklen_t *len);
9、查看服务的端口号/etc/services
10、查看协议的编号 /etc/protocols
2014年7月11日
11、http请求报头请求方法:GET、PUT、HEAD、POST、DELETE、TRACE、OPTIONS、CONNECT、PATCH
12、http响应码:1**:信息、继续发生数据2**:成功3**:重定向4**:客户端问题5**:服务器问题
2014年7月12日
13、服务器模型:B/S C/S P2P
14、服务器两种高效事件处理模式
Reactor主线程只负责监听文件描述符,所以描述符上的操作包括连接、读写事件都交由工作线程处理。主线程监听监听套接口和连接套接口。这是一种同步I/O模型。
Proactor模式主线程只监听监听套接口,连接套接口读写事件交由工作线程处理。这是一种异步I/O模型。
服务器两种高效的并发模式
半同步/半异步模式
缺点:
只有主线程一个异步线程,主线程和工作线程同时操作请求队列,执行加锁,耗费cpu时间
工作线程只处理一个客户请求,多开线程时造成线程切换,耗费cpu时间
领导者/追随者模型
Nginx模型
http有限状态机:
从缓存中每次读入一行,并记录读到的位置。
提高服务器性能的方法:池、数据复制(ftp sendfile零拷贝)、避免上下文切换(进程线程的切换)、尽量少使用锁或减小锁的粒度比如读写锁(锁不执行代码操作但是要切换到内核态)
2014年7月20日
15、Libevent
创建 struct event_base *base = event_intit()/ event_base_new()
注册事件 struct event * io_ev=event_new()//evsignal_new//evtimer_new
Event_add(io_ev);
Event_base_dispatch(base);
Event_base_loopexit()
没有需要监听的事件(两种退出的条件)
2014年7月21日
16、Linux架构
Linux数据存储的基本单位是字节
Linux的文件类型,-普通文件,目录文件,设备文件、链接文件、管道文件
17、Tcp滑动窗口会造成网络资源利用率低下,比如接收端读数据缓慢,通告窗口的值很小,但是tcp依然发送数据。因为tcp只限制了最大发送窗口,却没有限制最小发送窗口
解决:限制窗口的通告时机。
发送端持续发送少量数据,导致窗口闲置
解决:Nagle算法
确认号本身不含数据,占用宽带资源
解决:ACK延时,只发最后一个数据段的确认号
2014年7月22日
1、信号处理函数必须是可重入函数,为了避免竞态条件的产生,里面严禁调用不可重入函数,比如标准库函数;
2、信号处理函数在执行期间,信号是被屏蔽的,所以信号不会再次被触发。常用的解决方案是用管道将信号传递给主循环;(统一事件源的信号的实现)
3、主机字节序为小端,整数高位在内存的高位地址。网络字节序为大端。Java虚拟机采用大端字节
测试大小端
Union
{
Short value;
Char byte[sizeof(short)];
}
Test.Value = 0x0102;
If(test.byte[0] == 1 && test.byte[1] == 2)big endian
4、Htonl(unisigned long int hostlong) 主机字节序转网络字节序
5、Char *Inet_ntoa()网络字节序整数ip转换为字符串,内部是一个静态变量,不可重入
6、Accept只从监听队列中取出连接,而不在乎连接处于何种状态,ESTABLISHED和CLOSE_WAIT
7、Close()只对引用计数减1,shutdown可以由howto参数立即终止读端、写端或者读写端
8、Sockatmark()判断是否设置了带外数据
9、Getsockname()
getpeername()
10.Getsockopt()
setsockopt()
服务器端对socket设置的选项在accept调用后自动继承,客户端则在connect之前设置,connect后三次握手已经完成
10、tcp接受缓冲区最小值是256字节,发送缓冲区最小值为2048字节(一般)。默认情况
11、默认情况下tcp发送缓冲区和接收缓冲区低水位标记都为1字节
12、mmap()申请一段内存空间。Munmap()释放创建的这段内存空间
13、pipe中的零拷贝函数,其中至少有一端为管道。在epoll中可用。Tee函数用于在两个管道中的零拷贝。Fcntl改变文件描述符属性
2014年7月25日
18、零拷贝函数:splice(输入描述符,偏移位置,输出描述符,便宜位置,长度,标志位);
Sendfile(输入描述符,输出描述符,偏移位置,长度);
Tee(输入描述符,输出描述符,长度,标志);
Splice必须有一个为管道,tee两个必须都为管道。
19、存储器的层次结构
20、Select(int nfds,fd_set* readfds, fd_set* writefds, fd_set*excptfds,struct teimeval*timeout);
FD_ZERO(int fd, fd_set *fdset); FD_SET(int fd, fd_set *fdset);
FD_CLR(int fd, fd_set *fdset);
FD_ISSET(int fd, fd_set *fdset);
每次调用select前都要重新设置fd属性,FD_ISSET用来判断是哪种事件
21、Int poll(struct pollfd *fds, nfds_t nfds, int timeout);
22、EPOLLONESHOT:当一个连接套接口上有数据时交给线程处理,设置该参数,当再次有数据到达时不会触发epoll事件,防止多个线程处理同一个套接口
Epoll_wait(int epfd, struct epoll_event* events, int maxevent, int timeout);
23、Select和poll时间复杂度为n,每次遍历整个结构,epoll时间复杂度为1,底层在有事件触发时调用回调函数放在就绪队列里,最后一起拷贝到用户空间。
Select支持描述符个数cat /proc/sys/fs/file-max查看190984个
Linux 5中I/O模型
阻塞I/O、非阻塞I/O、I/O复用、信号驱动I/O、异步I/O
2014年7月26日
24、lsof -i :port命令来查询对应端口号所属程序
25、Killall + name 杀死指定名字的进程
26、多进程的调试
A、通过加一些代码,ps获取进程号,attach+进程号进入调试
B、set detach-on-fork on(调试时进入另一个进程,该进程继续运行)/off(调试时进入另一个进程,该进程挂起)
Set follow-fork-mode child/parent 调试父/子进程
Info inferiors 查看当前调试的进程*为当前调试的进程
Inferior + 1/2 切换调试的进程
2014年8月6日
27、线程同步机制posix信号量、互斥量和条件变量。pthread_join可以看做简单的线程同步方案
pthread_kill(pthread_t thread,int sig);
sig为0时,不发送信号,但会错误检查,可以检测线程是否存在。
2014年8月8日
28、任何一种语言都不能通过变量模拟二元信号量,因为高级语言不存在原子的判断变量为真或假再将其真假状态改变。
Linux 维持两套信号量。systemV和posix信号量。线程同步使用posix信号量。
处理僵尸进程:waitpid((-1,NULL, WNOHANG))>0);
T45页,163页
2014年8月18日
29、poll系统调用的原理:先注册回调函数__poll_wait,再初始化table变量(类型为struct poll_wqueues),接着拷贝用户传入的struct pollfd(其实主要是fd),然后轮流调用所有fd对应的poll(把current挂到各个fd对应的设备等待队列上)。在设备收到一条消息(网络设备)或填写完文件数据(磁盘设备)后,会唤醒设备等待队列上的进程,这时current便被唤醒了。current醒来后离开sys_poll的操作相对简单,这里就不逐行分析了
Poll底层每次在poll_wait时要将所有的文件描述符往内核空间拷贝一次,比如当描述符为1000时,拷贝不止一次,