精华内容
下载资源
问答
  • 在日常开发中我们会做一些服务器部署的工作,对于开发来说,运维部署并不是我们的专项;有些命令不是经常使用,很快就会忘记;在这总结一下日常部署时常用的一些运维命令。 文件操作 tail tail 命令可用于查看文件的...

    Linux命令大全

    前言

    在日常开发中我们会做一些服务器部署的工作,对于开发来说,运维部署并不是我们的专项;有些命令不是经常使用,很快就会忘记;在这总结一下日常部署时常用的一些运维命令。

    文件操作

    tail

    tail 命令可用于查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件。

    命令格式:

    tail [参数] [文件]

    参数:

    • -f 循环读取
    • -q 不显示处理信息
    • -v 显示详细的处理信息
    • -c<数目> 显示的字节数
    • -n<行数> 显示文件的尾部 n 行内容
    • --pid=PID 与-f合用,表示在进程ID,PID死掉之后结束
    • -q, --quiet, --silent 从不输出给出文件名的首部
    • -s, --sleep-interval=S 与-f合用,表示在每次反复的间隔休眠S秒

    示例

    image-20191213103608175

    image-20191213103723510

    一般我们及时使用-f参数实时监控服务器日志。

    ll命令

    ll并不是linux下一个基本的命令,它实际上是ls -l的一个别名。

    Ubuntu默认不支持命令ll,必须用 ls -l,这样使用起来不是很方便。

    image-20191213105629006

    1、文件类型

    • “-”表示普通文件;
    • “d”表示目录;
    • “l”表示链接文件;
    • “p”表示管理文件;
    • “b”表示块设备文件;
    • “c”表示字符设备文件;
    • “s”表示套接字文件;

    2、文件属性

    • r(Read,读取权限):对文件而言,具有读取文件内容的权限;对目录来说,具有浏览目录的权限。
    • w(Write,写入权限):对文件而言,具有新增、修改文件内容的权限;对目录来说,具有删除、移动目录内文件的权限。
    • x(eXecute,执行权限):对文件而言,具有执行文件的权限;对目录来说,该用户具有进入目录的权限。
      另外,这里还有2个很特殊的属性,平时不怎么
    • s或S(SUID,Set UID):可执行的文件搭配这个权限,便能得到特权,任意存取该文件的所有者能使用的全部系统资源。请注意具备SUID权限的文件,黑客经常利用这种权限,以SUID配上root帐号拥有者,无声无息地在系统中开扇后门,供日后进出使用。
    • t或T(Sticky):/tmp和 /var/tmp目录供所有用户暂时存取文件,亦即每位用户皆拥有完整的权限进入该目录,去浏览、删除和移动文件。

    3、目录/文件个数

    对于目录文件,表示它的第一级子目录的个数。注意此处看到的值要减2才等于该目录下的子目录的实际个数。4

    4、所有者/分组

    表示该文件的所有者/创建者(owner)及其所在的组(group)。

    5、文件大小

    如果是文件,则表示该文件的大小,单位为字节。
    如果是目录,则表示该目录符所占的大小,并不表示该目录下所有文件的大小。

    6、修改日期

    该文件最后修改的日期时间。

    7、文件名称

    ln命令

    centos下的ln命令就相当于window下的建立快捷方式,链接文件甚至可以链接不存在的文件,这就产生一般称之为”断链”的现象,链接文件甚至可以循环链接自己。 类似于编程语言中的递归。
    软链接文件只是其源文件的一个标记,当删除了源文件后,链接文件不能独立存在,虽然仍保留文件名,但却不能查看软链接文件的内容了。

    ln -s 源文件 目标文件

    ln -s /opt/soft/node-v8.9.0-linux-x64/bin/vuepress /usr/bin

    -s 是代号(symbolic)的意思

    1. ln命令会保持每一处链接文件的同步性,也就是说,不论你改动了哪一处,其它的文件都会发生相同的变化
    2. ln的链接又软链接 和硬链接两种,软链接就是ln -s xx xx,它只会在你选定的位置上生成一个文件的镜像,不会占用磁盘空间,硬链接ln ,没有参数-s, 它会在你选定的位置上生成一个和源文件大小相同的文件,无论是软链接还是硬链接,文件都保持同步变化。

    参数

    • -b 删除,覆盖以前建立的链接
    • -d 允许超级用户制作目录的硬链接
    • -f 强制执行
    • -i 交互模式,文件存在则提示用户是否覆盖
    • -n 把符号链接视为一般目录
    • -s 软链接(符号链接)
    • -v 显示详细的处理过程

    cp命令

    cp [选项] 源文件(source) 目标文件或者目录(destination)

    • -a: 是指archive的意思,也说是指复制所有的目录
    • -d: 若源文件为连接文件(link file),则复制连接文件属性而非文件本身
    • -f: 强制(force),若有重复或其它疑问时,不会询问用户,而强制复制
    • -i: 若目标文件(destination)已存在,在覆盖时会先询问是否真的操作
    • -l: 建立硬连接(hard link)的连接文件,而非复制文件本身
    • -p: 与文件的属性一起复制,而非使用默认属性
    • -r: 递归复制,用于目录的复制操作
    • -s: 复制成符号连接文件(symbolic link),即“快捷方式”文件
    • -u: 若目标文件比源文件旧,更新目标文件
    cp -f package.json ./backup

    mv命令

    mv [选项] source destination

    • -f: force,强制直接移动而不询问
    • -i: 若目标文件(destination)已经存在,就会询问是否覆盖
    • -u: 若目标文件已经存在,且源文件比较新,才会更新

    系统监控命令

    内存监控

    free命令

    image-20191213111344785

    Linux free命令用于显示内存状态。

    free指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等。

    语法

    free [-bkmotV][-s <间隔秒数>]

    参数说明

    • -b  以Byte为单位显示内存使用情况。
    • -k  以KB为单位显示内存使用情况。
    • -m  以MB为单位显示内存使用情况。
    • -h  以合适的单位显示内存使用情况,最大为三位数,自动计算对应的单位值。单位有:

      B = bytes
      K = kilos
      M = megas
      G = gigas
      T = teras
    • -o  不显示缓冲区调节列。
    • -s<间隔秒数>  持续观察内存使用状况。
    • -t  显示内存总和列。
    • -V  显示版本信息。

    Men:表示物理内存统计

    Swap:表示硬盘上交换分区的使用情况

    total:表示物理内存总数(total=used+free)
    used:表示系统分配给缓存使用的数量(这里的缓存包括buffer和cache)
    free:表示未分配的物理内存总数
    shared:表示共享内存
    buffers:系统分配但未被使用的buffers 数量。
    cached:系统分配但未被使用的cache 数量。
    -/+ buffers/cache:表示物理内存的缓存统计

    (-buffers/cache) 内存数: (指的第一部分Mem行中的used – buffers – cached)
    (+buffers/cache) 内存数: (指的第一部分Mem行中的free + buffers + cached)
    (-buffers/cache)表示真正使用的内存数, (+buffers/cache) 表示真正未使用的内存数

    vmstat命令

    vmstat(Virtual Meomory Statistics,虚拟内存统计)是对系统的整体情况进行统计,包括内核进程、虚拟内存、磁盘、陷阱和 CPU 活动的统计信息。

    常用命令

    vmstat 2 2 【在2秒时间内进行2次采样】

    image-20191213140826375

    参数

    Procs(进程):

    • r:运行队列中进程数量
    • b:等待IO的进程数量

    Memory(内存):

    • swpd: 使用虚拟内存大小
    • free: 可用内存大小
    • buff: 用作缓冲的内存大小
    • cache: 用作缓存的内存大小

    Swap:

    • si: 每秒从交换区写到内存的大小
    • so: 每秒写入交换区的内存大小

    IO:(现在的Linux版本块的大小为1024bytes)

    • bi: 每秒读取的块数
    • bo: 每秒写入的块数

    system(系统):

    • in: 每秒中断数,包括时钟中断。【interrupt】
    • cs: 每秒上下文切换数。 【count/second】

    CPU(以百分比表示):

    • us: 用户进程执行时间(user time)
    • sy: 系统进程执行时间(system time)
    • id: 空闲时间(包括IO等待时间),中央处理器的空闲时间 。以百分比表示。
    • wa: 等待IO时间

    CPU监控

    top命令

    top命令可以实时动态地查看系统的整体运行情况,是一个综合了多方信息监测系统性能和运行信息的实用工具

    使用权限:所有使用者。

    语法

    top [-] [d delay] [q] [c] [S] [s] [i] [n] [b]

    参数说明

    • d : 改变显示的更新速度,或是在交谈式指令列( interactive command)按 s
    • q : 没有任何延迟的显示速度,如果使用者是有 superuser 的权限,则 top 将会以最高的优先序执行
    • c : 切换显示模式,共有两种模式,一是只显示执行档的名称,另一种是显示完整的路径与名称S : 累积模式,会将己完成或消失的子行程 ( dead child process ) 的 CPU time 累积起来
    • s : 安全模式,将交谈式指令取消, 避免潜在的危机
    • i : 不显示任何闲置 (idle) 或无用 (zombie) 的行程
    • n : 更新的次数,完成后将会退出 top
    • b : 批次档模式,搭配 "n" 参数一起使用,可以用来将 top 的结果输出到档案内

      image-20191213111809397

    mpstat命令

    mpstat是 Multiprocessor Statistics的缩写,是实时系统监控工具。其报告与CPU的一些统计信息,这些信息存放在/proc/stat文件中。在多CPU系统里,其不但能查看所有CPU的平均状况信息,而且能够查看特定CPU的信息。

    常用命令

    mpstat -P ALL 2 【ALL表示显示所有CPUs,也可以指定某个CPU;2表示刷新间隔】

    image-20191213141621315

    参数

    • CPU:处理器ID
    • %usr 在internal时间段里,用户态的CPU时间(%),不包含 nice值为负进程
    • %nice 在internal时间段里,nice值为负进程的CPU时间(%)
    • %sys 在internal时间段里,核心时间(%)
    • %iowait 在internal时间段里,硬盘IO等待时间(%)
    • %irq 在internal时间段里,硬中断时间(%)
    • %soft 在internal时间段里,软中断时间(%)
    • %steal 显示虚拟机管理器在服务另一个虚拟处理器时虚拟CPU处在非自愿等待下花费时间的百分比
    • %guest 显示运行虚拟处理器时CPU花费时间的百分比
    • %idle 在internal时间段里,CPU除去等待磁盘IO操作外的因为任何原因而空闲的时间闲置时间(%)

    进程监控

    ps命令

    ps命令用于查看进程统计信息

    常用参数:

    • a:显示当前终端下的所有进程信息,包括其他用户的进程。
    • u:使用以用户为主的格式输出进程信息。
    • x:显示当前用户在所有终端下的进程。
    • -e:显示系统内的所有进程信息。
    • -l:使用长(long)格式显示进程信息。
    • -f:使用完整的(full)格式显示进程信息。

    ps -aux

    最常用的方法是ps -aux,然后再利用一个管道符号导向到grep去查找特定的进程,然后再对特定的进程进行操作。

    image-20191213112328721

    列说明:

    • USER: 用户名
    • PID: 进程ID(Process ID)
    • %CPU: 进程的cpu占用率
    • %MEM: 进程的内存占用率
    • VSZ: 进程所使用的虚存的大小(Virtual Size)
    • RSS: 进程使用的驻留集大小或者是实际内存的大小,Kbytes字节。
    • TTY: 与进程关联的终端(tty)
    • STAT: 进程的状态:进程状态使用字符表示的(STAT的状态码)
    • TIME: 进程使用的总cpu时间
    • COMMAND: 正在执行的命令行命令

    ps -ef

    image-20191213112434230

    • UID: 用户ID(User ID)
    • PID: 进程ID(Process ID)
    • PPID: 父进程的进程ID(Parent Process id)
    • STIME: 启动时间
    • TTY: 与进程关联的终端(tty)
    • TIME: 进程使用的总cpu时间
    • CMD: 正在执行的命令行命令

    ps -ef | grep

    | 符号,是个管道符号,表示ps 和 grep 命令同时执行;

    grep 命令是查找(Global Regular Expression
    Print),能使用正则表达式搜索文本,然后把匹配的行显示出来;

    image-20191213112931855

    ps -l

    image-20191213112521888

    • F: 代表这个程序的旗标 (flag), 4 代表使用者为 super user
    • S: 睡眠 Sleeping 休眠中, 受阻, 在等待某个条件的形成或接受到信号。
    • UID: 用户ID(User ID)
    • PID: 进程ID(Process ID)
    • PPID: 父进程的进程ID(Parent Process id)
    • C: CPU 使用的资源百分比
    • PRI: 这个是 Priority (优先执行序) 的缩写,详细后面介绍
    • NI: 这个是 Nice 值,在下一小节我们会持续介绍
    • ADDR: 这个是 kernel function,指出该程序在内存的那个部分。如果是个 running的程序,一般就是 "-"
    • SZ: 使用掉的内存大小
    • WCHAN: 目前这个程序是否正在运作当中,若为 - 表示正在运作
    • TTY: 登入者的终端机位置
    • TIME: 使用掉的 CPU 时间。
    • CMD 所下达的指令为何

    其他

    查看进程的启动时间:
    ps -eo lstart 启动时间

    查看进程的运行时间
    ps -eo etime 运行多长时间.

    查看进程的pid、启动时间、运行时间
    ps -eo pid,lstart,etime | grep [ pid ]

    pstree命令

    以树状图的方式展现进程之间的派生关

    • pstree -p 显示当前所有进程的进程号和进程id
    • pstree -a 显示所有进程的所有详细信息,遇到相同的进程名可以压缩显示。

    pidof命令

    查找正在运行进程的PID

    image-20191213143350781

    其他

    uptime:显示系统总共运行了多长时间和系统的平均负载

    image-20191213143707179

    pmap:比较专业的查看内存与进程对应关系工具

    image-20191213143920584

    磁盘监控

    df命令

    image-20191213114301424

    • df -h查看磁盘使用情况
    • df -i 查看inode使用情况

    du命令

    Linux du命令用于显示目录或文件的大小。

    du会显示指定的目录或文件所占用的磁盘空间。

    参数说明

    • -a或-all 显示目录中个别文件的大小。
    • -b或-bytes 显示目录或文件大小时,以byte为单位。
    • -c或--total 除了显示个别目录或文件的大小外,同时也显示所有目录或文件的总和。
    • -D或--dereference-args 显示指定符号连接的源文件大小。
    • -h或--human-readable 以K,M,G为单位,提高信息的可读性。
    • -H或--si 与-h参数相同,但是K,M,G是以1000为换算单位。
    • -k或--kilobytes 以1024 bytes为单位。
    • -l或--count-links 重复计算硬件连接的文件。
    • -L<符号连接>或--dereference<符号连接> 显示选项中所指定符号连接的源文件大小。
    • -m或--megabytes 以1MB为单位。
    • -s或--summarize 仅显示总计。
    • -S或--separate-dirs 显示个别目录的大小时,并不含其子目录的大小。
    • -x或--one-file-xystem 以一开始处理时的文件系统为准,若遇上其它不同的文件系统目录则略过。
    • -X<文件>或--exclude-from=<文件> 在<文件>指定目录或文件。
    • --exclude=<目录或文件> 略过指定的目录或文件。
    • --max-depth=<目录层数> 超过指定层数的目录后,予以忽略。
    • --help 显示帮助。
    • --version 显示版本信息。

    iostat命令

    ostat是一个用于收集显示系统存储设备输入和输出状态统计的简单工具。这个工具常常用来追踪存储设备的性能问题,其中存储设备包括设备、本地磁盘,以及诸如使用NFS等的远端磁盘。

    常用命令:

    iostat -x -k 2 100 # 2表示刷新间隔,100表示刷新次数

    image-20191213144330124

    iostat主要是用来监控磁盘I/O,首先输出了CPUs的平均数据(avg-cpu),我们可以看%iowait这一项,除此之外iostat还提供了一些更详细的I/O状态数据

    参数

    • /s: 每秒完成的读 I/O 设备次数。
    • w/s: 每秒完成的写 I/O 设备次数。
    • rkB/s: 每秒读K字节数.是 rsect/s 的一半,因为每扇区大小为512字节。
    • wkB/s: 每秒写K字节数.是 wsect/s 的一半。
    • avgrq-sz: 平均每次设备I/O操作的数据大小 (扇区)。
    • avgqu-sz: 平均I/O队列长度。
    • await: 平均每次设备I/O操作的等待时间 (毫秒)。
    • svctm: 平均每次设备I/O操作的服务时间 (毫秒)。
    • %util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。

    网络监控

    sar命令

    SAR是一个在Unix和Linux操作系统中用来收集、报告和保存CPU、内存、输入输出端口使用情况的命令。SAR命令可以动态产生报告,也可以把报告保存在日志文件中。

    常用命令

    sar -n DEV 3 100

    image-20191213145707669

    参数

    • IFACE:网络设备的名称
    • rxpck/s:每秒钟接收到的包数目
    • txpck/s:每秒钟发送出去的包数目
    • rxkB/s:每秒钟接收到的字节数
    • txkB/s:每秒钟发送出去的字节数

    netstat命令

    netstat命令一般用于检验本机各端口的网络连接情况,用于显示与IP、TCP、UDP和ICMP协议相关的统计数据。

    配置参数

    • -a, --all, --listening 显示所有连接中的Socket。
    • -n, --numeric 以数字形式显示地址和端口号。
    • -t, -–tcp 显示TCP传输协议的连线状况。
    • -u, -–udp 显示UDP传输协议的连线状况。
    • -p, --programs 显示正在使用socket的程序名/进程ID
    • -l, --listening 显示监控中的服务器的Socket。
    • -o, --timers 显示计时器。
    • -s, --statistics 显示每个网络协议的统计信息(比如SNMP)
    • -i, --interfaces 显示网络界面信息表单(网卡列表)
    • -r, --route 显示路由表

    常用命令

    netstat -aup 【输出所有UDP连接状况】

    image-20191213150018810

    • netstat -aup # 输出所有UDP连接状况
    • netstat -atp # 输出所有TCP连接状况
    • netstat -s # 显示各个协议的网络统计信息
    • netstat -i # 显示网卡列表
    • netstat -r # 显示路由表信息
    查看所有80端口的连接数
    netstat -nat|grep -i “80”|wc -l
    对连接的IP按连接数量进行排序
    netstat -anp | grep ‘tcp\|udp’ | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -n
    netstat -ntu | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -n
    netstat -ntu | awk ‘{print $5}’ | egrep -o “[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}” | sort | uniq -c | sort -nr
    查看TCP连接状态
    netstat -nat |awk ‘{print $6}’|sort|uniq -c|sort -rn
    netstat -n | awk ‘/^tcp/ {print $NF}’|sort|uniq -c|sort -rn
    netstat -n | awk ‘/^tcp/ {++S[$NF]};END {for(a in S) print a, S[a]}’
    netstat -n | awk ‘/^tcp/ {++state[$NF]}; END {for(key in state) print key,”\t”,state[key]}’
    netstat -n | awk ‘/^tcp/ {++arr[$NF]};END {for(k in arr) print k,”\t”,arr[k]}’
    netstat -ant | awk ‘{print $NF}’ | grep -v ‘[a-z]’ | sort | uniq -c
    查看80端口连接数最多的20个IP
    cat /www/web_logs/wzfou.com_access.log|awk ‘{print $1}’|sort|uniq -c|sort -nr|head -100
    tail -n 10000 /www/web_logs/wzfou.com_access.log|awk ‘{print $1}’|sort|uniq -c|sort -nr|head -100
    cat /www/web_logs/wzfou.com_access.log|awk ‘{print $1}’|sort|uniq -c|sort -nr|head -100
    netstat -anlp|grep 80|grep tcp|awk ‘{print $5}’|awk -F: ‘{print $1}’|sort|uniq -c|sort -nr|head -n20
    netstat -ant |awk ‘/:80/{split($5,ip,”:”);++A[ip[1]]}END{for(i in A) print A,i}’ |sort -rn|head -n20
    用tcpdump嗅探80端口的访问看看谁最高
    tcpdump -i eth0 -tnn dst port 80 -c 1000 | awk -F”.” ‘{print $1″.”$2″.”$3″.”$4}’ | sort | uniq -c | sort -nr |head -20
    查找较多time_wait连接
    netstat -n|grep TIME_WAIT|awk ‘{print $5}’|sort|uniq -c|sort -rn|head -n20
    查找较多的SYN连接
    netstat -an | grep SYN | awk ‘{print $5}’ | awk -F: ‘{print $1}’ | sort | uniq -c | sort -nr | more
    linux下实用iptables封ip段的一些常见命令:
    封单个IP的命令是:
    iptables -I INPUT -s 211.1.0.0 -j DROP
    封IP段的命令是:
    iptables -I INPUT -s 211.1.0.0/16 -j DROP
    iptables -I INPUT -s 211.2.0.0/16 -j DROP
    iptables -I INPUT -s 211.3.0.0/16 -j DROP
    封整个段的命令是:
    iptables -I INPUT -s 211.0.0.0/8 -j DROP
    封几个段的命令是:
    iptables -I INPUT -s 61.37.80.0/24 -j DROP
    iptables -I INPUT -s 61.37.81.0/24 -j DROP

    重启网络

    service network restart
    展开全文
  • 游戏服务器开发都要学什么

    万次阅读 多人点赞 2019-08-22 17:26:27
    一,游戏服务器开发工作介绍 近来遇到有很多人想从其它开发领域转到游戏服务器开发行业上来,他们或许觉得游戏服务器开发工资高,或许觉得做游戏服务器需要掌握的技术更高级,可以锻炼自己,或许觉得想换个环境等等...

    一,游戏服务器开发工作介绍

    近来遇到有很多人想从其它开发领域转到游戏服务器开发行业上来,他们或许觉得游戏服务器开发工资高,或许觉得做游戏服务器需要掌握的技术更高级,可以锻炼自己,或许觉得想换个环境等等。不管出于什么原因吧,做为一名几年的游戏服务器开发者,当然是持欢迎态度的,那么我就先介绍一下游戏服务器开发的工作吧,游戏服务器开发具体要做哪些工作呢?

    1,团队沟通

    基本上不管做什么开发,都是一个团队来完成的,游戏也是如此,游戏团队一般由老板,总经理,CTO(技术主管),主策划(领导一些人,包括数值策划,系统策划,特效策划),主美(领导一些人,包括原画,UI设计,特效动作设计),客户端主程(领导一些人,客户端程序员,客户端程序员...),服务器主程(领导一些人,包括服务器程序员,服务器程序员),外加运维。而游戏的大部分逻辑实现与逻辑数据验证都会放在服务器端,所以服务端程序需要明确了解策划的需求,要了解就需要沟通,沟通方式的正确与否,直接关系到功能的实现是否正确,由于游戏逻辑的复杂性,单纯的文档描述可能不会非常完整,不像其它行业需求文档就几百页,详细的图文并茂,制定好之后也很少变化。所以做为一名游戏程序员,一定要有良好的沟通方式和技巧。

    2,架构设计

    这个架构设计就像盖房子打基础,基础好,房子就稳固,基础不好,房子高了就容易倒。架构设计需要结合软件工程学来搞,它需要对服务器的整个流程有足够的了解,对需求的变化有足够的认识。架构的设计一般有几个特性。

    首先是易用性,架构一旦完成,在开发的时候就要方便使用,比如网络通信架构,设计好之后,其他开发者就不需要关心客户端的数据是怎么被传输到服务器端的,这个时候对于服务器开发者来说,只需要实现一些简单的接口,就可以直接对客户端发送来的请求进行处理操作。再比如说服务器端数据的存储与更新,开发者只需要写少量SQL语句或基本不用写,都由架构的底层代码完成,开发者只需要调用封装好的API,就可以把数据存入数据库而不用关心数据的最终流向,只需要关心实现逻辑就可以了。

    第二,可扩展性,可扩展性包括两个方面,一是代码的可扩展性,比如说游戏中的任务处理吧,一个游戏中任务可能有几十种,而且还可能不定时的增加,为了判断不同的任务类型该执行什么操作,最简单也是最差的写法是if else,想象一下,一个方法里面,有几十个if else,这简单是bug的理想诞生地呀。一种可行的做法是使用责任链模式(具体的请参考设计模式的实现),这样每种任务都有一个单独的类去处理它,而不会影响其它的类,符合开闭原则,相互关联少,越少越不容易出bug。二是部署的可扩展性,比如,如果在线人数突然增加或预期可能要增加,一台物理机器可能处理不过来这么多的请求,那怎么办?那就需要支持在不影响其它服务器运行的情况下,可以动态的添加机器。而当压力降低之后,又可以移除某些机器,合理利用资源。

    第三,高吞吐量,这个是指能尽量最大化的利用计算机固定的资源,去处理更多的请求,更快速的响应客户端。这就需要在服务器架构设计的时候考虑异步处理,减少IO等待时间(比如请求redis,存储数据库,和其它服务器通信)以及数据缓存。说到异步,一定会涉及到多线程,并发等相关的技术,所以架构设计的时候需要对这部分知识有足够的了解。

    第四,要考虑是否所有的功能模块都放在同一个进程中。也就是需不需要分布式开发,哪些功能需要单独拿出来。对于手机游戏来说,一般要求同时在线量比较小,功能比较单一,所有功能都在一个进程中,人数大量同时在线时,可以多部署几组进程。而对于大型网页游戏或客户端游戏来说,特别是有些大区或不分区的情况,单个功能访问量大,服务器就要考虑分布式部署开发了。

    架构设计一般需要有经验的开发者(项目主程)去搭建,新手可以做为了解,在接触到项目之后,可以按这个思路去理解项目的架构是怎么样构成的,如果让自己来做,能否模仿出来,有时间可以自己尝试去独立设计架构,锻炼自己的能力,为将来自己带项目做主程做好充值准备,机会都是留给有准备之人的。

     

    3,逻辑开发

    架构搭建完成之后,紧接着就是游戏服务器的逻辑开发,这时才开始真正去实现游戏需要的内容,比如注册,登陆,任务,活动,背包,组队战斗等。由于游戏逻辑可能需要的判断条件多,组合变化多,所以在游戏逻辑开发过程中,你会慢慢发现面向对象的重要性。逻辑开发是一个任重而道远的过程,同一个问题,可能有很多种实现方式,不同的实现方式对效率和吞吐量有很大的影响,所以就需要对需求功能的理解要深入,不同功能之间的关联要明确。对常用的设计模式要知道如何使用。比如像上面说的替换数量比较多的if else的方式。逻辑开发需要谨慎细心,而且一定要自己测试才可以,不然bug在不知不觉中就产生了。

    4,系统周边开发

    一个游戏成功的运营,需要很多服务去支持它,比如sdk接入,充值接入,日志统计,游戏运行管理系统(一般叫后台管理系统,是内部人员为了管理游戏的而开发的系统)。比如修改某个用户的等级,封号等。管理系统一般会用web开发,与游戏服务器通信。

     

     

    二,游戏类型与技术选择

    游戏服务器开发使用的技术取决于游戏的类型,不同的游戏类型,需要的游戏环境不一样,所使用的技术也不一样。但是在本质上都是一样的,都是面对数据,处理数据,不同的是面对的数量大小而已。

    1,PC类端游

    这类游戏在线人数庞大,游戏中要处理的数据也非常庞大。所以对服务器性能要求非常高,一般都是采用C++做为开发语言,C++可以直接操作内存数据,与操作系统直接交互,减少数据之间的复制,它运行效率高,处理速度快,是这类游戏开发的首选开发语言。服务器端采用分布式架构,把不同的模块分散在多台物理机上处理。需要学习的大致有C++编程,Linux网络编程、TCP/IP通讯协议、多线程编程再加数据库。它一般开发周期比较长,一个游戏的上线基本上需要三到五年。

    2,网页游戏

    这类游戏相对于端游来说,开发周期短,因为是网页游戏,游戏的界面展示依赖于网络传输,所在在画面和特效上会次于客户端游戏很多。游戏的特点主要集中在游戏的玩法上。但是对于服务器端来说,和端游类是差不多是一样的,有些公司之前是做端游的,他们就直接把端游的服务器架构拿来就可以使用,以完成快速开发。

    3,手机游戏

    手机类游戏目前是最火最热门的游戏,因为他的用户量大,用户占有时间长。但是手机游戏大多数是一般小游戏,功能简单,玩法单一,一般都是休闲娱乐的。现在也有一些稍微大型的MORPG游戏。所以手机游戏开发周期更短,上线更快。

    目前,游戏市场竞争激烈,当前服务器主流的开发语言是C++和Java,但是C++学习难度大,开发速度慢。为了满足游戏服务器快速开发,快速上线,所以一般来说我们都是使用Java语言来开发服务器。近年来,随着游戏市场的发展,游戏服务器开发技术因Java而生成了一套体系。可以供开发者选择。

     

    三,使用Java开发服务器需要学习什么

    Java语言,由于学习成本低,开发速度快,稳定性高,开源框架多,目前已成为网页游戏和手机游戏服务器开发的主要语言。咱们从系统的开发流程简单梳理一下服务器开发需要用到的技术。

    1,网络通信

    这个是首要实现的,如果没有网络通信,就没有服务器存在的必要了。网络通信就需要建立网络连接。目前网络通信有两种方式,一种是短连接,比如http,一种是长连接,比如socket,当然http也是基于socket的,socket是通信的基础。所以要对tcp/ip通信的知识有所了解,明白通信的原理。基于这两种网络通信,游戏服务器也分为两种,弱联网和强联网。弱联网的游戏一般是指一些小型的游戏,比如开心消消乐,连连看,以及一些卡牌养成类游戏,这类游戏一般几秒钟或几分钟再会与服务器同步一次数据,一般会使用短连接。而像一些arpg游戏,实时战斗类游戏,以及带同屏显示玩家的游戏,这类游戏与服务器交互信息频繁,一秒钟可能几十次,会采用长连接,避免每次连接重新建立消耗系统资源,提高通信效率。

    为了网络通信的效率,服务器要使用NIO(非阻塞网络通信)通信。它能支持大并发连接。Java NIO是多路复用IO,在多路复用IO模型中,会有一个线程不断去轮询多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作。因为在多路复用IO模型中,只需要使用一个线程就可以管理多个socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有socket读写事件进行时,才会使用IO资源,所以它大大减少了资源占用。目前基于此技术有很多开源框架,目前最热门的NIO异步网络通信框架是Netty,它目前已被应用到种大型的开源软件之后,比如RPC调用,阿里云的消 息队列组件RocketMQ,Spring cloud的网关组件也是用Netty实现的。为了便于新手学习,可以参考这个单服游戏服务器框:https://gitee.com/wgslucky/xinyue-alone-game-server  ,此开源框架实现了游戏服务器开发中常见的基本功能,比如网络通信,消息序列化与反序列化,逻辑处理,多线程封装,消息广播,消息加密解密,消息压缩与解压,连接管理,断包与粘包处理等。

    所以在网络通信这一块,如果是弱联网游戏,可以使用web那一套来开发游戏服务器,需要学习的技术一般有http原理,Json格式协议,servlet,Tomcat(也可以是其它web容器),spring等。如果是强联网游戏,要学习的技术有Netty或Mina可以选择一种,多线程以及线程池的应用。这是网络通信所必须掌握的。只要能把客户端发送的信息接收到,并解析成代码使用的明文,就是成功了一半了,剩下的事就是把代码封装好,方便逻辑开发调用!

    通信这块还要考虑消息的并发,长连接情况下,怎么处理断包,粘包问题,每个用户的消息处理的是不是有序的,如果有序会不会阻塞消息,如果无序会不会造成处理混乱,比如后到的消息先处理了,这些问题都要处理好,目前一般是保证同一个用户的消息要有序处理!

    2,数据存储

    网络通信调试好之后,不要急着做逻辑开发,还需要把数据如何存储理清楚!因为服务器端操作的全是数据,如果处理的不好,容易出bug,丢数据,这对游戏玩家来说是致命的,不可接受的!数据存储要考虑,

    一,数据如何存到数据库,是同步存储,还是异步存储!同步存储即将数操作完之后立刻写入数据库,异步操作即数据操作完之后先存储到内存缓存,然后由另外的线程或进程再同步到数据库!游戏中一般都是采用的异步存储方式,因为游戏并发量大,必须低延时,快速响应客户端!如果直接操作数据库太慢,会造成消息阻塞!内存缓存可先择的框架有redis,memcache,具体怎么同步到数据库,需要自己去设计了!

    二,数据接口如何设计,能不能用工作生成这些数据操作的代码,能不能不用写SQL语句,需是封装在底层,或由工具生成。编程是门艺术,在这就体现出来了,当然是仁者见仁,智者见智了!

    三,大并发情况下数据的一致性,像这类可能多线程操作的数据,一般是放在内存中,由锁来控制并发!所以对锁的使用要熟悉,不要出现死锁,或锁粒度过大,造成线程的长时间等待的情况!四,当数据量太大,一个数据库存储不了,数据该怎么分库分表!一种是水平划分,一种是垂直划分!具体的划分方式其它资料已有详细介绍,请自行查找阅读!目前有一个开源的分库框架mycat,是用JAVA写的,大家可以研究一下!

    四,目前常用的数据库有MySQL和MongoDB,MongoDB的优点是在开发过程中添加或删除字段不用操作数据库表,它是文档性数据库。两者各有利弊,可以都熟悉一下。

    3,逻辑开发

    逻辑开发就是实现游戏策划想象的各种游戏功能,比如,登录,物品使用,战斗结算等!逻辑开发代码量巨大,相互之间有很紧密的耦合性,所以每个功能模块一定要划分好!最好是接触下单元测试,写之前考虑一下是否方便单元测试,这样设计的代码会更加清晰,每个方法责任明确,不容易出bug!正是因为逻辑代码复杂,为了更好的管理代码,前辈们给我们总结了一些经验,就是著名的设计模式,所以学习一下设计模式对代码的管理有很大的好处!

    逻辑开发一般遇到的问题有:

    3.1,数据同步

    一说到数据同步或资源共享的时候,一般都会考虑到锁的使用。因为一份资源同时只能被一个线程访问才是安全的。Java的JDK中提供了一些锁,比如:synchronized,以及java.util.concurrent.lock包中的Lock对象,java.util.concurrent包中还提供了其它的一些原子操作的类,我们知道i++操作不是线程安全的,但是可以使用AtomicInteger中的getAndIncrement();方法代替,还有线程安全的ConcurrentHashMap哈稀Map。以及阻塞队列LinkedBlockingQueue等。都是逻辑开发中常用的处理数据同步的类。

    3.2,设计模式的使用

    使用设计模式,可以让代码更加清晰,可扩展性更强,维护性更佳,比如,任务系统,任务会有很多种类型,要获得任务数据时,在一开始写这个系统的时候,我是这样写的if(type == 1)做什么,else if(type == 2)做什么,else if(type == 3)......else if(type == 35) else等。如果需要添加新的类型,又要添加else,这些if else都在同一个方法中。最后都不敢动一块,就怕出bug。其实当一个方法中出现三个以上的if else将来还可能增加时,就应当考虑设计是不是有问题了,后来改成责任链模式或状态模式,就解决了这个问题。还有一个例子是,当一个值变化,要影响多个任务完成状态时,可以使用观察者模式或监听模式或订阅模式去实现,这样功能之间完全解耦,出问题的机率会很小很小。

    3.3,数据缓存框架的API使用

    目前主流使用的数据缓存框架有redis和memcache,虽然在逻辑开发前,主程会对这些进行一些封装,但是作为使用者还是需要对这些框架的客户端的使用要有所了解的。这些可以去阅读相关的文档。不是太难。

    4,程序部署与运行

    目前,大多数Java项目都采用maven管理 ,可以使用maven打包开发好的程序,程序一般运行在远程服务器上,比如云服务器。一般运行Java程序的远程服务器都是Linux系统,需要使用Linux命令操作,或写一些shell脚本去自动化部署管理一些程序。

    5,艰苦奋斗的精神

    首先,一定要让自己对这一行有兴趣,明确自己在这一行的技术选择,人生选择。很多人都知道,程序员加班是常有的事,坚持的住就做,坚持不了就再换一家公司做。

    综上所述,想做Java游戏服务器方面的开发要掌握的技术有以下一些:

    1,网络通信框架,Mina或Netty必须熟悉一种。而且自己必须要亲自搭建过,并明白其它原理。

    2,通信协议制定和处理断包粘包,这一般属于网络通信框架要解决的问题。

    3,数据缓存框架,redis或memcache选择一个,能熟练使用其客户端的命令。

    4,Java基础,Java NIO通信原理,Java集合的使用,Java多线程开发,Java锁的使用,在Java界,以后Spring MVC,Spring Boot,Spring Cloud是必不可少的。

    5,了解一些设计模式。最好能把23种设计模式都看一遍,并结合自己的开发经验,看哪些可以用到设计模式,但也不能死套设计模式,要灵活运用。

    6,熟悉使用Mysql数据库

    7,了解数据库连接池的一些框架,比如Mybatis,hibernate

    8,对Http协议熟悉,熟悉一种web容器,比如tomcat,了解其配置。

    9,对常用的一些Linux命令要熟悉使用。

    10,热爱学习,不断的充实自己,上面所说的只是入门技能而已,真正做起来要复杂的多,一定要让自己喜欢游戏这个行业,这样才能有动力做下去,做自己喜欢的工作还是比为了工作要好的!


     

     

                                                                        

     

    展开全文
  • 在日常开发中我们会做一些服务器部署的工作,对于开发来说,运维部署并不是我们的专项;有些命令不是经常使用,很快就会忘记;在这总结一下日常部署时常用的一些运维命令。 文件操作 tail tail 命令可用于查看文件的...

    Linux命令大全

    前言

    在日常开发中我们会做一些服务器部署的工作,对于开发来说,运维部署并不是我们的专项;有些命令不是经常使用,很快就会忘记;在这总结一下日常部署时常用的一些运维命令。

    文件操作

    tail

    tail 命令可用于查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件。

    命令格式:

    tail [参数] [文件]

    参数:

    • -f 循环读取
    • -q 不显示处理信息
    • -v 显示详细的处理信息
    • -c<数目> 显示的字节数
    • -n<行数> 显示文件的尾部 n 行内容
    • –pid=PID 与-f合用,表示在进程ID,PID死掉之后结束
    • -q, --quiet, --silent 从不输出给出文件名的首部
    • -s, --sleep-interval=S 与-f合用,表示在每次反复的间隔休眠S秒

    示例

    image-20191213103608175

    image-20191213103723510

    一般我们及时使用-f参数实时监控服务器日志。

    ll命令

    ll并不是linux下一个基本的命令,它实际上是ls -l的一个别名。

    Ubuntu默认不支持命令ll,必须用 ls -l,这样使用起来不是很方便。

    image-20191213105629006

    1、文件类型

    • “-”表示普通文件;
    • “d”表示目录;
    • “l”表示链接文件;
    • “p”表示管理文件;
    • “b”表示块设备文件;
    • “c”表示字符设备文件;
    • “s”表示套接字文件;

    2、文件属性

    • r(Read,读取权限):对文件而言,具有读取文件内容的权限;对目录来说,具有浏览目录的权限。
    • w(Write,写入权限):对文件而言,具有新增、修改文件内容的权限;对目录来说,具有删除、移动目录内文件的权限。
    • x(eXecute,执行权限):对文件而言,具有执行文件的权限;对目录来说,该用户具有进入目录的权限。
      另外,这里还有2个很特殊的属性,平时不怎么
    • s或S(SUID,Set UID):可执行的文件搭配这个权限,便能得到特权,任意存取该文件的所有者能使用的全部系统资源。请注意具备SUID权限的文件,黑客经常利用这种权限,以SUID配上root帐号拥有者,无声无息地在系统中开扇后门,供日后进出使用。
    • t或T(Sticky):/tmp和 /var/tmp目录供所有用户暂时存取文件,亦即每位用户皆拥有完整的权限进入该目录,去浏览、删除和移动文件。

    3、目录/文件个数

    对于目录文件,表示它的第一级子目录的个数。注意此处看到的值要减2才等于该目录下的子目录的实际个数。4

    4、所有者/分组

    表示该文件的所有者/创建者(owner)及其所在的组(group)。

    5、文件大小

    如果是文件,则表示该文件的大小,单位为字节。
    如果是目录,则表示该目录符所占的大小,并不表示该目录下所有文件的大小。

    6、修改日期

    该文件最后修改的日期时间。

    7、文件名称

    ln命令

    centos下的ln命令就相当于window下的建立快捷方式,链接文件甚至可以链接不存在的文件,这就产生一般称之为”断链”的现象,链接文件甚至可以循环链接自己。 类似于编程语言中的递归。
    软链接文件只是其源文件的一个标记,当删除了源文件后,链接文件不能独立存在,虽然仍保留文件名,但却不能查看软链接文件的内容了。

    ln -s 源文件 目标文件

    ln -s /opt/soft/node-v8.9.0-linux-x64/bin/vuepress /usr/bin
    

    -s 是代号(symbolic)的意思

    1. ln命令会保持每一处链接文件的同步性,也就是说,不论你改动了哪一处,其它的文件都会发生相同的变化
    2. ln的链接又软链接 和硬链接两种,软链接就是ln -s xx xx,它只会在你选定的位置上生成一个文件的镜像,不会占用磁盘空间,硬链接ln ,没有参数-s, 它会在你选定的位置上生成一个和源文件大小相同的文件,无论是软链接还是硬链接,文件都保持同步变化。

    参数

    • -b 删除,覆盖以前建立的链接
    • -d 允许超级用户制作目录的硬链接
    • -f 强制执行
    • -i 交互模式,文件存在则提示用户是否覆盖
    • -n 把符号链接视为一般目录
    • -s 软链接(符号链接)
    • -v 显示详细的处理过程

    cp命令

    cp [选项] 源文件(source) 目标文件或者目录(destination)

    • -a: 是指archive的意思,也说是指复制所有的目录
    • -d: 若源文件为连接文件(link file),则复制连接文件属性而非文件本身
    • -f: 强制(force),若有重复或其它疑问时,不会询问用户,而强制复制
    • -i: 若目标文件(destination)已存在,在覆盖时会先询问是否真的操作
    • -l: 建立硬连接(hard link)的连接文件,而非复制文件本身
    • -p: 与文件的属性一起复制,而非使用默认属性
    • -r: 递归复制,用于目录的复制操作
    • -s: 复制成符号连接文件(symbolic link),即“快捷方式”文件
    • -u: 若目标文件比源文件旧,更新目标文件

    cp -f package.json ./backup

    mv命令

    mv [选项] source destination

    • -f: force,强制直接移动而不询问
    • -i: 若目标文件(destination)已经存在,就会询问是否覆盖
    • -u: 若目标文件已经存在,且源文件比较新,才会更新

    系统监控命令

    内存监控

    free命令

    image-20191213111344785

    Linux free命令用于显示内存状态。

    free指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等。

    语法

    free [-bkmotV][-s <间隔秒数>]
    

    参数说明

    • -b  以Byte为单位显示内存使用情况。

    • -k  以KB为单位显示内存使用情况。

    • -m  以MB为单位显示内存使用情况。

    • -h  以合适的单位显示内存使用情况,最大为三位数,自动计算对应的单位值。单位有:

      B = bytes
      K = kilos
      M = megas
      G = gigas
      T = teras
      
    • -o  不显示缓冲区调节列。

    • -s<间隔秒数>  持续观察内存使用状况。

    • -t  显示内存总和列。

    • -V  显示版本信息。

    Men:表示物理内存统计

    Swap:表示硬盘上交换分区的使用情况

    total:表示物理内存总数(total=used+free)
    used:表示系统分配给缓存使用的数量(这里的缓存包括buffer和cache)
    free:表示未分配的物理内存总数
    shared:表示共享内存
    buffers:系统分配但未被使用的buffers 数量。
    cached:系统分配但未被使用的cache 数量。
    -/+ buffers/cache:表示物理内存的缓存统计

    (-buffers/cache) 内存数: (指的第一部分Mem行中的used – buffers – cached)
    (+buffers/cache) 内存数: (指的第一部分Mem行中的free + buffers + cached)
    (-buffers/cache)表示真正使用的内存数, (+buffers/cache) 表示真正未使用的内存数

    vmstat命令

    vmstat(Virtual Meomory Statistics,虚拟内存统计)是对系统的整体情况进行统计,包括内核进程、虚拟内存、磁盘、陷阱和 CPU 活动的统计信息。

    常用命令

    vmstat 2 2 【在2秒时间内进行2次采样】

    image-20191213140826375

    参数

    Procs(进程):

    • r:运行队列中进程数量
    • b:等待IO的进程数量

    Memory(内存):

    • swpd: 使用虚拟内存大小
    • free: 可用内存大小
    • buff: 用作缓冲的内存大小
    • cache: 用作缓存的内存大小

    Swap:

    • si: 每秒从交换区写到内存的大小
    • so: 每秒写入交换区的内存大小

    IO:(现在的Linux版本块的大小为1024bytes)

    • bi: 每秒读取的块数
    • bo: 每秒写入的块数

    system(系统):

    • in: 每秒中断数,包括时钟中断。【interrupt】
    • cs: 每秒上下文切换数。 【count/second】

    CPU(以百分比表示):

    • us: 用户进程执行时间(user time)
    • sy: 系统进程执行时间(system time)
    • id: 空闲时间(包括IO等待时间),中央处理器的空闲时间 。以百分比表示。
    • wa: 等待IO时间

    CPU监控

    top命令

    top命令可以实时动态地查看系统的整体运行情况,是一个综合了多方信息监测系统性能和运行信息的实用工具

    使用权限:所有使用者。

    语法

    top [-] [d delay] [q] [c] [S] [s] [i] [n] [b]
    

    参数说明

    • d : 改变显示的更新速度,或是在交谈式指令列( interactive command)按 s
    • q : 没有任何延迟的显示速度,如果使用者是有 superuser 的权限,则 top 将会以最高的优先序执行
    • c : 切换显示模式,共有两种模式,一是只显示执行档的名称,另一种是显示完整的路径与名称S : 累积模式,会将己完成或消失的子行程 ( dead child process ) 的 CPU time 累积起来
    • s : 安全模式,将交谈式指令取消, 避免潜在的危机
    • i : 不显示任何闲置 (idle) 或无用 (zombie) 的行程
    • n : 更新的次数,完成后将会退出 top
    • b : 批次档模式,搭配 “n” 参数一起使用,可以用来将 top 的结果输出到档案内

    image-20191213111809397

    mpstat命令

    mpstat是 Multiprocessor Statistics的缩写,是实时系统监控工具。其报告与CPU的一些统计信息,这些信息存放在/proc/stat文件中。在多CPU系统里,其不但能查看所有CPU的平均状况信息,而且能够查看特定CPU的信息。

    常用命令

    mpstat -P ALL 2 【ALL表示显示所有CPUs,也可以指定某个CPU;2表示刷新间隔】

    image-20191213141621315

    参数

    • CPU:处理器ID
    • %usr 在internal时间段里,用户态的CPU时间(%),不包含 nice值为负进程
    • %nice 在internal时间段里,nice值为负进程的CPU时间(%)
    • %sys 在internal时间段里,核心时间(%)
    • %iowait 在internal时间段里,硬盘IO等待时间(%)
    • %irq 在internal时间段里,硬中断时间(%)
    • %soft 在internal时间段里,软中断时间(%)
    • %steal 显示虚拟机管理器在服务另一个虚拟处理器时虚拟CPU处在非自愿等待下花费时间的百分比
    • %guest 显示运行虚拟处理器时CPU花费时间的百分比
    • %idle 在internal时间段里,CPU除去等待磁盘IO操作外的因为任何原因而空闲的时间闲置时间(%)

    进程监控

    ps命令

    ps命令用于查看进程统计信息

    常用参数:

    • a:显示当前终端下的所有进程信息,包括其他用户的进程。
    • u:使用以用户为主的格式输出进程信息。
    • x:显示当前用户在所有终端下的进程。
    • -e:显示系统内的所有进程信息。
    • -l:使用长(long)格式显示进程信息。
    • -f:使用完整的(full)格式显示进程信息。

    ps -aux

    最常用的方法是ps -aux,然后再利用一个管道符号导向到grep去查找特定的进程,然后再对特定的进程进行操作。

    image-20191213112328721

    列说明:

    • USER: 用户名
    • PID: 进程ID(Process ID)
    • %CPU: 进程的cpu占用率
    • %MEM: 进程的内存占用率
    • VSZ: 进程所使用的虚存的大小(Virtual Size)
    • RSS: 进程使用的驻留集大小或者是实际内存的大小,Kbytes字节。
    • TTY: 与进程关联的终端(tty)
    • STAT: 进程的状态:进程状态使用字符表示的(STAT的状态码)
    • TIME: 进程使用的总cpu时间
    • COMMAND: 正在执行的命令行命令

    ps -ef

    image-20191213112434230

    • UID: 用户ID(User ID)
    • PID: 进程ID(Process ID)
    • PPID: 父进程的进程ID(Parent Process id)
    • STIME: 启动时间
    • TTY: 与进程关联的终端(tty)
    • TIME: 进程使用的总cpu时间
    • CMD: 正在执行的命令行命令

    ps -ef | grep

    | 符号,是个管道符号,表示ps 和 grep 命令同时执行;

    grep 命令是查找(Global Regular Expression
    Print),能使用正则表达式搜索文本,然后把匹配的行显示出来;

    image-20191213112931855

    ps -l

    image-20191213112521888

    • F: 代表这个程序的旗标 (flag), 4 代表使用者为 super user
    • S: 睡眠 Sleeping 休眠中, 受阻, 在等待某个条件的形成或接受到信号。
    • UID: 用户ID(User ID)
    • PID: 进程ID(Process ID)
    • PPID: 父进程的进程ID(Parent Process id)
    • C: CPU 使用的资源百分比
    • PRI: 这个是 Priority (优先执行序) 的缩写,详细后面介绍
    • NI: 这个是 Nice 值,在下一小节我们会持续介绍
    • ADDR: 这个是 kernel function,指出该程序在内存的那个部分。如果是个 running的程序,一般就是 “-”
    • SZ: 使用掉的内存大小
    • WCHAN: 目前这个程序是否正在运作当中,若为 - 表示正在运作
    • TTY: 登入者的终端机位置
    • TIME: 使用掉的 CPU 时间。
    • CMD 所下达的指令为何

    其他

    查看进程的启动时间:
    ps -eo lstart 启动时间

    查看进程的运行时间
    ps -eo etime 运行多长时间.

    查看进程的pid、启动时间、运行时间
    ps -eo pid,lstart,etime | grep [ pid ]

    pstree命令

    以树状图的方式展现进程之间的派生关

    • pstree -p 显示当前所有进程的进程号和进程id

    • pstree -a 显示所有进程的所有详细信息,遇到相同的进程名可以压缩显示。

    pidof命令

    查找正在运行进程的PID

    image-20191213143350781

    其他

    uptime:显示系统总共运行了多长时间和系统的平均负载

    image-20191213143707179

    **pmap:**比较专业的查看内存与进程对应关系工具

    image-20191213143920584

    磁盘监控

    df命令

    image-20191213114301424

    • df -h查看磁盘使用情况
    • df -i 查看inode使用情况

    du命令

    Linux du命令用于显示目录或文件的大小。

    du会显示指定的目录或文件所占用的磁盘空间。

    参数说明

    • -a或-all 显示目录中个别文件的大小。
    • -b或-bytes 显示目录或文件大小时,以byte为单位。
    • -c或–total 除了显示个别目录或文件的大小外,同时也显示所有目录或文件的总和。
    • -D或–dereference-args 显示指定符号连接的源文件大小。
    • -h或–human-readable 以K,M,G为单位,提高信息的可读性。
    • -H或–si 与-h参数相同,但是K,M,G是以1000为换算单位。
    • -k或–kilobytes 以1024 bytes为单位。
    • -l或–count-links 重复计算硬件连接的文件。
    • -L<符号连接>或–dereference<符号连接> 显示选项中所指定符号连接的源文件大小。
    • -m或–megabytes 以1MB为单位。
    • -s或–summarize 仅显示总计。
    • -S或–separate-dirs 显示个别目录的大小时,并不含其子目录的大小。
    • -x或–one-file-xystem 以一开始处理时的文件系统为准,若遇上其它不同的文件系统目录则略过。
    • -X<文件>或–exclude-from=<文件> 在<文件>指定目录或文件。
    • –exclude=<目录或文件> 略过指定的目录或文件。
    • –max-depth=<目录层数> 超过指定层数的目录后,予以忽略。
    • –help 显示帮助。
    • –version 显示版本信息。

    iostat命令

    ostat是一个用于收集显示系统存储设备输入和输出状态统计的简单工具。这个工具常常用来追踪存储设备的性能问题,其中存储设备包括设备、本地磁盘,以及诸如使用NFS等的远端磁盘。

    常用命令:

    iostat -x -k 2 100 # 2表示刷新间隔,100表示刷新次数

    image-20191213144330124

    iostat主要是用来监控磁盘I/O,首先输出了CPUs的平均数据(avg-cpu),我们可以看%iowait这一项,除此之外iostat还提供了一些更详细的I/O状态数据

    参数

    • /s: 每秒完成的读 I/O 设备次数。
    • w/s: 每秒完成的写 I/O 设备次数。
    • rkB/s: 每秒读K字节数.是 rsect/s 的一半,因为每扇区大小为512字节。
    • wkB/s: 每秒写K字节数.是 wsect/s 的一半。
    • avgrq-sz: 平均每次设备I/O操作的数据大小 (扇区)。
    • avgqu-sz: 平均I/O队列长度。
    • await: 平均每次设备I/O操作的等待时间 (毫秒)。
    • svctm: 平均每次设备I/O操作的服务时间 (毫秒)。
    • %util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。

    网络监控

    sar命令

    SAR是一个在Unix和Linux操作系统中用来收集、报告和保存CPU、内存、输入输出端口使用情况的命令。SAR命令可以动态产生报告,也可以把报告保存在日志文件中。

    常用命令

    sar -n DEV 3 100

    image-20191213145707669

    参数

    • IFACE:网络设备的名称
    • rxpck/s:每秒钟接收到的包数目
    • txpck/s:每秒钟发送出去的包数目
    • rxkB/s:每秒钟接收到的字节数
    • txkB/s:每秒钟发送出去的字节数

    netstat命令

    netstat命令一般用于检验本机各端口的网络连接情况,用于显示与IP、TCP、UDP和ICMP协议相关的统计数据。

    配置参数

    • -a, --all, --listening 显示所有连接中的Socket。
    • -n, --numeric 以数字形式显示地址和端口号。
    • -t, -–tcp 显示TCP传输协议的连线状况。
    • -u, -–udp 显示UDP传输协议的连线状况。
    • -p, --programs 显示正在使用socket的程序名/进程ID
    • -l, --listening 显示监控中的服务器的Socket。
    • -o, --timers 显示计时器。
    • -s, --statistics 显示每个网络协议的统计信息(比如SNMP)
    • -i, --interfaces 显示网络界面信息表单(网卡列表)
    • -r, --route 显示路由表

    常用命令

    netstat -aup 【输出所有UDP连接状况】

    image-20191213150018810

    • netstat -aup # 输出所有UDP连接状况
    • netstat -atp # 输出所有TCP连接状况
    • netstat -s # 显示各个协议的网络统计信息
    • netstat -i # 显示网卡列表
    • netstat -r # 显示路由表信息
    查看所有80端口的连接数
    netstat -nat|grep -i “80”|wc -l
    对连接的IP按连接数量进行排序
    netstat -anp | grep ‘tcp\|udp’ | awk{print $5}| cut -d: -f1 | sort | uniq -c | sort -n
    netstat -ntu | awk{print $5}| cut -d: -f1 | sort | uniq -c | sort -n
    netstat -ntu | awk{print $5}| egrep -o “[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}| sort | uniq -c | sort -nr
    查看TCP连接状态
    netstat -nat |awk{print $6}|sort|uniq -c|sort -rn
    netstat -n | awk ‘/^tcp/ {print $NF}|sort|uniq -c|sort -rn
    netstat -n | awk ‘/^tcp/ {++S[$NF]};END {for(a in S) print a, S[a]}netstat -n | awk ‘/^tcp/ {++state[$NF]}; END {for(key in state) print key,”\t”,state[key]}netstat -n | awk ‘/^tcp/ {++arr[$NF]};END {for(k in arr) print k,”\t”,arr[k]}netstat -ant | awk{print $NF}| grep -v ‘[a-z]| sort | uniq -c
    查看80端口连接数最多的20个IP
    cat /www/web_logs/wzfou.com_access.log|awk{print $1}|sort|uniq -c|sort -nr|head -100
    tail -n 10000 /www/web_logs/wzfou.com_access.log|awk{print $1}|sort|uniq -c|sort -nr|head -100
    cat /www/web_logs/wzfou.com_access.log|awk{print $1}|sort|uniq -c|sort -nr|head -100
    netstat -anlp|grep 80|grep tcp|awk{print $5}|awk -F: ‘{print $1}|sort|uniq -c|sort -nr|head -n20
    netstat -ant |awk ‘/:80/{split($5,ip,”:”);++A[ip[1]]}END{for(i in A) print A,i}|sort -rn|head -n20
    用tcpdump嗅探80端口的访问看看谁最高
    tcpdump -i eth0 -tnn dst port 80 -c 1000 | awk -F”.” ‘{print $1″.”$2″.”$3″.”$4}| sort | uniq -c | sort -nr |head -20
    查找较多time_wait连接
    netstat -n|grep TIME_WAIT|awk{print $5}|sort|uniq -c|sort -rn|head -n20
    查找较多的SYN连接
    netstat -an | grep SYN | awk{print $5}| awk -F: ‘{print $1}| sort | uniq -c | sort -nr | more
    linux下实用iptables封ip段的一些常见命令:
    封单个IP的命令是:
    iptables -I INPUT -s 211.1.0.0 -j DROP
    封IP段的命令是:
    iptables -I INPUT -s 211.1.0.0/16 -j DROP
    iptables -I INPUT -s 211.2.0.0/16 -j DROP
    iptables -I INPUT -s 211.3.0.0/16 -j DROP
    封整个段的命令是:
    iptables -I INPUT -s 211.0.0.0/8 -j DROP
    封几个段的命令是:
    iptables -I INPUT -s 61.37.80.0/24 -j DROP
    iptables -I INPUT -s 61.37.81.0/24 -j DROP
    

    重启网络

    service network restart

    展开全文
  • 基于VC开发linux服务器 程序指南(V1.0) 2020-07-08 1 概述.... 3 2 背景.... 3 3 采用本方案目的.... 4 4 适用领域.... 4 5 总体思路.....

     

                                     基于VC++开发linux服务器程序指南

     

     

     

    1.  概述

    在此仅把此文献给那些奋斗在一线的c/c++开发人员,希望可以帮到大家。这是作者多年跨平台编程经验的总结,以文档的形式供大家参考。

     

    1.  背景

    本人一直基于微软Microsoft Visual C++(以下简称VC)开发后台服务器程序,

    由于项目需要,程序需要运行在linux/unix(以下的linux代表Linux和unix)

    平台。但是本人已经非常熟悉和依赖VC,不打算再掌握linux下的开发工具进

    行开发。 如果采用linux特有的API函数,windows源程序需要进行大量的修

    改。在朋友的指点下,采用基于VC开发、调试、测试,然后移植到linux/g++

    进行编译运行。随着移植文件的完善和编码兼容性的优化,现在基本上可以做到VC的工程迁移到linux,只需要做很少或不做修改即可编译通过。

     

    1.  采用本方案目的

    采用本方案希望达成以下几点目的。

    1、充分利用微软公司VC强大的可视化编辑、调试功能。同时可使用配套的版本管理工具

       和Visual Assit X开发助手,有助于提高开发过程的自动化和开发效率

    2、实现开发服务器程序跨平台(windows、linux、unix等)、跨开发工具(VC、g++等)。

    3、只需在VC下一次编写源码、一次调试、一次测试,然后到其他平台只需要编译、运行

       即可。

    4、加快代码的编写速度和质量。

    5、加快代码调试速度和质量。

    6、加快程序乃至整个项目的上线进度。

     

    本方案主要是移植大部分常用的功能函数,无意移植所有的功能函数。首先是有些函数由于操作系统的差异无法移植,或者移植代价太大完全没有必要。

     

    给开发人员提供多一种跨平台项目开发的选择,无意也不可能取代linux/g++开发工具和其他跨平台开发解决方案。

     

    本方案最适合开发后台服务器程序,如果开发人员要应用于其他领域,需要慎重考虑可行性。

     

    1.  适用领域

    本文适合以下读者:

     

    1、本文适用读者是面向VC开发人员,他们需要进行linux下进行开发服务器程

    序。 采用本方案对VC开发人员技能要求:熟悉VC开发工具、熟悉C/C/++、熟

    悉标准库(可选)、熟悉windows核心编程(多线程、线程同步等)、Socket编

    程、了解linux和g++基本知识,不要求掌握MFC。

     

    2、现有的windows平台下的VC工程需要移植到linux平台下运行。

     

    3、针对linux/g++ 开发人员也具有参考意义。

     

    采用本方案的领域:后台服务器程序。

    1.  总体思路

    1、采用VC开发工具进行服务器程序开发,源码中不使用任何MFC的类

       库,可以采用跨平台的第三方类库(标准库、Boost库),或采用我方提供的相

       关功能类库。开发过程中只采用标准的C函数或者Windows系统API函数。

     

    2、在linux下利用gcc/g++编写移植文件,把windows的API用linux/g++提供的

       API进行封装,还有就是把部分只有VC特有的c函数也用gcc/g++进   

       行封装。

     

    3、利用VC/windows上进行开发、调试、测试。

     

    4、把代码文件复制到linux下,然后在把移植文件也加入到工程中,进行编译。

       一般情况下可以编译通过,即使编译过程中有错误,也可以通过调整达到代

       码兼容的效果。

     

    7、用gcc/g++进行编译,生成可执行文件,运行可执行文件进行测试。

     

    说明:

    1、如果是开发动态库/静态库和上述过程类似。

    2、作者会提供linux的2个移植源码文件:PortLinux.cpp、PortLinux.h

     

    1.  开发工具和操作系统要求
    2.  Windows/VC

     

    1、建议采用/VC 2008及以上版本,同时安装Visual Assist X开发助手。

    2、操作系统

       1)桌面系统采用64位Win7及以上版本。

       2)服务器系统采用Windows 2008x64及以上版本

    3、其他

        如果只是开发32位程序,建议安装VC6,同时安装Visual Assist X开发助

        手。

     

    1.  linux/g++

    作者开发选用RedHat和CentOS 的linux,如果开发人员希望在其他厂商的linux上开发,需要进行进一步的测试

     

    1.  unix/g++

    作者没有在unix下开发的经历,如果开发人员在unix(HP_UX、AIX、Solaris、BSD)下采用本方案,需要进行进一步测试作者提供的移植文件,如果有必要可进行修改和完善。

     

    1.  linux移植工作

     

    需要在linux/g++下编写移植文件,作者提供2个移植文件PortLinux.cpp和

    PortLinux.h,开发人员需要在自己的源码文件(c、cpp、h)中包含(#include)PortLinux.h文件。

     

    编写移植文件需要熟悉linux/gcc/g++的开发人员协助VC开发人员一起编写,移植文件需要在linux 下编译、调试、测试,后续就可以把移植文件加入到g++工程里进行整体编译。移植工作只需要做一次即可,但是做到可以一劳永逸。

     

    1.  常用宏定义

     

    #define INFINITE    0xFFFFFFFF

    #define WINAPI

     

    1.  布尔类型常量宏定义

     

    #define FALSE  0

    #define TRUE  1

     

     

    1.  数据类型定义

    typedef int BOOL;

    typedef void* HANDLE;

    typedef void* POSITION;

    typedef void* LPVOID;

    typedef void* HINSTANCE;

    typedef char* LPCTSTR;

    typedef unsigned int DWORD;

    typedef unsigned short WORD;

    typedef unsigned char BYTE;

    typedef int INT;

    typedef int INT32;

    typedef unsigned int UINT32;

    typedef long long int INT64;

    typedef unsigned long long int UNIT64;

    typedef wchar_t WCHAR;

    typedef void* THREAD_RETURN_TYPE;

     

    typedef struct _LARGE_INTEGER

    {

           long long int QuadPart;

    }LARGE_INTEGER;

     

    1.  初始化函数

    初始化全局变量:获取操作系统开机时间

     

    InitSysPort();

     

    1.  线程相关移植
    2.  类型定义

    1、在移植文件中进行数据类型定义LPSECURITY_ATTRIBUTES;

        typedef char* LPSECURITY_ATTRIBUTES;

        用途:用于封装CreateThread函数。

     

    2、LPTHREAD_START_ROUTINE

     

           extern "C"

           {

                  typedef void* (*LPTHREAD_START_ROUTINE)(void *);

           }

     

       用途:用于封装CreateThread函数。

     

        1.  相关函数

     

          1.  CreateThread函数

     

    功能:CreateThread是一种微软在Windows API中提供了建立一个新的线程的

        函数,该函数在主线程的基础上创建一个新线程。线程终止运行后,线程对

        象仍然在系统中,必须通过CloseHandle函数来关闭该线程对象。

     

       函数定义如下:

            HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,

                                       unsigned int dwStackSize,

                                       LPTHREAD_START_ROUTINE lpStartAddress,

                                       LPVOID lpParameter,

                                       unsigned int dwCreationFlags,

                                       unsigned long* lpThreadId);

     

       函数使用说明:

       1、其中第1、5参数在linux/g++没有意义,填写默认参数。

         1)第1个参数lpThreadAttributes,赋值为NULL。

         2)第5个参数dwCreationFlags,赋值为0。

     

       2、执行成功返回非NULL的句柄。

     

          1.  TerminateThread函数

     

       功能:TerminateThread线程外终止一个线程,用于强制终止线程。

     

      函数声明如下:

       BOOLTerminateThread( HANDLE hThread, DWORDdwExitCode);

     

    bool SetThreadPriority(HANDLE hThread, int nPriority);

     

          1.  GetCurrentThreadId函数

     

    获取当前线程一个唯一的线程标识符。

     

    int GetCurrentThreadId ();

     

          1.  SetThreadPriority函数

    暂时没有实现。

     

     

          1.  其他说明

    1、不要封装暂停线程(SuspendThread)和恢复线程(ResumeThread)函数,主要是没有必要使

       用这2个函数,另外在linux下也没有类似的函数和功能。

     

    1.  同步对象

     

    1.  通用宏定义

     

    #define WAIT_OBJECT_0              00

    #define WAIT_TIMEOUT               01

     

     

    1.  临界区(CriticalSection)

    用于同一个进程内多线程间的互斥。

          1.  数据类型定义

    typedef pthread_mutex_t CRITICAL_SECTION;

    typedef CRITICAL_SECTION* LPCRITICAL_SECTION;

     

          1.  相关函数移植说明

    采用linux的互斥锁进行简单封装即可。

     

    void InitializeCriticalSection(CRITICAL_SECTION* lpCriticalSection)

    {

             pthread_mutex_init(lpCriticalSection, NULL);

    }

     

    void EnterCriticalSection(CRITICAL_SECTION* lpCriticalSection)

    {

             pthread_mutex_lock(lpCriticalSection);

    }

     

    BOOL TryEnterCriticalSection(CRITICAL_SECTION* lpCriticalSection)

    {

             int nret;

             nret = pthread_mutex_trylock(lpCriticalSection);

             if(nret == 0)

             {

                       return TRUE;

             }

             else

             {

                       return FALSE;

             }

    }

     

    void LeaveCriticalSection(CRITICAL_SECTION* lpCriticalSection)

    {

             pthread_mutex_unlock(lpCriticalSection);

    }

     

    void DeleteCriticalSection(CRITICAL_SECTION* lpCriticalSection)

    {

           pthread_mutex_destroy(lpCriticalSection);

    }

     

    1.  互斥锁(mutex)

    用于同一个进程内多线程间的互斥锁的操作,暂时没有实现多进程间的互斥锁操作。

     

    HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName);

     

    1、第1个参数lpMutexAttributes调用时填写NULL。

    2、第4个参数lpName调用时填写NULL。

     

    bool ReleaseMutex(HANDLE hMutex);

     

    1.  信号量(Semaphore)

    用于同一个进程内多线程间的信号量的操作,暂时没有实现多进程间的信号量操作。

     

    具体实现采用linux的互斥锁(pthread_mutex_t mutex)和条件变量

    (pthread_cond_t cond)组合实现。

       

    HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,

                         int lInitialCount,

                         int lMaximumCount,

                         LPCTSTR lpName );

     

    参数说明:

    1、第1个参数lpSemaphoreAttributes调用时填写NULL。

    2、第4个参数lpName调用时填写NULL。

     

    bool ReleaseSemaphore(HANDLE hSemaphore,

                         int lReleaseCount,

                         long* lpPreviousCount);

     

    1.  事件(Event)

    用于同一个进程内多线程间的事件的操作,暂时没有实现多进程间的事件操作。

     

    具体实现采用linux的互斥锁(pthread_mutex_t mutex)和条件变量

    (pthread_cond_t cond)组合实现。

     

          1. 相关函数移植说明

     

    HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,

                                   bool bManualReset,

                                   bool bInitialState,

                                   LPCTSTR lpName);

     

           参数说明:

           1、第1个参数lpEventAttributes调用时填写NULL。

           2、第4个参数lpName调用时填写NULL。

     

    bool SetEvent(HANDLE hEvent);

     

    bool ResetEvent(HANDLE hEvent);

     

    bool PulseEvent(HANDLE hEvent); 此函数无用,不需要实现。

     

        1.  单写多读锁(SRWLOCK)

     

            1.  数据类型定义

    把linux下的读写锁简单封装为windows形式的读写锁。

    typedef struct _SRWLOCK

    {

           pthread_rwlock_t rwLock;

    }SRWLOCK;

    typedef SRWLOCK* PSRWLOCK;

    typedef SRWLOCK* LPSRWLOCK;

     

          1.  相关函数移植说明

    采用linux的读写锁进行简单封装即可。

     

    1、初始化读写锁

    void InitializeSRWLock(LPSRWLOCK pLock)

    {

             pthread_rwlock_init(&(pLock->rwLock), NULL);

    }

     

    2、以独占写方式使用读写锁

    void AcquireSRWLockExclusive(LPSRWLOCK pLock)

    {

             pthread_rwlock_wrlock(&(pLock->rwLock));

    }

     

    3、以共享读方式使用读写锁

    void AcquireSRWLockShared(LPSRWLOCK pLock)

    {

             pthread_rwlock_rdlock(&(pLock->rwLock));

    }

     

    4、释放之前以独占写方式使用的读写锁

    void ReleaseSRWLockExclusive(LPSRWLOCK pLock)

    {

             pthread_rwlock_unlock(&(pLock->rwLock));

    }

     

    5、释放之前以共享读方式使用的读写锁

    void ReleaseSRWLockShared(LPSRWLOCK pLock)

    {

             pthread_rwlock_unlock(&(pLock->rwLock));

    }

     

    6、删除读写锁,使之不可再被访问使用。

    void DeleteSRWLock(LPSRWLOCK pLock)

    {

             pthread_rwlock_destroy(&(pLock->rwLock));

    }

     

    注意:windows的API中没有DeleteSRWLock这个函数,为了保持代码兼容新增此函数,在linux和windows下的移植文件中都需要声明和定义此函数。

    在Windows的移植文件中实现代码如下:

     

    void DeleteSRWLock(LPSRWLOCK pLock)

    {

             return;

    }

    如上所示,只需简单的返回即可,纯粹是为了兼容linux代码。

     

        1.  等待同步对象(WaitForSingleObject)

     

    WaitForSingleObject 函数用来检测 hHandle 事件的信号状态,当函数的执行时间超过 dwMilliseconds 就返回,但如果参数 dwMilliseconds  INFINITE 时函数将直到相应时间事件变成有信号状态才返回,否则就一直等待下去,直到 WaitForSingleObject 有返回直才执行后面的代码。

     

    DWORD WaitForSingleObject(HANDLE hObject, //指明一个内核对象的句柄
    DWORD dwMilliseconds); //等待时间

     

    WAIT_OBJECT_0,WAIT_TIMEOUT,WAIT_FAILED,WAIT_IO_COMPLETION。

    1.  关闭句柄(CloseHandle)

    关闭句柄函数如下:

       bool CloseHandle(HANDLE hObject);

     

    函数用途:

    1、用于关闭线程的句柄,线程的句柄由CreateThread函数返回。

    2、关闭同步对象的句柄:互斥锁(Mutex)、事件(Event)、信号量(Semaphore)

    3、其他核心对象句柄。

     

    具体实现参考作者提供的移植文件。

     

      1.  文件映射(FileMapping)

    暂时没有实现,读者如果需要可自行实现。

     

    1.  字符串函数

    实现了对以下常用字符串相关函数的封装,这些函数是作者经常使用但是linux没有提供相应的库函数,需要在移植文件中实现封装。

     

    int strcmpi(const char *string1, const char *string2);

    int stricmp(const char *string1, const char *string2);

    int strnicmp(const char *string1, const char *string2, int nCount);

     

    void strlower(char* sValue);

    void strupper(char* sValue);

     

    char* _strrev(char* sString);

     

    char* itoa(int value, char* string, int radix);

    char* _itoa(int value, char* string, int radix);

    char* _ultoa(unsigned long value, char* string, int radix);

    char* ultoa(unsigned long value, char* string, int radix);

    int64 _atoi64(const char* string);

    char* _i64toa(int64 value, char* string, int radix);

    char* _ui64toa(uint64 value, char* string, int radix);

    uint64 _atoui64(char* sValue);

    uint _atoui(char* sValue);

     

    1.  时间函数

     

        1.  数据类型定义

     

    typedef struct _FILETIME

    {

        unsigned long dwLowDateTime;

        unsigned long dwHighDateTime;

    } FILETIME, *PFILETIME, *LPFILETIME;

     

    typedef struct _SYSTEMTIME

    {

        unsigned short wYear;

        unsigned short wMonth;

        unsigned short wDayOfWeek;

        unsigned short wDay;

        unsigned short wHour;

        unsigned short wMinute;

        unsigned short wSecond;

        unsigned short wMilliseconds;

    } SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;

     

        1.  相关函数移植说明

    BOOL SystemTimeToFileTime(LPSYSTEMTIME pSysTime, LPFILETIME pFileTime)

    {

             int64 nRet;

             nRet = SystemTimeToInt(pSysTime);

             memcpy(pFileTime, &nRet, 8);

             return TRUE;

    }

     

    BOOL FileTimeToSystemTime(LPFILETIME pFileTime, LPSYSTEMTIME pSysTime)

    {

             int64 nRet;

             memcpy(&nRet, pFileTime, 8);

             IntToSystemTime(nRet, pSysTime);       

             return TRUE;

    }

     

    void GetLocalTime(LPSYSTEMTIME pSystemTime)

    {

             struct timeval now;

             gettimeofday(&now, NULL);

     

         struct tm* LocalTime;

             LocalTime = localtime(&(now.tv_sec));

     

             pSystemTime->wYear = 1900 + LocalTime->tm_year;

             pSystemTime->wMonth = LocalTime->tm_mon + 1;

             pSystemTime->wDay = LocalTime->tm_mday;

             pSystemTime->wHour = LocalTime->tm_hour;

             pSystemTime->wMinute = LocalTime->tm_min;

             pSystemTime->wSecond = LocalTime->tm_sec;

             pSystemTime->wMilliseconds = (now.tv_usec)/1000;

             pSystemTime->wDayOfWeek = LocalTime->tm_wday;    

    }

     

    void GetSystemTime(LPSYSTEMTIME pSystemTime)

    {

             struct timeval now;

             gettimeofday(&now, NULL);

     

        struct tm* LocalTime;

             LocalTime = gmtime(&(now.tv_sec));

     

             pSystemTime->wYear = 1900 + LocalTime->tm_year;

             pSystemTime->wMonth = LocalTime->tm_mon + 1;

             pSystemTime->wDay = LocalTime->tm_mday;

             pSystemTime->wHour = LocalTime->tm_hour;

             pSystemTime->wMinute = LocalTime->tm_min;

             pSystemTime->wSecond = LocalTime->tm_sec;

             pSystemTime->wMilliseconds = (now.tv_usec)/1000;

             pSystemTime->wDayOfWeek = LocalTime->tm_wday;    

    }

     

        1.  线程休眠函数(Sleep)

     

    void Sleep(unsigned int dwMilliseconds)

    {

             timespec tt;

             tt.tv_sec = dwMilliseconds/1000;

             tt.tv_nsec = (dwMilliseconds%1000)*1000000;

             nanosleep(&tt, NULL);

    }

     

        1.  获取系统启动毫秒数(GetTickCount)

     

    需要实现GetTickCount()、GetTickCount64()

     

    DWORD GetTickCount();

     

     

     

    int64 GetTickCount()

    {

           struct timeval tv;

           int64 qwVal;

           gettimeofday(&tv, NULL);

           qwVal = tv.tv_sec*1000 + tv.tv_usec/1000;

           return qwVal;

    }

     

    1.  socket编程

     

    1.  相关通用宏定义

     

           #define INVALID_SOCKET               -1

           #define SOCKET_ERROR              -1

           #define SD_BOTH                                   SHUT_RDWR

           #define SOCKET_SEND_DEFAULT_FLAG MSG_NOSIGNAL                                 

           #define MAKEWORD(x,y)             (((x<<8)&0xFF00)|(y&0xFF))

     

        1.  相关数据类型定义

     

           typedef int SOCKET;

     

           typedef struct WSAData

           {

                  unsigned short wVersion;

               unsigned short wHighVersion;

               char szDescription[20];

               char szSystemStatus[20];

               unsigned short iMaxSockets;

               unsigned short iMaxUdpDg;

               char* lpVendorInfo;

           }WSADATA;

           typedef WSADATA* LPWSADATA;

     

        1.  相关函数移植说明

     

          1.  WSAStartup函数

    本函数必须是应用程序或DLL调用的第一个Windows Sockets函数.它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节.应用程序或DLL只能在一次成功的WSAStartup()调用之后才能调用进一步的Windows Sockets API函数.

     

           此函数对于linux没有意义,封装此函数只需简单的返回0即可,在移植文件中此函

           数声明和定义如下:

       

        int WSAStartup(unsigned short wVersionRequested, LPWSADATA lpWSAData)

        {

                  return 0;

        }

     

          1.  WSACleanup函数

    应用程序在完成对请求的Socket库使用后,要调用WSACleanup函数来解除与Socket库的绑定并且释放Socket库所占用的系统资源。

     

           此函数对于linux没有意义,封装此函数只需简单的返回0即可,在移植文件中此函

           数声明和定义如下:

     

           int WSACleanup(void)

           {

                         return(0);

           }

     

          1.  closesocket函数

    本函数用来关闭一个套接字。在移植文件中此函数声明和定义如下:

     

    int closesocket(SOCKET s)

    {

            close(s);

            return 0;

    }

     

          1.  ioctlsocket函数

    本函数用于设置套接口相关的操作参数,在移植此函数声明和定义如下:

     

    int ioctlsocket(SOCKET s, unsigned long dwCmd, unsigned long* pArg)

    {

           return(ioctl(s, nCmd, pArg));

    }

     

          1.  其它函数使用说明

    以下函数不需要移植,windows和 linux的函数定义和语义是相同或类似。

    1、socket()

       生成一个套接字。

    2、bind()

       绑定套接字的本地IP地址和端口号。

    3、listen()

       用于TCP监听套接字。

    4、accept()

       接收来自外部的TCP连接请求。

     

    5、connect()

       连接远程TCP服务器。

     

    6、recv()

       用于TCP连接接收数据。

    7、send()

     

    8、recvfrom()

       用于UDP连接接收数据。

     

    9、sendto()

       用于UDP连接发送数据。

     

    10、select()相关函数,实现多路IO复用。

       FD_ZERO、FD_SET、FD_ISSET、FD_CLR

     

        1.  关于大并发TCP编程

    Linux或windows平台采用select函数的多路复用方案, 最大支持上千个并发TCP连接访问。如果想支持几万、几十万乃至上百万的TCP并发连接,在linux下需要采用epoll网络编程,但是在windows/VC平台上不支持epoll的开发接口,只是提供完成端口方式。作者通过使用VC的select函数封装成epoll的函数形式,这样就可以在VC上使用epoll函数进行开发、调试、测试,由于linux本来就支持 epoll,移植过去毫无障碍。关于在VC下用select相关函数封装成epoll函数作者在专门的开发手册中会详细介绍。

     

    作者体会: Windows对支持大TCP并发很糟糕,即使使用完成端口。 强烈建议使用linux/epoll的方案实现支持TCP大规模访问。

     

    1.  读取配置文件函数

    windows提供以下2个API函数读取Windows的ini配置文件。

     

    UINT GetPrivateProfileInt(const char* lpAppName,

                                              const char* lpKeyName,

                                               int nDefault,

                                              const char* lpFileName);

     

    unsigned int GetPrivateProfileString(const char* lpAppName,

                                                       const char* lpKeyName,

                                                       const char* lpDefault,

                                                       char* lpReturnedString,

                                                       unsigned int nSize,

                                                       const char* lpFileName);

     

     

    暂时作者没有提供修改配置文件的函数WritePrivateProfileString()。

     

    1.  动态库相关函数

    1、加载动态库函数

    HINSTANCE LoadLibrary(char* sFileName)

    {

             return(dlopen(sFileName, RTLD_LAZY));

    }

     

    2、获取动态库函数的地址

    void* GetProcAddress(HINSTANCE hInst, char* sFunctionName)

    {

             return(dlsym(hInst, sFunctionName));

    }

     

    3、卸载动态库函数

    BOOL FreeLibrary(HINSTANCE hInst)

    {

             int nRet;

             nRet = dlclose(hInst);

             if(nRet == 0)

             {

                       return TRUE;

             }

             else

             {

                       return FALSE;

             }

    }

     

    1.  文件/目录兼容

     

    1.  宏定义

    由于windows目录采用符号:\ 分隔,而linuxmu.lu采用符号/分隔,源码中的目录必须采用以下的宏定义。

     

    #define PATH_SP     '/'

    #define PATH_SPS   "/"

     

    实例代码:

           char sRootDir[1024];

           sprintf(sRootDir, "%s%cmain.ini", GetCurrentDir(), PATH_SP);

     

    假设函数GetCurrentDir()返回当前路径。

     

    1.  相关函数

    作者提供了以下目录和文件操作的函数:

     

    1、获取当前路径

           int GetCurrentDirectory(int len, char* sBuf);

     

    2、 删除指定文件

       BOOL DeleteFile(char* sFile);

     

    3、创建目录

       BOOL CreateDirectory(char* sFilePath, void* pPara);

     

    4、移动文件

        BOOL MoveFile(char* sSourFile, char* sDestFile);

     

    5、 文件重命名

       rename(char* sSourFile, char* sDestFile);

     

    1.  系统错误码

    常用错误码的宏定义如下:

    #define WSAEWOULDBLOCK                 EWOULDBLOCK

    #define PEINPROGRESS                          EINPROGRESS

    #define ERROR_ALREADY_EXISTS        EEXIST

     

    以下函数返回线程当前的错误码,函数声明和定义如下:

     

           int WSAGetLastError()

           {

                  return errno;

           }

     

           int GetLastError()

           {

                  return errno;

           }

     

    1.  VC工程源码兼容性调整

     

    1.  建议

    1、不试用任何MFC类库,推荐试用标准库跨平台的第三方功能类库。

    2、文件操作尽可能试用FILE(fopen、fclose、fseek、fread、fwrite)以及标准的IO函数(open、

       close、read、write等)

    3、c/c++语法选取VC和GCC/G++共同支持的语法规则

    4、socket编程不要实用VC特有支持异步事件的函数WSA,实用标准的socket函数。

    1.  准备移植文件

    作者提供了移植文件为: PortWindows.cpp、PortWindows.h,开发人员把这2个文件加入到VC的工程中进行编译。

    1.  宏定义

    在移植文件中进行以下宏定义

     

    #define MSG_NOSIGNAL 0

     

      1.  socket函数调整

    1、send()函数

      用于TCP连接发送数据,注意第4个参数在VC下默认填写0,建议在使用

      MSG_NOSIGNAL宏定义。

     

      示例代码如下:

       int nRet;

       nRet = send(s, "1234567890", 10, MSG_NOSIGNAL);

     

      1.  新增释放读写锁

    Windows的读写锁不需要释放,也没有对应的函数,为了兼容linux,新增一个释放读写锁的函数DeleteSRWLock,此函数不执行任何功能,直接返回。

     

    void DeleteSRWLock(LPSRWLOCK pLock)

    {

             return;

    }

     

    1.  本方案的功能限制

    由于作者一向倾向于采用单进程多线程的方式实现服务器程序,本方案的实现对支持多进程的编程开始模式很弱。例如对进程间通讯的支持基本没实现,例如:共享内存、信号量、消息队列、管道等,还有就是进程间的线程锁互斥和同步、文件映射等。如果读者需要,可根据需要自行实现或采用其他的方案解决。

     

    1.  本方案的缺点

    1、基于本文的移植方案的linux程序相比原生的linux程序,运行效率会降低一点,但是相

       对整体来说,可以忽略不记,毕竟只是增加了一层简单的移植外壳代码。

     

    2、有些Windows下的代码无法通过linux的移植文件实现,建议windows和linux分别实现,  

        然后通过加入预编译指令,分别编译。

     

    3、需要购买VC的正版授权。

     

    4、需要面临被微软断供的可能。

    1.  成功案例

    作者长期从事C/C++进行后台服务器程序开发,目前所有的项目或工程都支持跨平台,项目包括:

     

    1、功能类库SDK

       1)内存分配管理

     

       2)数据结构类

          链表、avl二叉树、红黑二叉树、trie查找树、trie模糊树、多级目录模糊匹配树、多

          级树、内存表。

     

       3)解析类库

          xml解析、Json解析等。

     

      4)其他

        消息队列等。

     

    2、内存数据库系统

     

    3、脚本引擎

     

    4、WebServer产品

     

    5、消息网关类

       短信网关、MQTT服务器系统等消息转发处理产品。

     

    以上所有的项目都是基于VC开发、调试测试,然后一次性移植到linux平台,效果明显。

     

     

    展开全文
  • HTML开发常用知识点

    2018-10-12 10:16:30
    HTML开发常用知识点 1.什么是HTML html即超文本标记语言,超文本标语又是标准通用标记语言下的一个应用。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; “超文本”就是指页面内可以包含...
  • 游戏服务器开发需要学什么

    千次阅读 2017-02-24 09:57:15
    一,游戏服务器开发的工作介绍 近来遇到有很多人想从其它开发领域转到游戏服务器开发行业上来,他们或许觉得游戏服务器开发工资高,或许觉得做游戏服务器需要掌握的技术更高级,可以锻炼自己,或许觉得想换个环境...
  • 不管出于什么原因吧,做为一名从事游戏服务器开发和教学很多年的人,我当然是持欢迎态度的,那么我就先介绍一下游戏服务器开发的工作吧,游戏服务器开发具体要做哪些工作呢? 1.团队沟通 基本上不管做什么开发,都...
  • 学习JAVA游戏服务器开发需要了解的情况

    万次阅读 多人点赞 2018-06-11 16:09:38
    一,游戏服务器开发的工作介绍近来遇到有很多人想从其它开发领域转到游戏服务器开发行业上来,他们或许觉得游戏服务器开发工资高,或许觉得做游戏服务器需要掌握的技术更高级,可以锻炼自己,或许觉得想换个环境等等...
  • 基本上不管做什么开发,都是一个团队来完成的,游戏也是如此,游戏团队一般由老板,总经理,CTO(技术主管),主策划(领导一些人,包括数值策划,系统策划,特效策划),主美(领导一些人,包括原画,UI设计,特效动作...
  • 文章目录WebRTC源码研究(4)web服务器工作原理 WebRTC源码研究(4)web服务器工作原理
  • 2018年3月3日近来遇到有很多人想从其它开发领域转到游戏服务器开发行业上来,他们或许觉得游戏服务器开发工资高,或许觉得做游戏服务器需要掌握的技术更高级,可以锻炼自己,或许觉得想换个环境等等。不管出于什么...
  • 去年刚毕业来公司后,做为新人,发现很多东西都没有文档,各种工具和地址都是口口相传的,而且很多时候都是不知道有哪些工具可以使用,所以...本文介绍的我所在小组的一些开发流程及相关工具。做为新人入门手册,
  • 网游服务器

    千次阅读 2012-04-20 15:56:19
    拼包函数及网络封包的异常处理(含代码) ...常见的网络服务器,基本上是7*24小时运转的,对于网游来说,至少要求服务器要能连续工作一周以上的时间并保证不出现服务器崩溃这样的灾难性事件。事 实上,要
  • java游戏服务器必备

    千次阅读 2018-12-28 16:41:44
    对于一个新手,想接触游戏服务器,一定会有个疑问——使用Java开发服务器需要学习什么? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java语言,由于学习成本低,开发速度快,稳定
  • myapps快速开发平台常用知识点

    千次阅读 2016-04-29 23:08:44
    开发常见问题及解答 1 表单 1.1表单的类型 说明: 表单类型分为普通,查询表单,普通(映射)表单。 (1)普通,常规的表单配置 (2)查询表单,主要为视图列表配置查询头,要与视图配置结合使用 (3)映射表单,...
  • GET方式:当使用GET方式提交表单内容的时候,浏览器将各个表单自元素及其数据按照URL参数的格式附加在请求行中的资源路径后面。使用GET方式传送的数据量是有限制的,一般限制在1KB一下。表单提交的时候默认是GET...
  • 第十六章、文件服务器之二: SAMBA 服务器 最近更新日期:2011/07/29 如果想要共享档案,在 Linux 对 Linux 的环境下,最简单的方法就是透过 NIS 这玩意儿了!至于 Windows 对 Windows 的环境下,...
  • 设计游戏服务器

    千次阅读 2012-01-05 10:48:34
    有段时间没有研究技术了,这次正好看到了新版的mangos,较之以前我看的版本有了比较大的完善,于是再次浏览了下他的代码,也借此机会整理下我在游戏服务器开发方面的一些心得,与大家探讨。  另外由于为避免与...
  • 用 Groovy 服务器页面(GSP)改变视图

    千次阅读 2008-12-14 10:00:00
    不论是熟练的 Struts 开发人员还是最近的 Rails 爱好者,都熟悉这种 Web 生命周期。 之所以提到这点,是因为近几年出现了大量不以页面为中心的视图技术(请参阅 参考资料 )。 面向组件的 Web 框架(例如 Java...
  • Linux 文件服务器之二 SAMBA服务器

    千次阅读 2013-11-11 23:38:43
    如果想要共享档案,在Linux对Linux的...系统的话,那就使用Samba服务器,Samba可以让Linux加入Windows的网芳支持,让异质平台可以共享文件系统,不仅如此,Samba也可以让Linux上面的打印机成为服务器 总之,Samba对于整
  • 游戏服务器设计(转)

    千次阅读 2015-07-14 17:23:29
    有段时间没有研究技术了,这次正好看到了新版的mangos,较之以前我看的版本有了比较大的完善,于是再次浏览了下他的代码,也借此机会整理下我在游戏服务器开发方面的一些心得,与大家探讨。  另外由于为避免与...
  • 游戏服务器编程

    千次阅读 2015-10-25 20:26:45
    拼包函数及网络封包的异常处理(含代码) ...常见的网络服务器,基本上是7*24小时运转的,对于网游来说,至少要求服务器要能连续工作一周以上的时间并保证不出现服务器崩溃这样的灾难性事件。事 实上,要
  • Linux常用的网络命令

    千次阅读 2013-05-20 18:30:23
    D(dynamically installed by daemon or redirect):已由服务器或转port功能设置为动态路由。 Ø M(modified from routing daemon or redirect):路由已被修改了。 Ø!(reject route):这个...
  • 游戏服务器架构

    2015-12-11 20:22:24
    有段时间没有研究技术了,这次正好看到了新版的mangos,较之以前我看的版本有了比较大的完善,于是再次浏览了下他的代码,也借此机会整理下我在游戏服务器开发方面的一些心得,与大家探讨。  另外由于为避免与...
  • Stan Lippman先生曾在《C++ Primer》一书中指出“C++是最为难学的高级程序设计语言之一”,人们常将“之一”去掉以表达自己对C++的敬畏。诚然,C++程序设计语言对于学习者的确有很多难以逾越的鸿沟,体系结构的庞大...
  • 一些关于网游服务器的东东

    千次阅读 2012-06-19 09:16:24
    拼包函数及网络封包的异常处理(含代码) ...常见的网络服务器,基本上是7*24小时运转的,对于网游来说,至少要求服务器要能连续工作一周以上的时间并保证不出现服务器崩溃这样的灾难性事件。事 实上,要

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,061
精华内容 3,224
关键字:

常用服务器端开发语言