cpp后台资料

搞了很久搜索了,可是做的很多都是业务逻辑和PM的需求,也没有高大上的技术。感觉随着开源项目的成熟技术的门槛在逐渐的降低,曾经高大上的技术已经渐渐变得没什么门槛了。。。(记得脉脉上看到一句很好玩的话,程序员是一个高大上的职业,直到JAVA语言的出现。。。)不过我也还是认真总结和实践了一些深入的技术,在做业务的时候也有一些积累的吧。总的来说C++后台开发深入一些的有网络编程、多线程编程、进程/线程同步/通信和调度、动态链接库使用、常用的框架的深入阅读和理解、常用的运行时程序问题排查(内存泄露、无法响应新的请求)、分布式系统的使用、高并发系统优化。所以本文一共分为如下十一个部分:

一、网络编程

二、多线程编程

三、多进程/线程同步/通信/调度

四、动态链接库使用

五、开源框架的深入阅读和理解(以thrift为例)

六、常用运行时程序问题排查

七、分布式系统问题

八、高并发系统的优化

九、代码风格和设计模式

十、C++语言的新特性

十一、Linux内核知识


一、网络编程:

             1. TCP与UDP:
                      a. TCP与UDP报头
                          1). TCP报头(最少20个字节):源端口、目的端口、序号、确认号、数据偏移、ACK、RST、SYN、FIN、窗口、校检和、紧急指针、选项、填充。
                          2). UDP报头:(8个字节)预案端口、目的端口、用户数据包长度、校检和、数据。
                      b. TCP与UDP的区别
                          1). TCP是面向连接的服务,有拥塞控制和超时重传,因此有滑动窗口。
                          2). UDP是非面向连接的服务,支持一对多通信,如广播。

             2. TCP 3次握手、4次挥手过程:

                               
                            a. TCP三次握手、四次挥手漏洞分析,天网如何使用TCP协议中断翻墙协议访问。
                                    为什么要进行三次握手?因为双方要交换序列号和窗口大小,发送方确认接收方接收到了syn请求,防止出现死锁。
                                   TCP三次握手的漏洞,SYN FLOOD攻击:客户端不停的伪造IP来给服务端发起请求,服务端对每个syn都要分配一个TCB,通常每个TCB至少280个字节。应对:syn cookie技术,使用双方通信信息、MSS、时间等计算,看看与对方回报文中的sequence number是否相同。
                                   TCP四次挥手?因为TCP连接有个半连接状态,假设AB要释放,那么A发送了一个释放请求给B,B立即回复确认。但在此之间B发送的数据A依然需要接受,B需要回复给A它不再发送数据了。
                                   为什么TIME_WAIT需要有2MSL的时间?为了避免最后一个ACK没有被接收到,预留重发时间。

                  3.  多路IO复用模型:
                          a. 阻塞、非阻塞:
应用程序的调用是否立即返回!
                          b. 异步、同步:
数据拷贝的时候进程是否阻塞!
                          c. select、poll、epoll
                              1). 三种IO复用模型对比:
                                        select支持最大打开文件数目有限(一般select使用32个32位整数作为文件描述符集)、用户态数据需要拷贝到内核态、每次都需要线性遍历每个FD,速度太慢; poll最大打开fd数目不限;epoll克服了上面所有的缺点,但是如果每个连接都是活跃的,效率也不高。
                              2). select:
                                        select执行流程:
                                        a). 
设置maxfd,将fd加入select监控集,使用一个array保存放到select监控集中的d,一是用于在select返回后,array作为源数据和fdset进行fd_isset判断。二是在select返回后会把以前加入的但并无事件发生的fd清空,则每次开始select都要从array取得fd逐一加入。(select模型必须在select前循环array(加fd,取maxfd),返回后循环array。

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
参数:    

        sockfd: socket 函数返回的套接字描述符
        readfds : 读描述符集合
        writefds: 写描述符集合
        errorfds: 错误描述符集合
        timeout:  超时
返回值
        成功:返回值 0:无 >0:描述符就绪的总位数
        错误:返回INVALID_SOCKET(-1)

示例:

[cpp]  view plain  copy
  1. <span style="font-size:12px;">/* 实现功能:通过select处理多个socket 
  2.  * 监听一个端口,监听到有链接时,添加到select的w. 
  3.  */  
  4. #include "select.h"  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <sys/socket.h>  
  8. #include <sys/select.h>  
  9. #include <sys/time.h>  
  10. #include <netinet/in.h>  
  11.   
  12. typedef struct _CLIENT{  
  13.     int fd;  
  14.     struct sockaddr_in addr; /* client's address information */  
  15. } CLIENT;  
  16.   
  17. #define MYPORT 59000  
  18.   
  19. //最多处理的connect  
  20. #define BACKLOG 5  
  21. //最多处理的connect  
  22. CLIENT client[BACKLOG];  
  23.   
  24. //当前的连接数  
  25. int currentClient = 0;   
  26.   
  27. //数据接受 buf  
  28. #define REVLEN 10  
  29. char recvBuf[REVLEN];  
  30. //显示当前的connection  
  31. void showClient();  
  32.   
  33. int main()  
  34. {  
  35.     int i, ret, sinSize;  
  36.     int recvLen = 0;  
  37.     fd_set readfds, writefds;  
  38.     int sockListen, sockSvr, sockMax;  
  39.     struct timeval timeout;  
  40.     struct sockaddr_in server_addr;  
  41.     struct sockaddr_in client_addr;  
  42.   
  43.     for(i=0; i<BACKLOG; i++)  
  44.     {  
  45.         client[i].fd = -1;  
  46.     }  
  47.   
  48.     //socket  
  49.     if((sockListen=socket(AF_INET, SOCK_STREAM, 0)) < 0)  
  50.     {  
  51.         printf("socket error\n");  
  52.         return -1;  
  53.     }  
  54.   
  55.     bzero(&server_addr, sizeof(server_addr));  
  56.     server_addr.sin_family  =  AF_INET;  
  57.     server_addr.sin_port = htons(MYPORT);  
  58.     server_addr.sin_addr.s_addr  =  htonl(INADDR_ANY);   
  59.   
  60.     //bind  
  61.     if(bind(sockListen, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)  
  62.     {  
  63.         printf("bind error\n");  
  64.         return -1;  
  65.     }  
  66.   
  67.     //listen  
  68.     if(listen(sockListen, 5) < 0)  
  69.     {  
  70.         printf("listen error\n");  
  71.         return -1;  
  72.     }  
  73.   
  74.     for(i=0; i<BACKLOG; i++)  
  75.     {  
  76.         client[i].fd = -1;  
  77.     }  
  78.   
  79.     //select  
  80.     while(1)  
  81.     {  
  82.         FD_ZERO(&readfds);  
  83.         FD_SET(sockListen, &readfds);  
  84.         sockMax = sockListen;  
  85.       
  86.         //加入client  
  87.         for(i=0; i<BACKLOG; i++)  
  88.         {  
  89.             if(client[i].fd >0)  
  90.             {  
  91.                 FD_SET(client[i].fd, &readfds);  
  92.                 if(sockMax<client[i].fd)   
  93.                     sockMax = client[i].fd;  
  94.             }  
  95.         }  
  96.           
  97.         timeout.tv_sec=3;                  
  98.         timeout.tv_usec=0;  
  99.         //select  
  100.         ret = select((int)sockMax+1, &readfds, NULL, NULL, &timeout);  
  101.         if(ret < 0)  
  102.         {  
  103.             printf("select error\n");  
  104.             break;  
  105.         }  
  106.         else if(ret == 0)  
  107.         {  
  108.             printf("timeout ...\n");  
  109.             continue;  
  110.         }  
  111.         printf("test111\n");  
  112.       
  113.         //读取数据  
  114.         for(i=0; i<BACKLOG; i++)  
  115.         {  
  116.             if(client[i].fd>0 && FD_ISSET(client[i].fd, &readfds))  
  117.             {  
  118.                 if(recvLen != REVLEN)  
  119.                 {  
  120.                     while(1)  
  121.                     {  
  122.                         //recv数据  
  123.                         ret = recv(client[i].fd, (char *)recvBuf+recvLen, REVLEN-recvLen, 0);  
  124.                         if(ret == 0)  
  125.                         {  
  126.                             client[i].fd = -1;  
  127.                             recvLen = 0;  
  128.                             break;  
  129.                         }  
  130.                         else if(ret < 0)  
  131.                         {  
  132.                             client[i].fd = -1;  
  133.                             recvLen = 0;  
  134.                             break;  
  135.                         }  
  136.                         //数据接受正常  
  137.                         recvLen = recvLen+ret;  
  138.                         if(recvLen<REVLEN)  
  139.                         {  
  140.                             continue;  
  141.                         }  
  142.                         else  
  143.                         {  
  144.                             //数据接受完毕  
  145.                             printf("%s, buf = %s\n", inet_ntoa(client[i].addr.sin_addr) , recvBuf);  
  146.                             //close(client[i].fd);  
  147.                             //client[i].fd = -1;  
  148.                             recvLen = 0;  
  149.                             break;  
  150.                         }  
  151.                     }  
  152.                 }  
  153.             }  
  154.         }  
  155.       
  156.         //如果可读  
  157.         if(FD_ISSET(sockListen, &readfds))  
  158.         {  
  159.             printf("isset\n");  
  160.             sockSvr = accept(sockListen, NULL, NULL);//(struct sockaddr*)&client_addr  
  161.           
  162.             if(sockSvr == -1)  
  163.             {  
  164.                 printf("accpet error\n");  
  165.             }  
  166.             else  
  167.             {  
  168.                 currentClient++;  
  169.             }  
  170.           
  171.             for(i=0; i<BACKLOG; i++)  
  172.             {  
  173.                 if(client[i].fd < 0)  
  174.                 {  
  175.                     client[i].fd = sockSvr;  
  176.                     client[i].addr = client_addr;  
  177.                     printf("You got a connection from %s \n",inet_ntoa(client[i].addr.sin_addr) );  
  178.                     break;  
  179.                 }  
  180.             }  
  181.             //close(sockListen);  
  182.         }  
  183.     }  
  184.   
  185.     printf("test\n");  
  186.     return 0;  
  187. }  
  188.   
  189. //显示当前的connection  
  190. void showClient()  
  191. {  
  192.     int i;  
  193.     printf("client count = %d\n", currentClient);  
  194.   
  195.     for(i=0; i<BACKLOG; i++)  
  196.     {  
  197.         printf("[%d] = %d", i, client[i].fd);  
  198.     }  
  199.     printf("\n");  
  200. }</span>  


                                        b).  int poll(struct pollfd *fds, nfds_t nfds, int timeout);

参数:
    fds
:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符;每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select()函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况;

    nfds:nfds_t类型的参数,用于标记数组fds中的结构体元素的总数量;

    timeout:是poll函数调用阻塞的时间,单位:毫秒;

返回值:
    >0:数组fds中准备好读、写或出错状态的那些socket描述符的总数量;

    ==0:数组fds中没有任何socket描述符准备好读、写,或出错;此时poll超时,超时时间是timeout毫秒;换句话说,如果所检测的       socket描述符上没有任何事件发生的话,那么poll()函数会阻塞timeout所指定的毫秒时间长度之后返回,如果timeout==0,那么poll() 函数立即返回而不阻塞,如果timeout==INFTIM,那么poll() 函数会一直阻塞下去,直到所检测的socket描述符上的感兴趣的事件发生是才返回,如果感兴趣的事件永远不发生,那么poll()就会永远阻塞下去;

     -1: poll函数调用失败,同时会自动设置全局变量errno;
示例:

[cpp]  view plain  copy
  1. <span style="font-size:12px;">/* 实现功能:通过poll, 处理多个socket 
  2.  * 监听一个端口,监听到有链接时,添加到poll. 
  3.  */  
  4. #include "select.h"  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <string.h>  
  8. #include <sys/socket.h>  
  9. #include <poll.h>  
  10. #include <sys/time.h>  
  11. #include <netinet/in.h>  
  12.   
  13. typedef struct _CLIENT{  
  14.     int fd;  
  15.     struct sockaddr_in addr; /* client's address information */  
  16. } CLIENT;  
  17.   
  18. #define MYPORT 59000  
  19.   
  20. //最多处理的connect  
  21. #define BACKLOG 5  
  22.   
  23. //当前的连接数  
  24. int currentClient = 0;   
  25.   
  26. //数据接受 buf  
  27. #define REVLEN 10  
  28. char recvBuf[REVLEN];  
  29.   
  30. #define OPEN_MAX 1024  
  31.   
  32. int main()  
  33. {  
  34.     int i, ret, sinSize;  
  35.     int recvLen = 0;  
  36.     fd_set readfds, writefds;  
  37.     int sockListen, sockSvr, sockMax;  
  38.     int timeout;  
  39.     struct sockaddr_in server_addr;  
  40.     struct sockaddr_in client_addr;  
  41.   
  42.     struct pollfd clientfd[OPEN_MAX];  
  43.   
  44.   
  45.     //socket  
  46.     if((sockListen=socket(AF_INET, SOCK_STREAM, 0)) < 0)  
  47.     {  
  48.         printf("socket error\n");  
  49.         return -1;  
  50.     }  
  51.   
  52.     bzero(&server_addr, sizeof(server_addr));  
  53.     server_addr.sin_family  =  AF_INET;  
  54.     server_addr.sin_port = htons(MYPORT);  
  55.     server_addr.sin_addr.s_addr  =  htonl(INADDR_ANY);   
  56.   
  57.     //bind  
  58.     if(bind(sockListen, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)  
  59.     {  
  60.         printf("bind error\n");  
  61.         return -1;  
  62.     }  
  63.   
  64.     //listen  
  65.     if(listen(sockListen, 5) < 0)  
  66.     {  
  67.         printf("listen error\n");  
  68.         return -1;  
  69.     }  
  70.   
  71.   
  72.     //clientfd 初始化  
  73.     clientfd[0].fd = sockListen;  
  74.     clientfd[0].events = POLLIN; //POLLRDNORM;  
  75.     sockMax = 0;  
  76.     for(i=1; i<OPEN_MAX; i++)  
  77.     {  
  78.         clientfd[i].fd = -1;  
  79.     }  
  80.   
  81.     //select  
  82.     while(1)  
  83.     {  
  84.         timeout=3000;                  
  85.         //select  
  86.         ret = poll(clientfd, sockMax+1, timeout);  
  87.       
  88.         if(ret < 0)  
  89.         {  
  90.             printf("select error\n");  
  91.             break;  
  92.         }  
  93.         else if(ret == 0)  
  94.         {  
  95.             printf("timeout ...\n");  
  96.             continue;  
  97.         }  
  98.       
  99.         if (clientfd[0].revents & POLLIN)//POLLRDNORM  
  100.         {  
  101.             sockSvr = accept(sockListen, NULL, NULL);//(struct sockaddr*)&client_addr  
  102.           
  103.             if(sockSvr == -1)  
  104.             {  
  105.                 printf("accpet error\n");  
  106.             }  
  107.             else  
  108.             {  
  109.                 currentClient++;  
  110.             }  
  111.           
  112.             for(i=0; i<OPEN_MAX; i++)  
  113.             {  
  114.                 if(clientfd[i].fd<0)  
  115.                 {  
  116.                     clientfd[i].fd = sockSvr;  
  117.                     break;  
  118.                 }  
  119.             }  
  120.             if(i==OPEN_MAX)  
  121.             {  
  122.                 printf("too many connects\n");  
  123.                 return -1;  
  124.             }  
  125.             clientfd[i].events = POLLIN;//POLLRDNORM;  
  126.             if(i>sockMax)  
  127.                 sockMax = i;  
  128.         }  
  129.       
  130.         //读取数据  
  131.         for(i=1; i<=sockMax; i++)  
  132.         {  
  133.             if(clientfd[i].fd < 0)  
  134.                 continue;  
  135.           
  136.             if (clientfd[i].revents & (POLLIN | POLLERR))//POLLRDNORM  
  137.             {  
  138.                 if(recvLen != REVLEN)  
  139.                 {  
  140.                     while(1)  
  141.                     {  
  142.                         //recv数据  
  143.                         ret = recv(clientfd[i].fd, (char *)recvBuf+recvLen, REVLEN-recvLen, 0);  
  144.                         if(ret == 0)  
  145.                         {  
  146.                             clientfd[i].fd = -1;  
  147.                             recvLen = 0;  
  148.                             break;  
  149.                         }  
  150.                         else if(ret < 0)  
  151.                         {  
  152.                             clientfd[i].fd = -1;  
  153.                             recvLen = 0;  
  154.                             break;  
  155.                         }  
  156.                         //数据接受正常  
  157.                         recvLen = recvLen+ret;  
  158.                         if(recvLen<REVLEN)  
  159.                         {  
  160.                             continue;  
  161.                         }  
  162.                         else  
  163.                         {  
  164.                             //数据接受完毕  
  165.                             printf("buf = %s\n",  recvBuf);  
  166.                             //close(client[i].fd);  
  167.                             //client[i].fd = -1;  
  168.                             recvLen = 0;  
  169.                             break;  
  170.                         }  
  171.                     }  
  172.                 }  
  173.             }  
  174.         }  
  175.     }  
  176.   
  177.     return 0;  
  178. }</span>  

                                        c).  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);

epoll_create生成一个 Epoll 专用的文件描述符,其实是申请一个内核空间,用来存放你想关注的 socket fd 上是否发生以及发生了什么事件。 size 就是你在这个 Epoll fd 上能关注的最大 socket fd 数,大小自定,只要内存足够。
epoll_ctl控制某个 Epoll 文件描述符上的事件:注册、修改、删除。其中参数 epfd 是 epoll_create() 创建 Epoll 专用的文件描述符。相对于 select 模型中的 FD_SET 和 FD_CLR 宏。op:EPOLL_CTL_ADD  Register the target file descriptor fd on the epoll instance, EPOLL_CTL_MOD Change the event event associated with the target file descriptor fd, EPOLL_CTL_DEL Remove  (deregister)  the  target  file descriptor fd from the epoll instance。

[cpp]  view plain  copy
  1. <span style="font-size:12px;">/* 实现功能:通过epoll, 处理多个socket 
  2.  * 监听一个端口,监听到有链接时,添加到epoll_event 
  3.  */  
  4. #include "select.h"  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <string.h>  
  8. #include <sys/socket.h>  
  9. #include <poll.h>  
  10. #include <sys/epoll.h>  
  11. #include <sys/time.h>  
  12. #include <netinet/in.h>  
  13. typedef struct _CLIENT{  
  14.     int fd;  
  15.     struct sockaddr_in addr; /* client's address information */  
  16. } CLIENT;  
  17. #define MYPORT 59000  
  18. //最多处理的connect  
  19. #define MAX_EVENTS 500  
  20. //当前的连接数  
  21. int currentClient = 0;   
  22. //数据接受 buf  
  23. #define REVLEN 10  
  24. char recvBuf[REVLEN];  
  25. //EPOLL相关   
  26. //epoll描述符  
  27. int epollfd;  
  28. //事件数组  
  29. struct epoll_event eventList[MAX_EVENTS];  
  30. void AcceptConn(int srvfd);  
  31. void RecvData(int fd);  
  32.   
  33. int main()  
  34. {  
  35.     int i, ret, sinSize;  
  36.     int recvLen = 0;  
  37.     fd_set readfds, writefds;  
  38.     int sockListen, sockSvr, sockMax;  
  39.     int timeout;  
  40.     struct sockaddr_in server_addr;  
  41.     struct sockaddr_in client_addr;  
  42.     //socket  
  43.     if((sockListen=socket(AF_INET, SOCK_STREAM, 0)) < 0)  
  44.     {  
  45.         printf("socket error\n");  
  46.         return -1;  
  47.     }  
  48.     bzero(&server_addr, sizeof(server_addr));  
  49.     server_addr.sin_family  =  AF_INET;  
  50.     server_addr.sin_port = htons(MYPORT);  
  51.     server_addr.sin_addr.s_addr  =  htonl(INADDR_ANY);   
  52.     //bind  
  53.     if(bind(sockListen, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)  
  54.     {  
  55.         printf("bind error\n");  
  56.         return -1;  
  57.     }  
  58.     //listen  
  59.     if(listen(sockListen, 5) < 0)  
  60.     {  
  61.         printf("listen error\n");  
  62.         return -1;  
  63.     }  
  64.     //1. epoll 初始化  
  65.     epollfd = epoll_create(MAX_EVENTS);  
  66.     struct epoll_event event;  
  67.     event.events = EPOLLIN|EPOLLET;  
  68.     event.data.fd = sockListen;  
  69.     //2. epoll_ctrl  
  70.     if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sockListen, &event) < 0)  
  71.     {  
  72.         printf("epoll add fail : fd = %d\n", sockListen);  
  73.         return -1;  
  74.     }  
  75.     //epoll  
  76.     while(1)  
  77.     {  
  78.         timeout=3000;                  
  79.         //3. epoll_wait  
  80.         int ret = epoll_wait(epollfd, eventList, MAX_EVENTS, timeout);  
  81.         if(ret < 0)  
  82.         {  
  83.             printf("epoll error\n");  
  84.             break;  
  85.         }  
  86.         else if(ret == 0)  
  87.         {  
  88.             printf("timeout ...\n");  
  89.             continue;  
  90.         }  
  91.         //直接获取了事件数量,给出了活动的流,这里是和poll区别的关键  
  92.         int n = 0;  
  93.         for(n=0; n<ret; n++)  
  94.         {  
  95.             //错误退出  
  96.             if ((eventList[n].events & EPOLLERR) ||  
  97.                 (eventList[n].events & EPOLLHUP) ||  
  98.                 !(eventList[n].events & EPOLLIN))  
  99.             {  
  100.               printf ( "epoll error\n");  
  101.               close (eventList[n].data.fd);  
  102.               return -1;  
  103.             }  
  104.               
  105.             if (eventList[n].data.fd == sockListen)  
  106.             {  
  107.                 AcceptConn(sockListen);  
  108.           
  109.             }else{  
  110.                 RecvData(eventList[n].data.fd);  
  111.                 //不删除  
  112.              //   epoll_ctl(epollfd, EPOLL_CTL_DEL, pEvent->data.fd, pEvent);  
  113.             }  
  114.         }  
  115.     }  
  116.     close(epollfd);  
  117.     close(sockListen);  
  118.     printf("test\n");  
  119.     return 0;  
  120. }  
  121. /************************************************** 
  122. 函数名:AcceptConn 
  123. 功能:接受客户端的链接 
  124. 参数:srvfd:监听SOCKET 
  125. ***************************************************/  
  126. void AcceptConn(int srvfd)  
  127. {  
  128.     struct sockaddr_in sin;  
  129.     socklen_t len = sizeof(struct sockaddr_in);  
  130.     bzero(&sin, len);  
  131.     int confd = accept(srvfd, (struct sockaddr*)&sin, &len);  
  132.     if (confd < 0)  
  133.     {  
  134.        printf("bad accept\n");  
  135.        return;  
  136.     }else  
  137.     {  
  138.         printf("Accept Connection: %d", confd);  
  139.     }  
  140.     //setnonblocking(confd);  
  141.     //4. epoll_wait  
  142.     //将新建立的连接添加到EPOLL的监听中  
  143.     struct epoll_event event;  
  144.     event.data.fd = confd;  
  145.     event.events =  EPOLLIN|EPOLLET;  
  146.     epoll_ctl(epollfd, EPOLL_CTL_ADD, confd, &event);  
  147. }  
  148.   
  149. //读取数据  
  150. void RecvData(int fd)  
  151. {  
  152.     int ret;  
  153.     int recvLen = 0;  
  154.       
  155.     memset(recvBuf, 0, REVLEN);  
  156.     printf("RecvData function\n");  
  157.       
  158.     if(recvLen != REVLEN)  
  159.     {  
  160.         while(1)  
  161.         {  
  162.             //recv数据  
  163.             ret = recv(fd, (char *)recvBuf+recvLen, REVLEN-recvLen, 0);  
  164.             if(ret == 0)  
  165.             {  
  166.                 recvLen = 0;  
  167.                 break;  
  168.             }  
  169.             else if(ret < 0)  
  170.             {  
  171.                 recvLen = 0;  
  172.                 break;  
  173.             }  
  174.             //数据接受正常  
  175.             recvLen = recvLen+ret;  
  176.             if(recvLen<REVLEN)  
  177.             {  
  178.                 continue;  
  179.             }  
  180.             else  
  181.             {  
  182.                 //数据接受完毕  
  183.                 printf("buf = %s\n",  recvBuf);  
  184.                 recvLen = 0;  
  185.                 break;  
  186.             }  
  187.         }  
  188.     }  
  189.   
  190.     printf("content is %s", recvBuf);  
  191. }</span>  

                   4. 网络协议分层模型: 
                   5. 其他一些小问题:

                       a. 网络模型直接排序一般采用大端存储的。
                       b. keepalive???:
                       c. 长连接、短连接:
                       d. 防火墙如何利用TCP协议终止你的翻墙请求?

                   6. 网络分层模型和不同层的支持的协议:

(如何画时序图)

二、多线程编程:

                   1. 线程与进程:
                        线程共享:进程指令、大多数数据、打开的文件、信号处理函数和信号处置、当前工作目录、用户id和组ID
                        进程共享:线程ID、寄存器集合(程序计数器和函数指针)、栈、errno、信号掩码、优先级
                        线程&进程:线程是系统调度的最小单元,fork需要把父进程内存影响复制到子进程;fork返回以后父子进程需要进行IPC通信。 

                   2. 多线程编程:
                        pthread_create( pthread_t *tid, const pthread_attr_t *attr, void *(*func)(void *), void arg);
                                    pthread_join(pthread_t *tid, void **status) //如果status指针非空,把线程的返回值、一个指向某个对象的指针存入status指向的位置
                                    pthread_self(void) // 线程自身id
                                    pthread_detach(tid)// 线程终止时,所有资源被释放
                                    pthread_exit(void *status)//线程终止

                   3. 多进程编程:
                        fork()//创建子进程
                                    exec()//4个函数族。创建进程,但子进程执行时废弃当前进程的数据段和堆栈段

                   4. 进程/线程间同步\通信:

                      一般我们讨论进程间共享数据,线程间同步。因为线程很多数据都是共有的,而进程间很难共享数据,因此线程的同步和进程的数据共享一般都是我们面临的问题的。
                      a. 进程间共享/通信数据(IPC)方法:
                          管道、FIFO、共享内存、消息队列、信号、socket
                           对比:
                                    1. 管道:速度慢、容量有限、只有父子进程通讯
                                    2. FIFO: 任何进程都能通信,但速度慢
                                    3. 消息队列:容量受限
                                    4. 信号量:不能传递复杂信息
                                    5. 共享内存:速度快、容量大。需要注意同步


                          1). 
                      b. 线程间同步方法(SYNC):
                          临界区、锁、信号量、事件、interlocked variable

                          1). 锁:

                                            pthread_mutex_t counter_mutex=PTHREAD_MUTEX_INITIALIZER; COND

                                            pthread_mutex_lock(pthread_mutex_t * mptr);
                                            // do something

                                            pthread_mutex_unlock(pthread_mutex_t *mptr);


                           http://www.cnblogs.com/memewry/archive/2012/08/22/2651696.html

五、开源框架深入阅读和理解:

                 1. thrift协议的数据类型、协议、传输、服务类型
                 2. thrift协议源代码阅读

六、常用运行时程序排查:

                 1. 使用cp替换so文件为什么服务会core?
                 2. 如何排查内存泄露

七、分布式系统问题:

十、C++语言的新特性:

             1. 智能指针 std::shared_ptr 用法:
                           a). 智能指针是用来实现指针对象的共享和内存生存期自动管理(一般使用引用计数实现,我理解智能指针就是一个栈对象,在智能指针的生命期结束时,对智能指针指向的动态内存使用减1,如果计数减为0,则释放内存)。
                           b). 所有的智能指针都会重载* -> 等符号。

[cpp]  view plain  copy
  1. #include <boost/shared_ptr.hpp>  
  2. using namespace std;  
  3. class implementation  
  4. {  
  5. public:  
  6.     ~implementation() { std::cout <<"destroying implementation\n"; }  
  7.     void do_something() { std::cout << "did something\n"; }  
  8. };  
  9. void test(){   
  10.     boost::shared_ptr<implementation> sp1(new implementation());   
  11.     boost::shared_ptr<implementation> sp2 = sp1;   
  12.     sp2.reset();   
  13.     boost::shared_ptr<int> a1(ptr);   
  14.     std::cout<<*ptr<<endl;  
  15. }  
 
                           b). 使用智能指针注意事项:
                                 a. 不要把原生指针给多个shared_ptr管理。
                                 b. 不要在函数实参里创建shared_ptr。
                                 c. shared_ptr作为被保护对象时小心循环引用。

                                 d. 不要把this指针传给shared_ptr。

                           c). static_ptr_cast ???:
                                 

                  2. auto用法:

参考文献:
1. Unix网络编程:
2. thrift服务源代码分析: http://yanyiwu.com/work/2014/12/06/thrift-tnonblockingserver-analysis.html
3. 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当 Unity 应用切换到后台时,应用会自动进入暂停状态以减少资源占用,这是 Android 和 iOS 平台的默认行为。如果您希望 Unity 应用在后台继续运行,您可以采用以下方式: 1. 在 Unity 中设置应用后台运行权限 在 Unity 的 Player Settings 设置面板中可以设置应用后台运行权限。具体步骤如下: - 打开 Unity,选择 File > Build Settings 菜单。 - 在 Build Settings 窗口中选择您的目标平台,例如 Android 或 iOS。 - 点击 Player Settings 按钮,打开 Player Settings 面板。 - 在 Player Settings 面板中,选择平台对应的选项卡,例如 Android 或 iOS。 - 在选项卡中找到“Other Settings”部分,在“Identification”中将“Package Name”设置为自己应用的包名。 - 在“Other Settings”中找到“Configuration”部分,将“Scripting Backend”设置为“IL2CPP”。 - 在“Other Settings”中找到“Optimization”部分,将“API Compatibility Level”设置为“.NET 4.x”。 - 在“Other Settings”中找到“Configuration”部分,将“Minimum API Level”设置为“Android 4.4 'KitKat'”或者“iOS 9.0”。 - 在“Other Settings”中找到“Configuration”部分,将“Target API Level”设置为“Android 9.0 'Pie'”或者“iOS 13.0”。 - 在 Unity 中编写一个后台服务的脚本,并在 AndroidManifest.xml 或 Info.plist 文件中注册该服务。 2. 在 Unity 脚本中实现后台运行 在 Unity 应用中,您可以编写一个后台服务的脚本,并在 AndroidManifest.xml 或 Info.plist 文件中注册该服务。该脚本可以使用 Unity 提供的 Application.runInBackground 方法来实现后台运行。例如: ```csharp void Start() { Application.runInBackground = true; } void Update() { // 在后台运行的代码 } ``` 需要注意的是,如果您的应用需要在后台运行,您需要在应用启动时启用后台运行,并在应用退出时停止后台运行。在 Android 平台上,您可以通过编写一个后台服务来实现这一点。在 iOS 平台上,您需要使用后台模式 API 来实现后台运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值