1:linux网络API分为:socker地址API,socker基础API,网络信息API

  1,socker地址API:包含IP地址和端口(ip, port)。表示TCP通信的一端。

  2,socker基础API:创建/命名/监听socker,接收/发起链接,读写数据,获取地址信息,检测带外标记和读取/设置socker选项。sys/socket.h

  3,网络信息API:主机名和IP地址的转换,服务名和端口号的转换。netdb.h

2:socket和API的函数 和 相关知识。

  1,函数。

 IP地址转换函数
  <arpa/inet.h>
  in_addr_t inet_addr( const char* strptr ); // 格式转换:十进制字符串IP -> 网络字节序(大端)IP
  int inet_aton( const char* cp, struct in_addr* inp ); // 格式转换:如上,但将数据保存到参数inp中
  char* inet_ntoa( struct in_addr in ); // 格式转换:网络字节序(大端)IP -> 十进制字符串IP
  int inet_pton( int af, const char* src, void* dst ); // 格式转换:字符串IP地址 -> 网络字节序(大端)整数IP
  const char* inet_ntop( int af, const void* src, char* dst, socklen_t cnt ); 格式转换:网络字节序(大端)整数IP -> 字符串IP地址
  // inet_ntoa函数不可重入。
  // inet_ntop返回目标储存单元的地址。
创建socket
  <sys/types.h> <sys/socket.h>
  int socket( int domain, int type, int protocol );
  // 1 参数domain:使用的底层协议族。
  // 2 参数type:指定服务类型。SOCK_STREAM(TCP) SOCK_UGRAM(UDP)
  // 3 参数protocol:指定具体协议。一般默认为0.(前面参数已经确定了协议)
  // 4 返回:socket文件描述符。失败-1,设置errno
命名socket
  <sys/types.h> <sys/socket.h>
  int bind( int sockfd, const struct sockaddr* my_addr, socklen_t addrlen );
  // 1 参数addrlen:socket地址长度。
  // 2 返回:成功0,失败-1,设置errno
监听socket
  <sys/socket.h>
  int listen( int sockfd, int backlog );
  // 1 参数sockfd:指定被监听socket
  // 2 参数backlog:监听队列最大长度。典型值:5
接收链接。
  <sys/types.h> <sys/socket.h>
  int accept( int sockfd, struct sockaddr* addr, socklen_t* addrlen );
  // 1 参数sockfd:执行过listen的socket。
  // 2 参数addr:被接受链接的远程socket地址。
  // 3 参数addrlen:地址长度。
  // 4 返回:成功新的链接socket,失败-1设置errno
  // 5 accept只从监听队列取出连接,并不检测网络状态。
发起链接
  <sys/types.h> <sys/socket.h>
  int connect( int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen );
  // 1 参数sockfd:由socket系统调用返回一个socket
  // 2 参数serv_addr:服务器监听的socket地址。
  // 3 返回:成功0,失败-1设置errno
关闭连接
  <unistd.h>
  int close( int fd );
  // 1 不会立即关闭,只是将引用减一。只有引用为0时才会真正关闭。
  <sys/socket.h>
  int shutdown( int sockfd, int howto );
  // 1 立即关闭连接。
  // 2 参数howto:决定函数的行为。SHUT_RD/WR/RDWR:可以分别控制读写关闭。
  // 3 返回:成功0,失败-1设errno
TCP数据读写。
  <sys/types.h> <sys/socket.h>
  ssize_t recv( int sockfd, void* buf, size_t len, int flags ); // 返回:实际读取到的数据长度。失败-1errno
  ssize_t send( int sockfd, const void* buf, size_t len, int flags ); // 返回:实际写入的数据长度。失败-1reeno
  // 1 参数buf,len:缓冲区的地址和大小。
  // 2 参数flags:数据收发额外控制。通常设0.
UDP数据读写。
  <sys/types.h> <sys/socket.h>
  ssize_t recvfrom( int sockfd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t *addrlen );
  ssize_t sendto( int sockfd, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t *addrlen );
  // 1 参数src/dest_addr:确定发送/接收端地址。(因UDP没有连接概念)
  // 2 这两个函数同样可以应用于TCP读写数据。
通用数据读写函数。
  <sys/socket.h>
  ssize_t recvmsg( int sockfd, struct msghdr* msg, int flags );
  ssize_t sendmsg( int sockfd, struct msghdr* msg, int flags );
  struct msghdr{
    void* msg_name; // socket 地址
    socklen_t msg_namelen;    // 地址长度
    struct iovec* msg_iov; // 分散的内存块
    int msg_iovlen; // 分散内存块的数量
    void* msg_control;      // 辅助数据地址
    socklen_t msg_controllen; // 辅助数据大小
    int msg_flags; // 保存函数flag参数
  }
确定下一个数据是否时带外数据。
  <sys/socket.h>
  int sockatmark( int sockfd ); // 返回:带外1,否则0
获取地址信息。
  <sys/socket.h>
  int getsockname( int sockfd, struct sockaddr* address, socklen_t* address_len ); // 本端
  int getpeername( int sockfd, struct sockaddr* address, socklen_t* address_len ); // 远端
  // 1 返回:成功0,失败-1errno
获取/设置socket选项
  <sys/socket.h>
  int getsockopt( int sockfd, int level, int option_name, void* option_value, socklen_t* restrict option_len );
  int setsockopt( int sockfd, int level, int option_name, const void* option_value, socklen_t* restrict option_len );
  // 1 参数level:具体协议选项。
  // 2 返回:成功0,失败-1errno。 // 此后为网络信息API
获取主机完整信息。
  <netdb.h>
  struct hostent* gethostbyname( const char* name ); // 通过主机名称获取
  struct hostent* gethostbyaddr( const void* addr, size_t len, int type ); //通过IP地址获取
  // 1 参数type:IP地址的类型。
  // 2 返回:主机信息。
获取服务的完整信息。
  <netdb.h>
  struct servent* getservbyname( const char* name, const char* proto ); // 通过名字获取
  struct servent* getservbyport( int port, const char* proto ); // 通过端口号获取
  // 1 参数proto:确定服务类型:UDP/TCP
获取主机和服务的综合函数。
  int getaddrinfo( const char* hostname, const char* service, const struct addrinfo* hints, struct addrinfo** result );
  int getnameinfo( const struct sockaddr* sockaddr, socklen_t addrlen, char* host, socklen_t hostlen, char* serv, socklen_t servlen, int flags );

  2,88-94在完成初版IM时,需要进行测试。

3:高级IO(高编已由函数省略)

  1,函数

 两个文件描述符之间直接传递数据
  ssize_t sendfile( int out_fd, int in_fd, off_t* offset, size_t count );
  // 1 参数count:传输字节数
  // 2 返回:成功返回传输字节数,失败-1errno
  // 3 in_fd:必须时真实文件,out_fd:必须是socket
两个文件描述符之间移动数据。零copy操作
  ssize_t splice( int fd_in, loff_t* off_in, int fd_out, loff_t* off_out, size_t len, unsigned int flags ); // 具体需要再了解和使用。
两个管道文件描述符之间复制数据。零copy操作
  ssize_t tee( int fd_in, int fd_out, size_t len, unsigned int flags );

4:linux服务程序规范。

  1,函数。

 和日志进程通信。
  <syslog.h>
  void syslog( int priority, const char* message );
  // 1 参数priority:设置值与日志级别按位与。
2 设置日志进程的输出方式。
  void openlog( const char* ident, int logopt, int facility );
  // 1 参数ident:添加到日志消息的日期和时间之后。
  // 2 参数facility:用来修改syslog函数中的默认值。
3 设置日志进程的掩码。(设置屏蔽信息)
  int setlogmask( int maskpri );
4 关闭日志功能。
  void closelog();
5 使进程称为后台进程:
  <unistd.h>
  int daemon( int nochdir, int noclose );
  // 1 参数nochdir:传0,则工作目录为根目录/。否则不变。
  // 2 参数noclose:传0,则被重定向为/dev/null。
  // 3 返回:成功0,失败-1errno。

  2,基本规范。

    1)一般以后台进程形式运行。后台进程又称为守护进程。

    2)通常有一套日志系统。至少能输出日志到文件。

    3)一般以某个专门的非root身份运行。

    4)通常时可配置的。

    5)启动时,会生成一个PID文件并存入/var/run目录中。

    6)通常需要考虑系统资源和限制。

  3,日志进程:rsyslogd。

    1)能够接收 用户/内核 的日志。

  4,ps命令可查看进程、进程组和会话之间的关系。

5:高性能服务器框架。

  1,函数。

  2,零散细节。

    1)客户连接请求时随即到达的异步事件,服务器需要使用某种IO模型来监听。

    2)服务器可以解构成三个主要模块:IO处理单元,逻辑单元,储存单元。

    3)服务器基本模块的功能描述。

模块 单个服务器程序 服务器机群
IO处理单元 处理客户连接,读写网络数据 作为接入服务器,实现负载均衡
逻辑单元 业务进程或线程 逻辑服务器
网络储存单元 本地数据库、文件或缓存。 数据库服务器
请求队列 各单元之间的通信方式。 各服务器之间的永久TCP连接

    4)IO服用函数本身时阻塞的,它们能提高程序效率的原因:它们具有同时监听多个IO事件的能力。

    5)同步IO向应用程序通知的是IO就绪事件,异步IO向应用程序通知的是IO完成事件。

    6)服务器程序通常需要处理三类事件:IO事件,信号和定时事件。

    7)如果程序是计算密集型, 并发没有任何优势。但如果是IO密集型,并发就会有意义。因为IO速度比CPU缓慢。

    8)并发模式中,同步指程序完全按照代码序列顺序执行(用于处理客户逻辑),异步指程序执行需要由系统事件来驱动(用于处理IO)。

    9)主线程向工作线程发送scoket最简单的方式:往管道中写数据。

    10)池是一组资源的集合。这组资源在服务器启动之初就被完全创建好并初始化。常见的有:内存池,线程池,进程池和连接池。

    11)高性能服务器应该避免不必要的数据复制。(避免数据复制,共享内存是最块的方式,但不一定是最好的。)

    12)并发程序必须考虑上下文切换的开销。

    13)尽量减少锁的开销。

  3,P2P模式:peer to peer。

    1)P2P模式时,主机之间很难相互发现。

  4,reactoer模式。

    1)它要求主线程(IO处理单元)只负责监听文件描述符是否有事件发生,有的话就立即将该事件通知工作线程(逻辑单元)。

    2)特点:主线程只确定有请求,工作线程针对具体事件类型针对处理。

  5,proactor模式:它将所有IO操作都交给主线程和内核来处理。工作线程仅仅负责业务逻辑。。

  6,半同步/半反应堆模式:主线程用来监听IO,并发送请求到请求队列。然后工作线程竞争抢夺处理权限。

    1)主线程和工作线程共享请求队列。需要锁来保证读写,消耗CPU

    2)每个工作线程同一时间只能处理一个客户请求。

  7,leader/follewer模式:leader监听scoket。当有新请求时,leader去处理请求,并从follower中推选新leader。

    1)需要包含几个组件:句柄集,线程集,事件处理器,具体事件处理器。

6:IO复用

  1,函数。

 epoll系列:linux特有的IO复用函数。
  <sys/epoll.h>
  int epoll_create( int size ); // 创建一个描述符(标识事件表)
  int epoll_ctl( int epfd, int op, int fd, struct epoll_event *event ); // 对 事件表 进行操作(添加,修改,删除注册事件)。
  int epoll_wait( int epfd, struct epoll_event* events, int maxevents, int timeout ); // 等待事件。
2

  2,零散细节。

    1)IO复用虽然能同时监听多个文件描述符,但它本身是阻塞的。

    2)epoll系列有两种模式:LT和ET。ET是相对高效的模式。

    3)ET模式的文件描述符都应该是非阻塞的。(如果是阻塞的,可能会一直阻塞下去)

    4)EPOLLONESHOT事件:使事件只能触发一次。若需要再次触发,需要重置。可以防止重复读写。

  3,select,poll,epoll的区别

系统调用 select poll epoll
事件集合 用户通过三个参数分别传入可读,可写和异常事件。内核通过这些参数在线修改就绪事件。每次调用都会重读 统一处理所有事件类型。需要一个事件集。用户通过pollfd.event传入事件。内核通过修改pollfd.event反馈就绪事件。 内核通过事件表直接管理所有事件。无需反复传入事件。epoll_wait仅用来反馈就绪事件(不需要多余判断)
应用程序索引就绪文件描述符的时间复杂度 n n

1

最大支持文件描述符数 一般有最大值限制 65535 65535
工作模式 LT LT LT/ET
内核实现和工作效率 轮询方式检测就绪事件 轮询 回调方式检测就绪事件。

7:信号。

  1,函数

  2,零散细节。

    1)服务器程序必须处理(至少能忽略)一些常见信号。以避免异常终止。

    2)信号是一种异步事件:信号处理函数和程序的主循环是两条不同的执行路线。所以信号需要尽快完成。典型的解决方案:信号仅提供信号,具体处理尽量方在主循环中。

8:时间堆:将所有定时器超时时间最小的一个定时器的超时值作为心搏间隔。

9:高性能IO框架库。

  1,常见框架:ACE,ASIO,Libevent。

  2,linux服务器程序必须处理三类事件:IO,信号和定时事件。但需要考虑三个问题

    1)统一事件源。需要统一管理三类事件。一般方法为:利用IO复用系统调用来管理所有事件。

    2)可移植性。

    3)对并发编程的支持。

  3,IO框架库以库函数的形式,封装了较为底层的系统调用,给应用程序提供了一组更便于使用的接口。

  4,Libevent框架库。

    1)跨平台支持,拥有统一事件源,线程安全,基于Reactor模式。

    2)官方网站:libevent.org

  5,P240,需要执行代码确认。

10:多线程编程。

  1,线程实现方式:完全在用户空间实现,完全由内核调度和双层调度。

    1)完全在用户空间实现优点:创建和调度线程无需内核的干预,速度很快。创建多各线程对系统性能没有太大影响。但无法在多CPU情况下使用。

    2)内核调度:和用户空间完全相反。

    3)双层调度:上两种模式的混合体。

11:进程池和线程池。

  1,线程池中的线程数量应该和CPU数差不多。

  2,进程之间(有关联进程)传递数据最简单的方法是管道。

12:服务器调制,调试和测试。

  1,linux平台的一个优秀特性是内核微调:可以通过修改文件的方式来调正内核参数。

  2,调试方法:tcpdump抓包看数据,或者gdb。

  3,linux对应用程序能打开的最大文件描述符数量有两个层次的限制:用户级限制和系统级限制。

  4,gdb调试多进程的两个简单方法:

    1)找到PID,然后使用attach添加到gdb中。

    2)set follow-fork mode(parent or child)

  5,gdb调试多线程的方法。

    1)info threads:显示当前可调试的所有线程。

    2)threadID:调试ID线程

    3)set scheduler-locking(off|on|step):off所有线程执行,on只有当前线程执行,step单步调试时,只有当前线程会执行。

  6,压力测试:IO复用,多线程,多进程并发编程等方法(不懂- -)。

13:常用工具。

  1,tcpdump:经典的网络抓包工具

  2,lsof:列出当前系统打开的文件描述符的工具。

  3,nc:用来快速构建网络连接。

    1)服务器方式运行时:监听某个端口并接收客户端连接。

    2)客户端方式运行时:可以向服务器发起连接并收发数据。

    3)所以可以用来调试客户端和服务器。

  4,strace:测试服务器性能的工具。

    1)跟踪程序运行过程中执行的系统调用和接收到的信号,并将系统调用名、参数、返回值及信号名数处到标准输出或指定文件。

  5,netstat:网络信息统计工具。

    1)可以打印本地网卡接口上的全部连接、路由表信息、网卡接口信息。

  6,ifstat:interface statistics。简单的网络流量检测工具。

  7,mpstat:multi-processor statistics。能实时监测多处理器系统上的每个CPU的使用情况。

study notes: high performance linux server programming的更多相关文章

  1. Machine Learning Algorithms Study Notes(2)--Supervised Learning

    Machine Learning Algorithms Study Notes 高雪松 @雪松Cedro Microsoft MVP 本系列文章是Andrew Ng 在斯坦福的机器学习课程 CS 22 ...

  2. Machine Learning Algorithms Study Notes(1)--Introduction

    Machine Learning Algorithms Study Notes 高雪松 @雪松Cedro Microsoft MVP 目 录 1    Introduction    1 1.1    ...

  3. 在Azure上实现Linux Server故障转移

    要充分利用公有云的弹性扩展和高可用, 首先要在应用系统层面支持横向扩展(scale out),这个说起来很容易,或者说对新开发的应用系统而言已经成为标配.但是对已有的.老旧的应用系统来说,这就比较困难 ...

  4. HowTo: Linux Server Change OR Setup The Timezone

    Method 1 #tzselect # select timezone e.g. Asia/Shanghai#echo 'Asia/Shanghai' > /etc/timezone # se ...

  5. Machine Learning Algorithms Study Notes(3)--Learning Theory

    Machine Learning Algorithms Study Notes 高雪松 @雪松Cedro Microsoft MVP 本系列文章是Andrew Ng 在斯坦福的机器学习课程 CS 22 ...

  6. 在Oracle Linux Server release 6.4下配置ocfs2文件系统

    ① 安装ocfs-tools-1.8 如果是使用RedHat Enterprise Linux 6.4,也可以安装ocfs-tools-1.8的,只是要插入Oracle Linux Server re ...

  7. Linux Server

    Linux Server CentOS 6.3下配置iSCSI网络存储 摘要: 一.简介iSCSI(internet SCSI)技术由IBM公司研究开发,是一个供硬件设备使用的.可以在IP协议的上层运 ...

  8. ORACLE Install (10g r2) FOR Red Hat Enterprise Linux Server release 5.5 (64 bit) (转)

    OS Info----------# cat /etc/redhat-releaseRed Hat Enterprise Linux Server release 5.5 (Tikanga)# cat ...

  9. Red Hat Enterprise Linux Server(RHEL) yum安装软件时This system is not registered with RHN. RHN support will be disabled. 的解决方法(转)

    新安装了redhat6.5.安装后,登录系统,使用yum update 更新系统.提示: This system is not registered to Red Hat Subscription M ...

随机推荐

  1. CGRect包含交错,边缘,中心的检测

    CGRectContainsPoint函数        判断给定的点是否被一个CGRect包含,可以用CGRectContainsPoint函数 BOOL contains = CGRectCont ...

  2. 有向强连通分支Tarjan算法

    本文转载自:http://blog.csdn.net/xinghongduo/article/details/6195337 说到以Tarjan命名的算法,我们经常提到的有3个,其中就包括本文所介绍的 ...

  3. netCDF

    NetCDF started in 1989 most used in geoscience community array-oriented self-describing header, desc ...

  4. PHP函数参数的引用传递和值传递

    函数的参数传递有两种方式 1,值传递 常见的 test($param)  方式就是值传递,在函数内部修改$param,不会影响外部变量$param的值 2,引用传递 参数是引用传递的方式,此时函数内部 ...

  5. Windows,Linux换行知识

    换行符在写文件的时候用得上 Linux: "\n"Windows: "\r\n" 注意:换行符一定要加上双引号,单引号是没有用的.

  6. centos minimal 安装无法自定义分区

    安装了太多版本的linux,最后还是决定安装CentOS的minimal版本: 安装的时候发现,没办法自定义分区,经查确实在命令行界面下安装是没有自定义分区的. 但是不管怎么安装都是没有图形介面,最后 ...

  7. information_schema.collations 学习

    information_schema.collations 表中的每一行对应一个排序规则 1.information_schema.collations 表中学用列: 1.id :排序规则的ID 2. ...

  8. JS笔试题

    JS 引用相关题目 以下代码输出什么? 为什么? var a = {n:1}; var b = a; a = {n:2}; a.x = a ; console.log(a.x); console.lo ...

  9. MongoDB insert performance rapidly dropping

    http://dba.stackexchange.com/questions/65554/mongodb-insert-performance-rapidly-dropping http://www. ...

  10. 优盘文件系统(FOR C)

    优盘上的数据按照其不同的特点和作用大致可分为5 部分:MBR 区.DBR 区.FAT 区.FDT区和DATA 区. 主引导记录(MBR) 绝对扇区号为:MBR_LBA=0x00000000 处是主引导 ...