-
主要是参考关于网络编程书上的实例,不是原创
-
接触了好几个关于web服务器的实现的,发现虽然代码不一样,但是底层所用的知识却是相同的
基本原理
-
web服务器 主要是通过C语言中的
socket
相关函数,建立通讯的,然后web服务器代替客户端去请求服务端的资源,从而实现双发的交流 -
目前大多数是采用多线程模式,一个线程负责监听连接,监听到连接时,则在创建一个线程去提供服务。
-
监听线程始终负责监听,不断有客户请求,则不断去创建子线程来提供服务。
-
可以查看具体相关的
TCP/IP
网络应用编程书籍,系统学习,在csapp
上有具体相关的精简例子和原理分析。 -
socket
- 编程过程- client - socket()->connect (创建套接字 -> 发起连接)
- server - socket()->bind()->listen()->accept() (创建套接字->将套接字地址和套接字描述符绑定在一起->创建监听描述符->等待客户端连接请求,创建连接描述符)
- client and Server
- C语言 实现client 和 server
-
机制
- 进程之间是通过内核更新进程的上下文来传输信号的,收到信号后会有特定的信号处理程序或者默认的行为进行响应信号。
-
主要问题
- 信号是怎么传递的
- 信号是怎么发送的
- 信号是怎么接受的
- 信号是怎么阻塞的
- 信号是怎么解除阻塞的
- 收到信号的行为是什么(行为)
- 想一下,在马路上行走的时候,遇到红绿灯我们的行为是什么?
-
发送信号(基于
进程组
)- 用
/bin/kill
发送信号 - 用
键盘输入
- eg:ctrl+c
- 用
kill()
- 调用kill函数发送给其他进程和他们自己 - 用
alarm()
- 定闹钟
- 用
-
接受信号
- 信号(正在处理的 + 未处理的)
- 信号是不排队的,同一种类型的信号只会在
待处理信号
中出现一次 signal()
- 接受信号
-
阻塞和解除阻塞信号
sigprocmask(int how, const sigset \*set, sigset_t \*oldset)
- how定义行为,然后处理信号(阻塞set)
-
编写信号处理程序
异步处理
- 避免因为
信号不排队
造成的有些信号没有得到处理,导致进程成为僵尸进程
- 会引起内存资源被过度消耗的问题 volatite sig_atomic_t t
- 定义了一组原子操作的类型
- 在函数调用过程中,便是用到了栈,栈中存放了函数的
返回地址
,参数
,局部变量
等。 - C语言很容易发生缓冲区溢出,所以很容易造成缓冲区溢出攻击,攻击者会注入可执行代码(
shellcode
),然后执行非法程序. - 一般攻击者会通过测试注入,捕获
函数帧
的返回地址,然后通过填入攻击(shellcode)程序的起始地址,然后正常的程序在执行到这个位置时,就会转向执行非法程序的位置,从而达到攻击的目的
int atoi(char s[])
{
int i = 0;
int n = 0;
for (i; '0' <= s[i] && s[i] <= '9'; i++)
{
//相对于字符 0 的偏移 也就是可以认为是这个数 但不是这个数的ascii
n = n * 10 + (s[i] - '0');
//234 =
//0 * 10 + 2 = 2
//2 * 10 + 3 = 23
//23 * 10 + 4 = 234
}
return n;
}
- char *str;//指针
- char str[];//数组
- char str[100];//数组
- 真是太容易搞混了
- int32_t 用
typedef long int32_t
int 型的负值,比一个字符串的
length()
属性要大
- 原因:
- length()返回的是无符号型整数
- int 遇到和无符号型的比较时,会发生类型转换,正数不受影响,但是负数却导致变得很大,和具体的平台相关
- 所以,用负数和字符串的length()比较时,则会出现问题。
写在最后
纵浪大化中
不喜亦不惧
应尽便须尽
无复独多虑