高性能linux服务器编程—— linux C网络编程基础

首先明确大端字节序和小端字节序,看下面一段程序

#include<stdio.h>


void byteorder() {
    union {
        short value;
        char union_bytes[sizeof(short)];
    }test;
    test.value = 0x0102;
    if((test.union_bytes[0] == 1) && (test.union_bytes[1] == 2)) {
        printf("big endian\n");
    }
    else if((test.union_bytes[1] == 1) && (test.union_bytes[0] == 2)) {
        printf("little endian\n");
    }
    else printf("unknown...\n");
}

int main() {
    byteorder();
}

联合体,value和2个字节的字符串union_bytes共用一块内存, 像value中写入两个16进制的数

从union_bytes 可以判断出大端模式以及小端模式

 

下面列出linux C socket API函数

#include<sys/types.h>
#include<sys/socket.h>
int socket(int domain, int type, int protocol);
int bind(int sockfd, const struct sockaddr* my_addr, socklen_t addrlen);
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr* addr, socklen_t *addrlen);
int close(int fd);
int shutdown(int sockfd, int howto);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
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);

其中ssize_t 为无符号整数类型

 前三个函数较为简单,不再赘述。对于监听函数listen,第二个参数是backlog,表示内核监听队列的最大长度,如果数量超过了这个值,则服务器将不受理新的客户连接,下面我们用一个实验来测试一下这个最大长度和backlog有什么关系:

这里listen和accept还是有区别。

 

对于接受连接的accept函数,它从监听队列中取出一个连接,与其建立连接,而不管其处于ESTABLISHED或CLOSE_WAIT状态,更不关心任何网络变化。

 

第九章      I/O复用

  I/O复用技术是重要的提高服务器工作效率和性能的手段,Linux下实现I/O复用的系统调用主要有select、poll和epoll。

  首先我们来看一下select的函数原型和常用的宏:

#include<sys/select.h>
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
FD_ZERO(fd_set *fdset);                    //清除fdset所有位
FD_SET(int fd, fd_set* fdset);                    //设置fdset的位fd
FD_CLR(int fd, fd_set* fdset);                //清除fdset的位fd
int FD_ISSET(int fd, fd_set* fdset);            //测试fdset的位fd是否被设置

 

 epoll是Linux特有的I/O复用函数,其实现和select、poll有很大区别。epoll将用户关心的文件描述符上的事件放在内核里的一个事件表中,从而无须像select和poll那样每次调用都要重复传入文件描述符集或事件集,但是epoll需要一个额外的文件描述符来标识内核中的这个事件表。与poll不同的是,epoll如果检测到事件,就将所有就绪时间从内核时间表中复制到events指向的数组中,这样就极大提高了应用程序检索就绪文件描述符的效率,从O(n)的时间复杂度降为了O(1)。我们来看一下epoll的几个函数:

1 #include<sys/epoll.h>
2 int epoll_create(int size);
3 int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
4 int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);

epoll对于文件描述符的操作有两种模式:LT和ET,其中LT是默认模式,这种模式下其效率相当于一个稍微改进的poll,效率没有显著提高,而ET模式则是epoll的高效工作模式。对于LT模式的文件描述符,当epoll_wait检测到其上有事件发生并将此事件通知应用程序后,因公程序可以不立即处理该事件,这样当epoll_wait再次被触发,还会再向应用程序通告此事件,知道该事件被处理。而对于ET模式,当epoll_wait检测到其上有事件发生,将其通告应用程序,应用程序必须马上处理,因为后续的epoll_wait将不再向应用程序通知这一事件。可见,ET模式降低了同一个epoll事件被重复触发的次数,所以效率更高。我们用一个实例来看一下:

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值