Savelog项目总结回忆

时间:2021-02-21 17:28:27

Savelog项目的细节已经不太记得,感觉有些遥远,需要翻回旧的笔记本电脑或者是旧的笔记本。

概述:

本项目采用的Linux C,监听一个或多个特殊的端口,当其中一个端口有发起连接时就产生一个新的线程,并将端口发来的数据进行检验,然后保存到日志,日志只保留最近7天的内容,连接的端口会不断的发送数据,大概每秒钟发送一个,发送成功或失败都要写入日志,成功用info标签,记录端口号,IP等,失败根据失败的内容检查,并给出相应的原因。

下面讲一些笔记记下来,是从刚开始学Linux开始的那段。

杂锦:

linux:
命令部分
1 linux的命令遵循大小写
2 用cat输入文字后必须回车后Ctrl+c
3 chmod :change mode(right)
chown :change owner
chgrp :change group
crontab:cron进程
ps:proccess scan
kill:杀死进程
4 echo命令有很多功能,其中最常用的是下面几个:
\c 不换行。
\f 进纸。
\t 跳格。
\n 换行。
5 grep:global rep(正则) 查询使用
6 登录成功后,系统执行两个环境设置文件,第一个是/ e t c / p r o f i l e,第二个是. p r o f i l e,位
于用户根目录下。
7 rm=remove
8 df=disk file ??
9 diff=different ??] 不用于什么
10 du=disk usage ????左边那一列是什么用但
11 eject=弹出 与device有关
12 mkdir=makedirectory

13
常用命令:
帮助:man intro
编辑:vi sed ed ex
目录:cd ls mkdir pwd du
文件:rm cp mv chmod diff ln nl wc
过滤:sort more head tail uniq
查看:set cat od file echo clear
进程:ps kill pkill pgrep sleep wait
Shell:who w . Sh alias
参数:pich xargs
时间:date touch
查找:grep which find whereis
计算:bc expr
打包:tar gzip compress rpm
系统:sync reboot shutdown poweroff

14 安装64位linux需要设置电脑都CPU兼容虚拟机

15 C部分:
1 八进制数,程序中以0 开始,如013,-013 等。
2 另外,可在整型常数后添加一个“L”或“l”字母表示该数为长整型数,如代码中的j=1234L,
表示j 为长整型数。
3 NULL 是一个特殊的字符,在C 程序中有着重要的功能。NULL 在ASCII 码表中是0,
在程序中表示空字符,或者没有这个数值。在定义变量时,如果要对变量赋值为空值,可将
这个变量赋值为NULL,如下面代码所示。
4 printf的输出格式控制:
?? 格式字符串是以%开头的字符串,在%后面跟有各种格式字符。不同格式字符串的作
用是说明输出数据的类型、形式、长度、小数位数等。如“%d”表示按十进制整型输
出,“%ld”表示按十进制长整型输出。这些格式字符串与输出变量列表中的变量一一
对应。
?? 格式字符串以外的内容是非格式字符串,在输出时按照原有的字符直接输出。
格式字符串的内容和意义如下所示。
?? %c:输出单个字符,参数为该字符的ASCII 码。
?? %d:以十进制形式输出带符号整数(正数不输出符号)。
?? %e 或%E:以指数形式输出单、双精度实数,默认保留6 位小数。
?? %f:以小数形式输出单或双精度实数,默认保留6 位小数。
?? %g 或%G:以%f 或%e 中较短的输出宽度输出单、双精度实数。如果指数小于-4 或大
于等于默认精度,则使用%e 或%E 格式输出。否则用%f 格式输出,省略末尾多余的0。
?? %i:以十进制形式输出带符号整数,同%d。
?? %o:以八进制形式输出无符号整数(不输出前缀0)。
?? %s:输出字符串,参数为char 指针,显示字符串中所有的字符。
?? %u:以十进制形式输出无符号整数。
?? %x 或%X:以十六进制形式输出无符号整数,%x 表示输出小写,%X 表示输出大写。
5 在使用指针时,需要牢记,不可以随意向不确定的内存单元写入数据。这种写操作可能
破坏内存中其他的数据,引起其他程序的错误。
*p=i;
/*对指针变量指向的值进行赋值。注意,这个操作是错误的。*/
6 gdb 常用命令
除了前面讲述的gdb 命令以外,gdb 还有很多种命令。这些命令可以完成程序调试的各
种功能。其他的常用命令含义如下所示。
?? backtrace:显示程序中的当前位置和表示如何到达当前位置的栈跟踪(同义词:where)。
?? breakpoint:在程序中设置一个断点。
?? cd:改变当前工作目录。
?? clear:删除刚才停止处的断点。
112
Linux 系统下C 程序开发详解
?? commands:命中断点时,列出将要执行的命令。
?? continue:从断点开始继续执行。
?? delete:删除一个断点或监测点,也可与其他命令一起使用。
?? display:程序停止时显示变量和表达式。
?? down:下移栈帧,使得另一个函数成为当前函数。
?? frame:选择下一条continue 命令的帧。
?? info:显示与该程序有关的各种信息。
?? info break:显示当前断点清单,包括到达断点处的次数等。
?? info files:显示被调试文件的详细信息。
?? info func:显示所有的函数名称。
?? info local:显示当函数中的局部变量信息。
?? info prog:显示被调试程序的执行状态。
?? info var:显示所有的全局和静态变量名称。
?? jump:在源程序中的另一点开始运行。
?? kill:异常终止在gdb 控制下运行的程序。
?? list:列出相应于正在执行的程序的源文件内容。
?? next:执行下一个源程序行,从而执行其整体中的一个函数。
?? print:显示变量或表达式的值。
?? pwd:显示当前工作目录。
?? pype:显示一个数据结构(如一个结构或C++类)的内容。
?? quit:退出gdb。
?? reverse-search:在源文件中反向搜索正规表达式。
?? run:执行该程序。

16 Xshell下字符显示不出来,是字符集的问题:
输入export LANG=c即可!
?? search:在源文件中搜索正规表达式。
?? set variable:给变量赋值。
?? signal:将一个信号发送到正在运行的进程。
?? step:执行下一个源程序行,必要时进入下一个函数。
?? undisplay display:命令的反命令,不要显示表达式。
?? until:结束当前循环。
?? up:上移栈帧,使另一函数成为当前函数。
?? watch:在程序中设置一个监测点(即数据断点)。
?? whatis:显示变量或函数类型。

17 do..while后面不要总忘记加";"

18 字符集问题:1)vim ~/.bashrc
2) 在最下面一行添加
export LANG=C
保存退出
3)source ~/.bashrc

19 去除搜索高光的方法:nohl是去除当前的
开启高光 set hlsearch 关闭高光 set nohlsearch

20 用if判断两个字符串相等记得要空格 if [ $a = $b ] 否则总是对的!

21 解决cannot open the disk "XXX.vmdk"的办法(无法启动虚拟机)
答:删除.lck结尾的文件夹即可!

22 出现expected declaration specifier "..." before XXX
多半是代码的组织问题。
1)头文件互相引用或头文件中的结构体等互相引用。
2)XXX.c若要生成链接库,则头文件中只需要xxx.h即可,xxx.h再包含内核的库。然后主函数中再使用#include "xxx.h"

23 select与pselect的不同:pselect带信号屏蔽功能。

24 select与poll的不同:poll支持各种类型的文件描述符做I/O多路转换。poll对每一个要监控的文件描述符建立一个操作描述的结构体。

25 perror与printf,perror会将参数先打印出来,然后后面加上错误原因。如perror("login");
结果是:login,error 0

26 exit和_exit的用法的区别:
答:(1)_exit执行后立即返回给内核,而exit()要先执行一些操作,然后将控制权交给内核。
(2)exit()是_exit基础上的封装,会进行一些流清理。
(3)缓冲I/O操作时,有些数据在缓冲区,没达到一定条件,不会写入磁盘,调用exit函数会先让他写入硬盘,再退出进程,而_exit会直接退出。
(4)exit(0)表示正常退出,exit(1)表示异常退出,会结束当前进程,整个程序。

27 return时会自动调用exit,使进程以及所有的线程退出(无论在其他线程或者主线程调用都有以下效果)

28 wait只是waitpid的一个特殊情况而已。wait的必须阻塞组进程,直到收到某子进程的信号为止。

29 所有变量都应该初始化,结构体也不例外。

30 vi使用技巧之一,v选中文本,n(任意数字)+>可以向右移动。

31 rm -rf 强制删除目录。

32 vsplit,split,分别是打竖,打横vim多窗口界面。

33 vim下:copen调试常用。

34 gdb下:wh,调试常用

35 gdb下:bt查看错误常用

36 tlist插件,在vim下可以显示函数列表。

37 更改vim下的一些属性?请到\etc\.vimrc下寻找!

38 write的第三个参数strlen()+1是为了把\0传过去。

37 如果你的代码丢失并且保存了或者找不到啦,但是你的debug文件还在(编译好可以用来调试的那个),那你完全可以在gdb下list他出来,不就可以恢复代码了么!!——此想法大错特错啦!因为gdb要映射到本地的.c文件,否则根本list不出来。——所以代码如果跑到注释里去是可以理解的,必然是因为更改企且保存了.c文件,但没有编译。

二、telnet项目:
1 为什么要用telnet,因为要传递快捷键进行配置么?
(我们这的)交换机只支持telnet协议 端口号23

2 select可用于解决各种阻塞问题(多路选择I/O)
构造一张设备表,轮询查看这些设备哪些可用,若可有可用的,则select才返回可用值,接着执行read语句进行读取,即不会进行阻塞,若超时则返回0。

3 怎么避免僵尸进程?
1)wait方法,主进程去等子进程回来再退出。
2)子进程自己exit,然后init进程领养这些孤儿进程,即孤儿进程将变成init的子进程。

4 守护进程?如何创建?
答:1)即脱离终端的进程,不会因为该系统终端关闭而将对应的进程销毁。
2)创建的话需要创建子进程,并更改该子进程的文件权限掩码等多个步骤(因为该进程继承了很多父进程的信息包括目录等),然后将其遗弃。

5 文件权限掩码,4 2 1 分别表示 r w x,读 写 执行,一个文件的描述一般是-rwxrwxrwx,首位是文件类型,其次就是u g o,user group others,而权限的掩码就是每个加起来,例如最强悍的777,4+2+1=7,就所有用户等都可以读写执行。

6 抓包教程:
1)port 23 -w /root/telnet.pcap
2)开启自己的程序发送请求给服务器
3)将telnet.pcap发送到桌面 用wireshark打开~

7 如何调试多文件?
在编译链接库的时候需要先使用-g开关。

8 出现expected declaration specifier "..." before XXX
多半是代码的组织问题。
1)头文件互相引用或头文件中的结构体等互相引用。
2)XXX.c若要生成链接库,则头文件中只需要xxx.h即可,xxx.h再包含内核的库。然后主函数中再使用#include "xxx.h"

9 write或read的失败,显示错误是bad file descriptor,肯定是因为fd句柄值改变了,或者该设备已经不起作用了。

10 一个值无端改变,很可能是越界,很可能是某个数组的数值定得太大了!

11 strstr顺序不要弄错了。

12 select()中的FD_SET用于设置指定的描述符情况的,select()的第一个参数sfd,其实是最大描述符的值,也就是小于这个描述符的都会监视。

13 某些交换机,使用\n\r作为真正的换行符,也就是输入回车,写协议的时候经常要用到,其中要注意到的时用fgets进行读,可以读到空格,同时以\n作为结尾,也会添加到字符串尾部,需要注意。

14 read或write的长度非常重要,都是以字节位单位的,如果是char格式,或者int格式,要特别注意一下。

15 strlen关心数组内容,不关心实际大小,只能算字符串,不包括结尾的\0。
sizeof主要关键所有东西的大小,根据类型不同都不同,指针的话会告诉指针指向空见的大小,对象则是对象包含空间的大小。

三、savelog项目:
1 无论什么变量,包括结构体,最重要是数组,一定要初始化,char数组直接初始化0比较好!。

2 socket编程时,read(fd,buf,len)函数,在对方未write的时候是卡死状态,读的长度是buf的长度(若len>buf长度)。若对方断开链接,read会返回0.

3 write返回的也是实际写入的值。

4 write会不定时出错??
答:因为多线程间非互斥的使用同一个sfd导致,必须互斥访问,或者顺序访问。

5 select函数有记录功能,即发送过来的数据不会丢失,select函数出现时就能获取到描述符对应的变化。

6 字符串截取的一种好办法:
unsigned char *p=strchr(buffer,' ');
/*get the process name*/

int len=strlen(buffer)-strlen(p);

unsigned char pname[100]={0};

strncpy(pname,buffer,len);

7 获取时间的好方法:
struct tm *ptm;
time_t now;
time(&now);
//ptm=gmtime(&now);
ptm = localtime(&now);
int y=0,m=0,d=0,h=0,min=0,s=0;
y = ptm->tm_year + 1900;
m = ptm->tm_mon+1;
d = ptm->tm_mday;
h = ptm->tm_hour;
min = ptm->tm_min;
s = ptm->tm_sec;

8 DIR *dir;
rewinddir(dir);用于讲目录下的文件指针指向开头。

9 检索文件的大小或检索文件的修改时间,切记:文件打开时可能会产生一些文件,例如vim打开时会产生.swp文件,

10 怎么给线程void *thd_recv(void *arg)传一个参数?
答:int c_fd=*(int *)arg;

11 快速重新使用绑定的socket句柄:
/* enable address reuse at once*/
int on=1;
setsockopt(l_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));

12 printf时,%ns表示 字符串要占用n个位置 并靠右对齐,%-ns是靠左对齐

13 所有东西都要初始化才是好习惯。

14 每个装字符的数组用完后都要用memset以保证下次不会有大问题。

15 ^这个是异或运算符

16 FD_SET(fd,&rd)设置位向量,rd类似一个数组,记录了哪些文件被设置了。一般情况下FD_ZERO后跟FD_SET,只对一个连接进行监控。select的时候只针对其中一个。

17 read(fd,buf,len),len的长度一定要是buf数组的长度,总之不能大于!

18 Setsocketopt与setsocketopt是不一样的,前者可用于多端口。

19 extern是为了有多个.c的外界文件调用时用的。
static的话只是对应本.c文件的

20 不知道为什么,静态文件链接时只能用这个命令 -lxxxx不能用?
gcc -g savecdr_main.c -static ./savecdr_lib.a -o cdr_app

21 传结构体,要用fstat(fd,&st);声明时不能声明成指针,否则不可用!(只能传地址!!!)

22 if(S_ISDIR(st.st_mode))
{
printf("the directory is existed\n")
}
这招判断文件夹是否存在靠谱@!

23 用open创建文件时一定要增加掩码的参数!!

24 time_t类型保存的是秒数,当time()获取时间后,time_t就是从1900年开始的秒数。可以直接进行加减。

25 makefile中的命令必须以tab键开头,如果vim中设了set expandtab则tab自动转为空格,会导致命令无法生效。

四、装系统:
1 装64位系统要先在bois里面设置 visual technology为enable
2 用pq的时候一定要记得先把各种各样的垃圾程序关掉,这样才能顺利进行。(本次捣鼓最久的问题)

五、shell脚本
1 【shell脚本很多不科学和不完善】
竟然没有修改文件的操作,必须使用原始的tmp文件去重定向并且导入。

2 [[]]支持正则 此时变量要加引号。

3 字符串比较加上引号可以防止出现bash [:too many argument 错误

4 do..while后面不要总忘记加";"

5 用if判断两个字符串相等记得要空格 if [ $a = $b ] 否则总是对的!

六、rpc接口调用
1 使用ftp传东西,首先主机装上ftp server,设置用户密码,设置目录地址,
然后客户机使用命令
ftpget -u hello -p 1 192.0.10.121 rpc_pirnt rpc_print
前者是取来后的文件名,后一个rpc_print是原文件文件名

七、搜索文件:
1 搜索当前目录下以@开头的文件 find -maxdepth 1 -name “@*”

2 单字符转int:int i=(int)(ch-'0')

3 网络编程尽量使用:尽量使用uint8_t,uint16_t,uint32_t,uint64_t

4 argv包括路径名~ 用basename可以解决!

5 抓UDP的包:tcpdump -i eth0 udp port 6060(6060是端口号)

6 复制结构体:memcpy(dest,source)

7 16进制字符串转int
inline int _cal_shm_key(const char *p_str_key) {
if (!p_str_key) return 0;
return (strstr(p_str_key, "0x") || strstr(p_str_key, "0X")) ? (int)strtoul(p_str_key, NULL, 16) : atoi(p_str_key);
}

8 recv revcfrom read等从网路接受时,会受到网络字节序的byte直接赋值给struct的话与本机不同,可以先做成buf再复传一次。

9 ntohl用于32位网络字节序转成主机字节序。针对uint16_t yu uint32_t使用。

10 91状态查看:/etc/init.d/portmon status
/etc/init.d/portmon restart

11 tcpdump -i eth0 host 192.0.10.91 -w eth0.pcap 抓包发出

tcpdump -i eth0 -w eth0 host 192.0.10.151抓自己发出的包

12 当前目录是 ./XX

13 TCPDUMP是用RAW SOCKET的
RAW SOCKET可以接受IP层以上的原始协议 如ICMP TCP UDP等等

14 重命名文件夹 rm A B

15 方法论:用某些结构体感觉很奇怪时,看一下定义,也许他定义了别名。

16 printf 参数换行:用\

17 某些时候抓包需要:tcpdump -i eth0 udp port 6060 -s 0

18 memcpy(&l_m_port_6012,&m_port_6012,sizeof(m_port_6012))

19 printf()没法打印64位的。

20 诡异问题往往源于数组越界,如果出现segmentation fault或者malloc错误,请向前查找哪里出现了越界操作或者非法操作。

21 gdb看复杂东西的时候 使用 set print pretty on 看上去会非常雅观!!