“TCP:三次握手”分析——以一个简单的“服务器”和“客户端”为例
linux&C这两天学到了网络编程这一章,自己写了一个小的”服务器”和”客户端”程序,目的在于简单理解tcp/ip模型,以及要搭建一台简单服务器,服务器和客户端最基本的事情要干什么,这篇博客就这个小程序,也简单分析了自己对”TCP-三次握手”过程的理解。因为初学网络编程,说的不对的地方欢迎大家评论交流。
套接字:
套接字由4部分组成,服务器IP地址和客户端IP地址以及服务器端口号和客户端端口号,是客户端和服务器端传输数据确定线路的保证,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
首先我们来看服务器端的代码:
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
#define MAX_QUEUE_LENGTH 1024
int main(int argc,char *argv[])
{
int sock_fd,conn_fd;
struct sockaddr_in serv_addr,conn_addr;
socklen_t conn_len;
pid_t pid1;
char recv_buf[128];
int ret;
//创建套接字
sock_fd = socket(AF_INET,SOCK_STREAM,0);
/*参数分别为(使用IPV4 tcp/ip协议,使用tcp流套接字,
通过前两个参数来确定使用的协议类型,默认为零)*/
//mZ服务器端的套接字进行初始化
memset(&serv_addr,0,sizeof(struct sockaddr_in));
//memset函数将serv_addr 用0进行初始化
serv_addr.sin_family = AF_INET;
/*设置地址类型:对于sin_family,表示用tcp/ip协议编程,
所以此值只能为AF_INEF*/
serv_addr.sin_port = htons(4507);
//设置端口号为4507
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//关于ANADDR——ANY这个宏的解释在下面有,也可以向下面一样设定指定IP
//inet_pton(AF_INET,"XXX.XXX.XXX.XXX",&serv_addr.sin_addr);
//当我只有一块网卡,一个IP,所以也只能设置为自己的ip了
//绑定套接字
bind(sock_fd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr_in));
/*绑定套接字的过程是将我前面创建的套接字与初始化的端口绑定起来, 因为socket只是创建了一个套接字,这个套接字将在哪个端口上工作, 并没有被指定,作为服务器,它的IP和端口一般是固定的,因此我们需要将刚才
初始化的端口和套接字绑定到一起,这时套接字已经完成服务器的ip和端口这一半*/
//将套接字转化成监听套接字
listen(sock_fd,MAX_QUEUE_LENGTH);
//第二个参数比较重要,它是我们服务器已完成套接字队列的长度,accept函数每次
//会从已完成的套接字队列中拿走一个即conn_fd,也就是监听套接字,注意:内核会维护两个队列,
//一个是已完成的套接字队列,一个是未完成的套接字队列,一个套接字完成的过程是在三次握手的
//过程中完成的,是由tcp/ip协议栈完成的
//接受客户端的请求
conn_len = sizeof(struct sockaddr_in);
while(1)
{
conn_fd = accept(sock_fd,(struct sockaddr *)&conn_addr,&conn_len);
//服务器会将客户端的连接消息先放在未完成的队列中,三次握手之后,就到已完成队列中
//conn_fd就是accept返回的叫作连接套接字,它的信息有服务器的端口和IP以及客户的端口和IP,
//监听套接字继续监听,对于新的处理,系统会重新开一个线程处理,自己也可以用进程
printf("accept a new connection,ip:%s\n",inet_ntoa(conn_addr.sin_addr));
pid1 = fork();
if(pid1 == 0)
ret = recv(conn_fd,recv_buf,sizeof(recv_buf),0);
recv_buf[ret-1] = '\0';
}
printf("%s\n",recv_buf);
}
注释中解释了套接字的初始化,建立,绑定,监听的过程,结束之后我们服务器端的工作就做好了,为了检验程序是否正确,运行程序之后我们可以用netstat命令查看我们服务器端是否开启监听模式
$ netstat -apt | grep LISTEN
可以看到4507端口的状态是LISTEN。
在说说INADDR_ANY的作用
INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。 一般来说,在各个系统中均定义成为0值。举个例子:你的电脑上如果有多块网卡就会有好几个IP,或者说你的服务器有多台主机也会有好多个IP,而如果你的IP会发生变化,比如变多或者变少,但是为了减少bind()时的麻烦,可以统一设定就在0.0.0.0这个地址上监听。所有的信息都会到这个地址上,如果你需要将服务器上的所有IP中的80端口监听,再将80端口绑定就OK了,我就了解了这么多。
然后再看我们的客户端代码:
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<netinet/in.h>
int main(int argc,char *argv)
{
struct sockaddr_in serv_addr;
int conn_fd;
//同样我们需要在客户端也建立套接字
conn_fd = socket(AF_INET,SOCK_STREAM,0);
//初始化与服务器端匹配的信息
memset(&serv_addr,0,sizeof(struct sockaddr_in));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(4507);
inet_aton("192.168.20.144",&serv_addr.sin_addr);
//用于向服务器端发送连接请求,服务器的IP地址和端口号由参数serv_addr指定
connect(conn_fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in));
close(conn_fd);
}
客户端有点简单啊,但是可以登录,这样就可以基本实现我们的客户端和服务器之间连接了,下面我们进入我们的主题:是不是都忘了我们的主题是——“三次握手“。
在这个实例中,三次握手发生在客户端执行connect函数的时候。三次握手的过程下面的图片可以显示清楚,我再举个例子
第一次 client->server SYN=1,seq = x
第二次 server->client SYN=1,ACK = 1,seq = y,ack = x+1
第三次 client->server ACK=1,seq = x+1
SYN:同步序号,当SYN=1,ACK=0时,表明这是一个连接请求。
ACK:当ACK=1时,确认号字段即ack才有效。
seq:范围:[0,2^32 - 1],表示发送的第一个字节的编号。
ack:确认号,当ack = n,表示到n-1为止的所有字节都已经被收到。
另外我用tcpdump命令抓了个包,可以分析下,不对的地方指出
$ tcpdump port 4507
我的客户端IP为192.168.122.172,服务器的IP为192.168.20.128。
第一次:Flag[S],表示这是一个请求连接,S是SYN字母的首字母,seq是将要发送的首字节的序列号,此时SYN = 1,ACK = 0。
第二次:收到SYN = 1的包,将ACK置为1,ack = 1588197944表示在此之前的字节我已经全部收到。
第三次:当再次收到SYN=1,ACK=1的包时,将ack = 1,表示确认连接。
“TCP:三次握手”分析——以一个简单的“服务器”和“客户端”为例的更多相关文章
- Wireshark抓包介绍和TCP三次握手分析
wireshark介绍 wireshark的官方下载网站: http://www.wireshark.org/ wireshark是非常流行的网络封包分析软件,功能十分强大.可以截取各种网络封包,显示 ...
- TCP三次握手四次分手—简单详解
关于TCP三次握手四次分手,之前看资料解释的都很笼统,很多地方都不是很明白,所以很难记,前几天看的一个博客豁然开朗,可惜现在找不到了.现在把之前的疑惑总结起来,方便一下大家. 疑问一,上图传递过程中出 ...
- 用C++写一个简单的服务器和客户端
我们将创建一个服务器节点add_two_ints_server,它将会收到两个整数,并且返回它们的和.切换目录到之前建立的beginner_tutorials包下: cd ~/catkin_ws/sr ...
- 抓包工具-Wireshark(详细介绍与TCP三次握手数据分析)
功能使用的详细介绍 wireshark(官方下载网站: http://www.wireshark.org/),是用来获取网络数据封包,可以截取各种网络封包,显示网络封包的详细信息,包括http,TCP ...
- Wireshark抓包TCP三次握手数据
抓包工具 - Wireshark(详细介绍与TCP三次握手数据分析) 功能使用的详细介绍 wireshark(官方下载网站: http://www.wireshark.org/),是用来获取网络数据封 ...
- 这次一定让你记住 TCP 三次握手、四手挥手!
TCP协议全称为:Transmission Control Protocol,是一种面向链接.保证数据传输安全.可靠的数据传输协议.为了确保数据的可靠传输,不仅需要对发出的每个字节进行编号确认,还需要 ...
- 详解TCP三次握手(建立TCP连接过程)
在讲述TCP三次握手,即建立TCP连接的过程之前,需要先介绍一下TCP协议的包结构. 这里只对涉及到三次握手过程的字段做解释 (1) 序号(Sequence number) 我们通过 TCP 协议将数 ...
- 简单说说TCP三次握手、四次挥手机制
1.什么是TCP TCP全称Transmission Control Protocol(传输控制协议),是一种面向连接的.可靠的.基于字节流的传输层通信协议.是为了在不可靠的互联网络上提供可靠的端到端 ...
- 用tcpdump分析tcp三次握手,四次挥手
1.tcpdump 简介 tcpdump是一个对网络上的数据包进行截获的包分析工具,一般linux系统以命令的形式使用 2.tcp三次握手 建立一个tcp连接会发生下面三个过程: 1.服务器必须准备好 ...
随机推荐
- Jmeter系列(7)- 分析源码,创建下单、用户注销接口请求
源码分析 下单 用户注销 创建请求 下单 用户注销 请求调整 将信息头管理器从[02.浏览订单]请求中抽出来就变成公用的.[03,04]请求不需要单独再加信息头管理器 DeBug取样器 添加DeBug ...
- T183637-变异距离(2021 CoE III C)【单调栈】
正题 题目链接:https://www.luogu.com.cn/problem/T183637 题目大意 给出\(n\)个二元组\((x_i,y_i)\),求最大的 \[|x_i-x_j|\time ...
- idea使用gitee的小坑
1. 账号配置 账号配置登陆时提示 *** is not a valid login name: Email support only. 翻译:只能支持邮箱登录 解决方法:在gitee网站上查看自己配 ...
- 【Go】Golang实现gRPC的Proxy的原理
背景 gRPC是Google开始的一个RPC服务框架, 是英文全名为Google Remote Procedure Call的简称. 广泛的应用在有RPC场景的业务系统中,一些架构中将gRPC请求都经 ...
- c# 类型安全语言
所谓的安全性语言其本质是有关类型操作的一种规范,即不能将一种类型转换为另一种类型. c#作为一种安全性语言,允许合理的类型转换,但是不能将两个完全不同的类型相互转换. c#允许开发者将对象转换为它的实 ...
- 【MySQL】MySQL进阶(外键约束、多表查询、视图、备份与恢复)
约束 外键约束 外键约束概念 让表和表之间产生关系,从而保证数据的准确性! 建表时添加外键约束 为什么要有外键约束 -- 创建db2数据库 CREATE DATABASE db2; -- 使用db2数 ...
- 自定义view---仪表盘--kotlin
我们知道一个自定义view一般来说需要继承view或者viewGroup并实现onMeasure, onLayout, onDraw方法. 其中onMeasure用于测量计算该控件的宽高, onLay ...
- 「JOISC 2020 Day2」变态龙之色 题解
题目传送门 注意 同性必定不同色 必有一个同色异性,且不相互不喜欢 Solution 我们发现,我们问题比较大的就是如何确定性别问题.我们可以一个一个加进去,在原来已经确定了的二分图上增加新的性别关系 ...
- Centos7 python3环境搭建 兼容python2.7
Centos7 python3环境搭建 兼容python2.7 安装前提依赖 yum install openssl-devel bzip2-devel expat-devel gdbm-devel ...
- Netty 进阶
1. 粘包与半包 1.1 粘包现象 服务端代码 public class HelloWorldServer { static final Logger log = LoggerFactory.getL ...