Linux下TCPT通信
目录
1.温故知新
2.TCP通信
1.温故知新
知道了我们UDP下我们的通信方式,下面我们要学习我们的TCP通信,在这之前,我们先介绍一下我们所了解的UDP是有什么特性呢?它是面向数据报的,它是快速的,它是不保证数据安全的,它是全双工的,实现是一个套接字会有2个缓冲区,一个是读的缓冲区,一个是写的缓冲区,就实现了读的时候写,写的时候读,代码编写的时候,我们的UDP是要先创建套接字,然后进行套接字绑定,然后就可以进行读和写了。
2.TCP通信
知道了我们的UDP通信后,我们还需要知道我们的TCP通信,它也要创建套接字,只不过这次创建套接字的选项我们要选择流,因为TCP是面向字节流的。
所以我们的第二个参数要选择我们的SOCK_STREAM,由于我们的TCP也是面向网络通信的,所以我们的第一个参数依旧是,AF_INET!
创建完套接字之后,我们需要进行我们绑定套接字,这个过程和我们的UDP类似,还是那些细节,比如我们的客户端不显示绑定,要让我们的系统帮助我们去绑定,然后我们的服务端绑定的时候不指定IP绑定,防止我们只能通过一个IP进行访问,然后绑定套接字之后我们的TCP就不一样了。
由于我们的TCP是保证数据安全的,它得确保我们双方的信道通畅,它需要来监听我们客户端的链接请求,第一个参数是我们的套接字的返回值,第二个参数是我们的建立链接的个数。细节看图
开启监听之后,它就要开始进行链接了,当它监听到客户端请求链接的请求的时候,它就要开始建立链接了,这个接口我们用的是我们的accept。
我们的accept在没有链接的时候是阻塞的,当有链接来的时候它就要开始帮助我们建立链接了。它建立链接会创建一个文件帮助我们进行文件的传输,和UDP类似,它也是为我们创建一对缓冲区,也是全双工的。所以我们的TCP通信它监听的时候有一个套接字,然后它每建立一个链接也会有一个 套接字。
这个就好比我们的饭馆,有一个人在外面吆喝要不要吃饭,然后当客人进去之后,会为每个客人分配一个服务员,我们在外面的只负责把客人拉进去,进去之后由我们的服务员进行服务,各司其职,互不干扰。在外面吆喝的就相当与我们的监听, 在里面为每个客人服务的就是我们的建立链接。
上面说的是我们的服务端,我们的服务端需要建立套接字,绑定套接字,开启监听,然后等待建立链接。
然而我们的客户端是发起请求的一方,它需要connect,第一个参数是我们的文件下标,第二个是我们的结构体,第三个是我们的长度。
我们的TCP我们调用write向它的发送缓冲区里进行写入,当我们用户把我们的数据写到发送缓冲区的时候,之后的工作全部由我们的TCP完成,它决定什么时候发,发多少,我们的write本质就是一个拷贝,因为它仅仅是我们要写的数据从我们的应用层拷贝到了我们的缓冲区内。
通过下面的图,我们也可以更好的理解为什么TCP是全双工的,它的一个链接会在一个主机内创建一对缓冲区,一个缓冲区用来读,一个缓冲区用来写。它是面向字节流传输的。然后就是我们的TCP当我们把数据交给他之后,他就能决定什么时候发,发多少,有TCP自己来决定,所以TCP叫做传输控制协议。
所以,通过上面的介绍,我们可以得出结论,我们的TCP通过网络发送数据,就是把我的发送缓冲区的数据通过网络拷贝到对方的接受缓冲区。
TCP支持全双工本质是它有一对发送缓冲区和接受缓冲区。
我们的任务,本质一个cp问题,它在每一个的缓冲区单元内进行生产和消费。
我们发送数据不能直接发送结构体,因为我们不同设备之间,大小端问题不统一,还有我们的语言问题,还有内存对齐问题,但是在内核发送数据可以这么发,因为内核都是用C语言写的,语言是统一的,大小端也是统一的,内存对齐的问题也不存在。
OS之间就是用我们的结构体来进行数据传输的。
但是应用层不可以用结构体,因为它们会出现我们上述的问题。
所以应用层之间的数据发送,我们需要将我们的数据进行序列化,然后传过去再进行反序列化。
这就是把我们结构体序列化成我们的字符串,结构体不能传输,转成字符串可以传输呀,然后我们共同约定我们的结构体含义,我们就可以根据字符串进行序列化和反序列化。
你看我们如果发送一条结构体信息,我们在上层把它序列化传给我们的TCP让它发送给对方,然后对方根据我们传输的信息进行反序列化,用我们发送的字符串对约定的结构体进行填充,我们就实现了一次传输,同层来看是以结构体来传输的,实际底层是进行了对应的序列化和反序列化。
所以协议就是一种约定,约定了我们字符串的含义,让我们通过这些协议我们可以实现结构体之间的传输。
我们的序列化和反序列化有2个好处,一个是解决了结构体无法进行传输的问题,还有就是方便了我们协议的可扩展性,假如哪一天我的协议更新了,我们只需要把我们传输的信息进行修改就可以。