笔记
TCP并发服务器
一.引入
1> 对于UDP通信而言,由于是面向无连接的通信,一个服务器可以服务多个客户端,处理多个客户端的消息
2> 对于TCP服务器而言,需要建立连接,服务器域客户端建立连接后,其他客户端就无法通信了
3> 如何做到一个TCP服务器能够跟多个客户端进行通信,此时我们引入了TCP并发服务器
4> 实现TCP并发服务器可以使用:多进程、多线程、IO多路复用
二.循环服务器
循环服务器模型
1、sfd = socket(); //创建用于连接的套接字文件描述符
2、bind(); //为套接字绑定ip地址和端口号
3、listen(); //将套接字设置成被动监听状态
4、while(1)
{
newfd = accept(); //阻塞等待客户端的连接
recv();
send(); //数据收发
close(newfd);
}
close(sfd); //关闭套接字
三.使用多进程完成TCP并发服务器
实现原理:父进程主要用于解决accept接收客户端连接请求的阻塞,当有客户端发来连接请求后,创建出子进程用于通信使用
实现模型:
//定义收尸函数
void handler(int signo)
{
while(waitpid()>0);
}
signal(SIGCHLD, handler); //将信号与信号处理函数绑定
1、sfd = socket(); //创建用于连接的套接字文件描述符
2、bind(); //为套接字绑定ip地址和端口号
3、listen(); //将套接字设置成被动监听状态
4、while(1)
{
newfd = accept(); //阻塞等待客户端的连接
pid = fork(); //创建子进程用于处理客户端
if(pid > 0)
{
close(newfd); //关闭newfd
}else if(pid == 0)
{
close(sfd); //关闭sfd
recv();
send(); //数据收发
close(newfd);
}
}
close(sfd); //关闭套接字
四.使用多线程完成TCP并发服务器
实现原理:主线程主要完成accept接收客户端连接请求的阻塞,当客户端发来连接请求后,创建一个分支线程用于跟客户端进行通信
实现模型:
//定义线程题函数
void *deal_cli_msg(void *arg)
{
recv();
send(); //数据收发
close(newfd);
pthread_exit(NULL);
}
1、sfd = socket(); //创建用于连接的套接字文件描述符
2、bind(); //为套接字绑定ip地址和端口号
3、listen(); //将套接字设置成被动监听状态
4、while(1)
{
newfd = accept(); //阻塞等待客户端的连接
//创建用于通信的分支线程
struct MsgInfo buf = {newfd, cin};
pthread_create(&tid, NULL, deal_cli_msg, &buf);
//将线程设置成分离态
pthread_deatch(tid);
}
close(sfd); //关闭套接字
抓包分析
一.wireshark使用
安装
1) wireshark的官方下载网站:www.wireshark.org/
2) Linux sudo apt install wireshark
3) 启动sudo wireshark
设置中文 Edit->Preferences->Appaerance->Language->Chinese
二.包头分析
三次握手:
- 第一次握手:客户端发送SYN包(SYN=1, seq=0)给服务器,并进入SYN_SENT状态,等待服务器返回确认包。
- 第二次握手:服务器接收到SYN包,确认客户端的SYN,发送ACK包(ACK=1 , ack=1),同时发送一个SYN包(SYN=1, seq=0),并进入SYN_RCVD状态。
- 第三次握手:客户端接收到服务器的SYN包,以及ACK包,进入establish状态,同时向服务器发送ACK包(ACK=1, ack=1)。此时三次握手包发送完毕,服务器也进入establish状态
四次挥手:
- 第一次挥手,主动关闭方发送一个FIN包(FIN=1, seq = u)给被动方,进入FIN_WAIT_1状态;
- 第二次挥手:被动方接收到FIN包,给主动方发送一个ACK包(ACK=1, ack=u+1);并进入CLOKSE_WAIT状态。主动方接受到ACK包后,进入FIN_WAIT_2状态。如果有数据没有发送完毕,则继续发送,直到发送完毕为止;
- 第三次挥手:被动方发送一个FIN包(FIN=1, seq=w),进入LAST_ACK状态.
- 第四次挥手:主动关闭方收到FIN包,回复一个ACK包(ACK=1, ack=w+1)。被动关闭方收到主动关闭方的ACK后关闭连接。