ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【Socket网络通信 | TCP协议分析】

2022-01-01 14:02:58  阅读:129  来源: 互联网

标签:网络通信 协议 Socket 数据 TCP 接字 数据包


Socket网络通信


第二章 初始协议内容


前言

1、接口(套接字)是什么?

套接字是一个由主机本地应用程序所建立,被操作系统所控制的一个接口;应用程序可以依靠这个接口,使用传输层所提供的服务,从而实现跨网络发送给其他应用进程(从其他应用进程中接收消息)

常见最多的例程一般就是用Socket建立一个服务端,一个客户端,而操作系统想要实现两个程序之间的通信,是通过操控中间介质,也就是我们的套接字,来实现的。

LINUX系统下,一切的操作都是文件,而我们程序猿操作的也仍然是中间介质,就是文件描述符,这对于套接字就比较好类比了。


一、TCP协议

1.TCP协议特点

TCP是面向连接的,在传输开始时,是需要先建立连接,三次握手后,才开始传输数据;和UDP协议不同,能直接传递。

TCP提供可靠性,能实现丢失重传。实际上,网络传输上,比如在网线通信过程中,所受的干扰,或者网卡性能上,来不及接收等等可能,物理层上都有可能造成通信失败;TCP每个通信包都加了协议在其中,就支持丢失重传,但不代表着一直丢失就一直重传,也会存在丢包的情况。但基于整个通信而言,它是相对稳妥的。

如果数据包过长的时候,它会被切割成多个数据包进行传输。单对单进行通信的时候,按次序就行收发,基本不存在问题;但网络上不同,经过多个路由器、交换机等等,这些期间数据的传输序列都会发生变化,在监听包的时候,就可以发现经过多个这些中转设备时,虽然数据包1先发出,数据包2后发出,但如果传输路径数据包2比数据包1要短的话,数据包2有可能就先到达目标设备了,就有可能造成数据先后顺序对不上了。这时,TCP本身提供的序列号就给每个包,在建立3次握手连接后,提供顺序的序号就行排列,由底层按照这个序列号,排序好再发送给目标设备

TCP还提供流量控制,限定客户端以多快的速度来接收数据

TCP的连接是全双工的(举例:千兆网卡有一组接口里有两根发送线两根接收线,发送和接收同时进行,互不干扰)

2.TCP协议头

通过捉包工具,其实可以分析出来,我们的数据包内容其实分为以上的部分。
在这里插入图片描述
在上一章中讲到了,TCP层是基于端口号的,有源端口和目的端口。
序号:是确保数据包按顺序发送,在三次握手以后进行排序
确认号:在三次握手时用到
数据偏移:除了上方20个固定字节大小的首部以外(下方还有一个长度可变的选项)致使整个TCP协议头大小可变,真实数据位置就需要进行一定的偏移
(和UDP协议不同,UDP协议头固定,用比较机械的固定大小解包方式便能获得用户数据)
6 bit 协议类型:在建立三次握手时,需要告诉对方,当前的数据包是什么类型的,对方收到信息给予的回包也要标注确认包的数据包类型,通过标志位来标识数据包类型
窗口:实现排序实现数据可靠性的主要内容
检验和:收发数据做的校验(类似sum校验),发生错误的概率相对较小
紧急指针:指向紧急数据的最后一个字节的位置,表示这个包目前有紧急数据,控制流量会等对方全部接收完后才会发送下一次的数据;但紧急数据只要你确定这是个紧急情况,会把这些数据优先发过去(应用不是特别多)

3.窗口分析

在这里插入图片描述
发送方和接收方都会存在独立的窗口

发送方会确认它内部的数据什么时候才需要前移(等数据都发完的时候、超时);接收方会确认它内部的数据什么时候才需要往后移(等数据都接收完的时候);窗口往下移的时候便可以接收新的数据;

窗口基本上就是一个缓存的大小,发送数据和读取数据都不是调用接口后就立即能发送或者接收,都是会排到窗口队列中,等待窗口进行发送;接收也同样的道理,需要等窗口数据处理完后(做好排序后)才能被用户读到

所以说是实现数据可靠性的主要部分

二、程序示例

1.创建一个或N个Socket

这里使用的是 DEV C++ 的编辑编译环境,需要配置一下编译链接内容“工具”–>“编译选项”,
在“编译器”–>“编译时加入以下指令”键入

-lwsock32

因为在WINDOWS下需要引用库才能使用其中的API接口
在这里插入图片描述

#include <windows.h>
#include <stdio.h>


int main(int argc,char* argv[])
{
	int i;

	//1、初始化动态链接库 
	WSADATA ws;//定义一个结构体对象 
	/*
	MAKEWORD定义版本号,把结构体传过去,把对动态库的引用+1 ;
	Windows下对动态库的引用不会反复添加,当所有程序都退出这个库的时候,才会从内存卸载 
	*/
	WSAStartup(MAKEWORD(2,2),&ws);//不调用的话,会导致Socket失败 

	//4、 为了演示资源数量,循环创建一下Socket  
	for(i=0;i<2000;i++)
	{
		//2、创建 Socket 套接字 
		//AF_INET是属于TCP/IP的网络通信协议,用户还可以使用其他的一些诸如蓝牙之类的协议 ;传输层是TCP Or UDP ;最后一个参数在做原始套接字的时候可能会用到 
		int sock = socket(AF_INET,SOCK_STREAM,0); 
		
		//对于Socket通信的步骤,每一步都必须判断是否成功,成功的判断标准就是返回值是否<0
		if(sock == -1)
		{
			//Windows一般资源耗尽才会创建失败,一般很难失败;但Linux上的每个任务分配的(句柄数量)都是有限的 ~ 默认1024个 
			printf("Create Socket Failed !\r\n");
			return -1;		
		} 
		printf("[%d]",sock);
		//3 Or 5、打印后关闭掉 Socket 或者 循环创建时,不关闭 
		closesocket(sock); //会发现,如果循环创建时,原资源没关闭时则一直被占用,没有释放,所以只能使用新资源去创建 (Linux 系统下单个进程对于文件句柄资源有限则,所以会出现创建失败)
		//Linux Console: ulimit -n #查询单进程最大限制资源数  ulimit -n 3000 可以把最大限制资源数设置到 3000 
	} 
	return 0;
}

上面的程序为了演示一下,在Windows环境下,对于Socket函数的创建,以及查看能最大申请的资源


标签:网络通信,协议,Socket,数据,TCP,接字,数据包
来源: https://blog.csdn.net/MJiarong_personal/article/details/121756833

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有