![](https://img-blog.csdnimg.cn/20201014180756918.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
服务器开发
凌云天空
这个作者很懒,什么都没留下…
展开
-
服务器程序日志介绍以及实现封装
日志的一般有诊断日志和交易日志,诊断日志简单说就是以文本形式供人阅读的日志。而交易日志是数据库的write-ahead log、文件系统的journaing等,通过回放日志可以恢复每一次修改后的状态。这里说的日志是诊断日志。日志的作用:1.诊断定位程序执行问题2.追踪(trace)程序执行过程和数据变化。3.程序的性能分析4.记录数据采集、分析和统计在服务器编程中日志必不可少,对于程序问题的诊断和分析,GDB不一定是好的方法,通过日志定位问题是必要的。日...原创 2021-09-30 11:00:24 · 459 阅读 · 0 评论 -
关于weak_ptr在工作中的使用
前一段时间遇到一个问题,做的一个buff管理器,buff执行过程中需要用到释放skill的对象,当时为了方便和执行效率,直接保存了对象的指针(没有用智能指针)。后来业务逻辑修改了,在buff存在期间,释放skill对象可能已经销毁了。这就尴尬了,buff执行过程中可能会用到已经销毁的对象,但是buff管理器不知道,这样会导致未知的错误。 后来处理方法是buff对象直接保存释放skill对象的ID,每次执行的时候,从map中取一下,如果可以取到就是表明对象还活着,取不到表示对象已经死了。这...原创 2021-06-24 15:17:30 · 432 阅读 · 0 评论 -
网络服务器端程序线程划分
1.I/O线程,这种线程的主循环是多路复用,阻塞地等待在select/poll/epoll_wait系统调用上。这类线程也处理定时事件。当然它的功能不止IO,有些简单计算也可以放在其中,比如消息的编码或者解码。2.计算线程(习惯叫事件线程),这类线程的主循环是阻塞的事件队列,阻塞地等在条件变量上,这样的线程可以有多个位于线程池中,这种线程通常不涉及I/O,一般要避免任何阻塞操作(尽量不要有系统调用函数,如read write之类的函数)。当然根据实际情况也可以试非阻塞的事件循环,不断轮询从事件队列中取得原创 2021-02-05 10:28:05 · 301 阅读 · 0 评论 -
多线程编程,互斥锁与自旋锁注意事项
多线程编程中会涉及公共资源相互竞争问题,就像火车上的厕所,只用一个人可以上,当有人进入后就会加锁。多线程一样为了避免多个线程同时访问公共资源也需要加锁。一般会用到互斥锁或者自旋锁。互斥锁线程请求锁,如果请求到加锁执行,然后解锁。如果没有请求到锁,那么就把线程放入等待队列里,将线程挂起。如果持有锁的线程执行完并且释放锁,则会唤醒等待队列里的某个线程去执行,那么它就能获取到锁。互斥锁会涉及线程挂起,导致线程的状态切换(用户态->内核态),这样会有上下文切换,这样性能会有损耗。Linux内核提供原创 2020-11-12 10:25:49 · 495 阅读 · 0 评论 -
多线程编程类封装,线程id注意事项
一般在多线程编程的时候,我们会封装一个thread类,其中封装了线程的开启、回调以及终止等操作。c++的线程不同于java,线程没有名字。我们通过thread类还可以定义线程的名字,同时在类实现时,每一个线程都应该有一个线程id。 POSIX threads库提供了pthread_self函数,调用pthread_self函数可以返回当前线程的标识符,返回值类型是pthread_t,通过调用pthread_equal函数来比对两个线程标识符是否相等。而通过调用pthread_self函数返...原创 2020-10-29 16:14:28 · 354 阅读 · 0 评论 -
C++内存问题以及解决办法和shared_ptr基本原理实现
C++这门复杂而灵活的语言不同于其他很多语言诸如Java,需要编程者通过new/delete来动态管理内存,这一不留神就容易造成内存泄漏,严重影响程序的健壮性。 shared_ptr作为一种智能指针,原理很简单,它的作用跟指针一样,不过shared_ptr保存了一个引用计数,记录了有多少个shared_ptr共同指向同一对象。每当有新的shared_ptr指向该对象时计数加一,如果指向对象的shared_ptr销毁时计数减一,一旦对象的引用计数变成0,这个对象自动被销毁,这样对内存泄漏的控制...原创 2020-10-26 15:58:35 · 815 阅读 · 0 评论 -
通过setjmp与longjmp实现try catch
函数头文件:#include <setjmp.h>int setjmp(jmp_buf env);调用setjmp将堆栈上下文保存在jmp_buf结构体中(入栈),供longjmp稍后使用。如果直接调用返回0,如果使用保存的上下文从longjmp返回,则返回保存值非零。void longjmp(jmp_buf env, int val);调用longjmp程序跳转到最后一次使用相应env参数调用setjmp处,调用longjmp后setjmp不能返回0,如果longjmp第二个参数原创 2020-10-24 12:58:38 · 531 阅读 · 0 评论 -
论原子性操作使用场景以及原子类封装
原子性操作,意思是说CPU执行的过程中,操作的粒度如同原子,不可再细分中途不能被打断。众所周知如今CPU执行程序是分时间片执行的,线程是CPU调度的单位。每一个线程的执行都会分到一个时间片,当线程的时间片用完后,线程挂起等待下次调度,然后在从调度队列中取出其他线程开始执行。 对于多线程程序中,如果有公共资源,多个线程可以并行,就会涉及到一个线程在操作公共资源时,另一线程也开始操作公共资源,造成数据错乱的问题。 解决办法就是加锁,通过加锁实现了线程对公共资源操作一次的完整性,哪怕操作...原创 2020-10-13 18:00:56 · 888 阅读 · 0 评论 -
在开发中用lua做配置文件
我们在开发中常用ini或者xml做配置文件,ini配置只有简单的节、键、值组成,无法应对复杂的多层次配置,或者列表配置。xml文件层次分明,写起来比较复杂。lua脚本作为一门轻量小巧的脚本语言,常用在游戏开发中或者web应用中。lua脚本简单清晰,很适合做配置文件。可以做服务器端程序的配置文件,下面是封装了一个类,用于来读取lua配置文件。#include <stdio.h>#include <stdlib.h>#include <unistd.h>#...原创 2020-10-12 15:37:11 · 1438 阅读 · 0 评论 -
UDP通讯相关以及与epoll结合的回射服务器
UDP属于用户数据报协议,属于传输层协议。提供面向无连接的、不可靠的传输,没有拥塞控制和超时重传机制。相对于TCP面向连接的,提供可靠传输的传输层协议,UDP也有其应用场景。UDP在首部开销小,传输速度快的优点,应用也很广泛比音视频通话,网络直播,游戏中帧同步等等。不同于TCP这样的流式套接字,对于UDP不用处理粘包问题。UDP是面向报文的,对应用层交付的报文,直接添加协议头就交付给IP层,不会对报文进行合并或者拆分,保留了报文的边界。所以接收端的socket缓冲区采用链式结构保存每一个到达的UDP数据原创 2020-09-22 13:00:24 · 1456 阅读 · 0 评论 -
eventfd与多路复用结合实现进程/线程间通讯
eventfeventfd是Linux2.6.27内核版本加入的系统调用,主要可以用来进程/线程间通讯。用法很简单,通过调 用inteventfd(unsignedintinitval,intflags)函数返回一个文件描述符,通过read和write函数进行进程/线程间通讯。 调用eventfd函数会创建一个eventfd对象,可以被用户空间的应用程序用来作为事件等待/通知机制。eventfd函数返回eventfd对象的文件描述符,通过操作文件描述符来进行事件等待和...原创 2020-09-07 14:48:54 · 748 阅读 · 0 评论 -
timerfd与多路复用完美融合实现定时器
在服务器开发中一般都会用到多路复用技术来处理网络I/O事件,至于服务器中的定时器我们可以用timerfd来实现,可以想监听网络事件一样处理定时器事件,与select/poll/epoll配合使用。使用timefd做定时器需要三个函数:timerfd_create、timerfd_settime、timerfd_gettime。timerfd_create函数#include <sys/timerfd.h>int timerfd_create(int clockid, int ...原创 2020-09-03 09:31:45 · 654 阅读 · 0 评论 -
Linux下简单的线程池模型实现
为了充分利用多核的优势,程序一般会开启多个进程或者线程去处理任务。进程是资源分配的基本单位,而线程是执行和调度的基本单位。因此多线可以充分利用多核,而且因为共享资源,线程间数据共享便于程序开发,而进程间通讯就没有那么方便。 但是由于多个线程共享同一进程的资源,如果其中一个线程现了段错误或者其它的致命错误,会导致整个程序退出,而多进程程序,由于进程的资源是独立的,如果某一个程序出现错误也只会影响一个进程。 多线程中由于线程间共享资源,对于公共资源的排他性,同一时刻只能有一个线程访...原创 2020-08-20 14:48:44 · 324 阅读 · 0 评论 -
daemon函数使程序后台运行
daemon函数的作用就是让程序从控制终端分离开,以后台进程方式运行,服务器程序都是这么运行的。查看一下man手册NAME daemon - run in the backgroundSYNOPSIS #include <unistd.h> int daemon(int nochdir, int noclose);DESCRIPTION The daemon() function is for programs wishing...原创 2020-08-19 10:08:13 · 780 阅读 · 0 评论 -
设计模式之Reactor反应堆
Reactor反应堆设计模式是高效的I/O设计中常用的模式之一,它是以同步I/O方式来处理I/O事件的。目前常见的开源网络事件库libevent、libev、libuv、muduo都用到了Reactor反应堆设计模式。在服务器开发中,也有不少人基于Reactor反应堆设计模式来封装自己的网络库。下面是用C++实现Reator模式实现的回射服务器EventHandler.h#ifndef EVENT_HANDLER_H_#define EVENT_HANDLER_H_typedef int原创 2020-08-18 16:51:15 · 818 阅读 · 0 评论 -
服务器开发常用设计模式之单例模式
在服务程序开发时,常常会用到单例模式,很多模块的实现只有一个类实例,为其他模快提供调用接口和数据,使用起来方便高效。是我在游戏服务器端开发中用的比较多设计模式之一。 由于C++的构造函数不是线程安全的。在多线程的情况下,为了防止多个线程同时创建对象,造成内存泄漏,需要我们注意进行处理接下来介绍如何避免内存泄漏。单例模式分为懒汉模式和饿汉模式。我们可以通过饿汉模式来避免内存的泄漏,在单例类定义时就进行类的实例化,就不会存在多个线程同时创建对象的情况。这种情况就是用空间换时间,不用在我们使用...原创 2020-08-15 13:04:20 · 509 阅读 · 0 评论 -
关于sched_yield()主动出让CPU的占有权
有时候程序在一个死循环中执行,不断尝试获取某个资源,如果没有获得就会不断尝试。为了防止程序空跑,可以调用sched_yield函数来主动出让CPU的占有权,减少CPU的空跑。比如自旋锁的实现可以调用sched_yield来减少CPU的空跑。man一下,查看一下手册:NAME sched_yield - yield the processorSYNOPSIS #include <sched.h> int sched_yield(void);...原创 2020-08-13 11:23:31 · 1337 阅读 · 0 评论 -
用new在指定内存构造对象
C++中使用new进行系统调用分配内存,与C语言中的malloc分配内存的本质区别在于malloc只是在堆上开辟一块内存,而new不但开辟内存而且还调用了对象构造函数进行初始化,最后返回相应指针。如:A* p = new A; A* p = new(std::nothrow)A;//如果分配内存失败不抛出异常,返回NULL指针另外new作为函数可以在指定内存上分配构造对象的。形式如下:new (ptr)A();利用placement new可以在栈上分配对象:char buff[1024..原创 2020-06-17 17:51:10 · 1042 阅读 · 0 评论 -
对于TCP连接三次握手和四次挥手的理解
为了理解TCP的三次握手和四次挥手需要了解TCP协议TCP协议的头如下:源端口和目的端口各占16位也就是两个字节,这也就说明了为什么端口号在程序中是unsignedshort类型的值。标志位flags有六个:URG:紧急指针(urgentpointer)有效。ACK:确认序号有效。PSH:接收方应该尽快将这个报文交给应用层。RST:重置连接。SYN:发起一个新连接。FIN:释放一个连接。按位设置每一个标志位代表一个状态,比如发起新的连接时SYN位置1。三次握手:acce...原创 2020-06-08 14:42:00 · 210 阅读 · 0 评论 -
程序崩溃生成core文件
写游戏服务器程序的时候,运行时避免不了出错崩溃,需要生成core文件,来定位发生错误的位置,可以通过信号处理调backtrace和backtrace_symbols获取堆栈信息,写到文件中,查看文件定位错误。 简单的方法,在运行服务器程序的脚步中加一行指令ulimit -c unlimited 这样就会生成类似core.17609这样的文件,file core.17309来确...原创 2019-08-03 15:01:58 · 1155 阅读 · 0 评论 -
signal在服务器开发中的简单应用
开发高性能的游戏服务器程序需要用到很多知识,也要注意很多细节,通过不断地积累,将一个一个简单的知识点组合,最终便形成一个高效稳定的游戏服务器。signal在服务器开发中的简单应用。Siganl函数用于设置某一个信号的对应动作,如果不设置,执行系统默认处理(通过 man 7 signal 查询),有些结果可能不是我们想要的,有时候需要我们设置。如下是通过man查到的函数声明:#include <...原创 2018-04-01 14:17:51 · 1049 阅读 · 0 评论