最简单的二分 1.循环实现 template <typename T> int binary_search(const vector<T> &set, const T &value) { auto low = set.begin(); auto high = set.end(); auto high_dump = high; auto low_dump = low; auto mid = low + ((high - low) >> 1); /*1. mid=(low+high)/2,如果 low 和 high 太大就会产生溢出*/ while ((low <= high) && (mid != high_dump)) /*2. 一定是 <= */ { if (*mid == value) return mid - low_dump; /*3. 一定要+1,-1,不然当  继续阅读 >>


刘生玺 18/11/04 22:52:10
1. 为新线程传递参数 错误代码示例: for (i = 0; i < N; i++) { pthread_create(&tid, NULL, &handle, &i); } 当当当,要提问啦!!! 以上这段代码会发生什么奇怪的事情吗?当线程去进行处理i的时候,如果cpu调度到主线程运行,就会改变i的值。因为传入的是地址,所以线程中使用的i就会被改变。这就会出现问题。那么我们如何给线程传递参数呐?一般有以下两种方法: 1. 传送值而不传送地址 2. 通过`new,malloc`传递 1. 传送值而不传送地址 for (i = 0; i < N; i++) { pthread_create(&tid, NULL, &handle, (void *)i); } void *handle(void *arg) { int i = (int)arg; 。。。 retur 继续阅读 >>


刘生玺 18/09/27 23:41:07
   首先,如果你还不了解什么是带外数据:点这里 心跳机制的产生就是为了检测出对端主机或到对端的通信路径是否过早失效。 注意:在使用心跳机制时,你应该考虑是不是符合你所处的情景,确定在对端应答的时间超过 5~10s 之后终止连接是件好事还是坏事。如果你的产品需要实时的知道对端的“生存状态”,(要么是为了需求,要么是为了节省资源)那么就是需要这种机制的。一般用于 长连接 。    在这里,我们使用TCP的带外数据来完成心跳机制的实现(每秒钟轮询一次,若5秒没有得到响应就认为对端已经“死亡”),实现如下所示 : 客户端每隔1秒钟向服务器发送一个带外字节,服务器收到该类型的字节然后再发送回一个带外字节。因为每一端都需要对端不复存在或者不再可达。需要指出的是:**数据,回送数据和带外字节都通过单个的连接交换的 。**代码实现如下,具体实现细节在代码中有注释指出 Recvline 函数 #include "../myhead.h" static int recv_cnt = 0; static char 继续阅读 >>


刘生玺 18/09/23 15:31:39
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客: 全新的界面设计 ,将会带来全新的写作体验; 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示; 增加了 图片拖拽 功能,你可 继续阅读 >>


刘生玺 18/09/18 17:21:48
   首先给出OSI 参考模型与TCP/IP协议模型图: 1. 概述: 首先,我们需要知道的是数据分为两种,一种是带内数据,一种是带外数据。带内数据就是我们平常传输或者说是口头叫的数据。带外数据就是我们接下来讲的内容。    许多的传输层都具有带外数据(也称为 经加速数据 )的概念,想法就是连接的某段发生了重要的事情,希望迅速的通知给对端。这里的迅速是指这种通知应该在已经排队了的带内数据之前发送。也就是说,带外数据拥有更高的优先级。带外数据不要求再启动一个连接进行传输,而是使用已有的连接进行传输。    其中,UDP没有实现带外数据(是个极端哦~)    TCP中telnet,rlogin,ftp等应用(除了这样的远程非活跃应用之外,几乎很少有使用到带外数据的地方) 2. TCP 带外数据 2.0 铺垫 : 我们亲爱的 TCP 就位于传输层,下面还有互联网层(主要是IP)与网卡等 。相信学过网络编程的都知道,对于报文的处理,在经过每一层时都会有添加头部和解析头部的操作。 继续阅读 >>


刘生玺 18/09/13 17:36:24
1.非阻塞Connect有什么用? 可以让三路握手的处理等同与一般数据的处理,而不是一直让 connect一直尝试重连或者花费一个RTT时间。而且RTT时间从几毫秒到几秒不等,万一有许多连接,不论是尝试重连还是花费一个RTT时间,都将是致命的延时。 可以使用该技术同时建立多个连接。Web浏览器中常用。 既然使用select等待连接的建立,我们就可以质地不嗯一个时间限制,使得我们能够缩短connect的超时。 2.必须去处理的细节: 处理connect立即建立的情况。(比如我们连接的是同一个主机时) 使用selcet与非阻塞connect的一些注意事项: 2.1. 当连接成功建立后,描述符变为可写。 2.2 当遇到错误时,描述符变为即可写又可读。 3. 两个例子: (1)非阻塞connect:时间获取客户程序 int Connect_nonblock(int sockfd, const SA *saptr, socklen_t salen, int nsec) / 继续阅读 >>


刘生玺 18/09/08 23:33:35
   最近学弟学妹们在写聊天室,期间遇到了很多问题,也“逼迫”我们这些大二(其实即将大三)狗考虑了许多以前没有考虑过的东西。现在就着我们小组的聊天室的项目,送给学弟学妹们”几个可能安全的封装函数。“ frist : 保证发送“len”字节到套接字 ssize_t Sendlen(int fd, const void *buf, size_t len, int flags) { ssize_t n = 0; size_t sum = 0; const char *ptr; ptr = (const char *)buf; while (sum < len) { n = send(fd, (void *)ptr, len - sum, flags); if (n < 0) { if (errno == EINTR) n = 0; 继续阅读 >>


刘生玺 18/08/23 16:45:01
1. 基础介绍   最通用的I/O函数,只要设置好参数,read、readv、recv、recvfrom和write、writev、send、sendto等函数都可以对应换成这两个函数来调用。同时,各种输出函数调用也可以替换成sendmsg调用。 #include <sys/socket.h> ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); ssizt_t sendmsg(int sockfd, struct msghdr *msg, int flags); 大部分参数都在 msghdr结构中 struct iovec { /* Scatter/gather array items */ void *iov_base; /* Starting address */ size_t iov_len; /* Number of bytes to transfe 继续阅读 >>


刘生玺 18/08/22 20:28:00
  unp上讲述了以下三种方法: 1.调用alarm,它在指定超时期满时将产生SIGALRM信号。 2. 使用select为函数设置超时 3.使用SO_RCVTIMEO套接字选项为函数设置超时 (1.1).使用 SIGALRM 信号为 connect设置超时 static void connect_alarm(int); int connect_timeo(int sockfd, const SA *saptr, socklen_t salen, int nsec) { Sigfunc *sigfunc; int n; sigfunc = Signal(SIGALRM, connect_alarm);//设置新的信号处理函数 if (alarm(nsec) != 0)//检测以前有没有设置过时钟,如果有就会覆盖 err_msg("connect_timeo: alarm was already set"); 继续阅读 >>


刘生玺 18/08/17 22:38:16
1. 经典“入门级”问题:IO 多路复用是什么意思? 在单个线程通过记录跟踪每一个Sock(I/O流)的状态来同时管理多个I/O流. 发明它的原因,是尽量多的提高服务器的吞吐能力。 是不是听起来好拗口,看个图就懂了.(其实就是一个时分复用)    在同一个线程里面, 通过拨开关的方式,来同时传输多个I/O流 那么,“一个请求到来了,nginx使用epoll接收请求的过程是怎样的”, 其实,ngnix会有很多链接进来, epoll会把他们都监视起来,然后像拨开关一样,谁有数据就拨向谁,然后调用相应的代码处理。 其中,“复用”指的是复用同一个线程。 其实就是操作系统为你提供了一个功能,当你的某个socket可读或者可写的时候,它可以给你一个通知,让你去处理读事件或者写事件。 而这个功能能够通过select/poll/epoll等来使用。这些函数都可以同时监视多个描述符的读写就绪状况,这样,多个描述符的 I/O 操作都能在一个线程内并发交替地顺序完成 。 2.s 继续阅读 >>


刘生玺 18/08/17 21:00:21