TCP的握手和挥手
对于TCP的三次握手和四次挥手一直以来都知道, 但是没有深入实验了解. 看来网上的一些文章, 今天做一个实验并记录一下
简介
- 三次握手
- 4次挥手
需要注意的是, 为什么握手时三次和挥手时四次呢, 因为 在建立连接阶段可以直接把SYN和ACK一次发送过去
而对于断开连接时, 可能我发送完数据后, 发送SYN
试图断开连接, 但是另外一端还在接受数据(SOCKET还在工作)!
代码
写了一段简单的测试代码, 一个服务端, 一个测试端, 这是windows下的socket代码, 使用GCC编译, 记得连接(-lws2_32)
服务端
#include
#include
#include
int main(){
WORD sockVersion = MAKEWORD(2,2);
WSADATA wsaData;
if(WSAStartup(sockVersion, &wsaData)!=0)
{
return 0;
}
int ret = 0;
char buff[1024] = {0};
SOCKET fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(6000);
addr.sin_addr.S_un.S_addr = INADDR_ANY;
if(bind(fd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0)
{
printf("%s\n", "bind errro!");
}
if(0 != listen(fd, 5))
{
printf("%s\n", "listen errro!");
}
struct sockaddr caddr;
int len = sizeof(sockaddr);
SOCKET newfd = accept(fd, &caddr, &len);
if(newfd == INVALID_SOCKET)
{
printf("%s %d\n", "accept errro!", WSAGetLastError ());
}
else
{
printf("%s\n", "accept succ!");
}
while(1){
ret = recv(newfd, buff, 1024, 0);
if (ret <= 0){
Sleep(10);
break;
}
}
closesocket(newfd);
closesocket(fd);
Sleep(5000);
WSACleanup();
return 0;
}
客户端
#include
#include
#include
int main(){
WORD sockVersion = MAKEWORD(2,2);
WSADATA wsaData;
if(WSAStartup(sockVersion, &wsaData)!=0)
{
return 0;
}
SOCKET fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(6000);
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int ret = connect(fd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if(0 != ret){
printf("connect error: %d\n", WSAGetLastError ());
}
else
{
printf("%s\n", "connect succ!");
}
closesocket(fd);
WSACleanup();
Sleep(5000);
return 0;
}
抓包分析
握手: ASYN->BSYN/ACK->AACK
挥手:AFIN->BACK->BFIN->AACK
ps: 开头一个AB表示方向
我看到过一篇文章说, FIN本身携带ACK号, 如果双方都立刻关闭, 那么可能仅需三个报文即可完成挥手(第一个FIN可能被第二个FIN的ACK所确认), 但是我实验并没有成功验证这个! 敬请指教