TCP Posix API的理解

我们主要从TCP连接讲解整个的流程。

  • 连接的建立
  • 消息的收发
  • 连接的断开

连接的建立

先看一下一个TCP server的创建过程。

#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>
using namespace std; int main(int argc, char *argv[])
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd<0)
{
printf("Create Socket failed!code:%d\n", errno);
return -1;
}
struct sockaddr_in ServerAddr; memset(&ServerAddr, 0, sizeof(ServerAddr)); ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
ServerAddr.sin_port = htons(9999);
if (bind(sockfd, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr))<0)
{
printf("bind function is failed!error code:%d\n", errno);
return -1;
}
if (listen(sockfd,10)<0)
{
printf("listen function is failed!error code:%d\n", errno);
return -1;
} //开始接受TCP连接
while (true)
{
socklen_t len = 0;
int client_sock = accept(sockfd, (struct sockaddr*)&socket, &len);
if (client_sock<0)
{
printf("accept() error ! error code:%d\n", errno);
return -1;
} char buf[2048];
while(1)
{
memset(buf,'\0',sizeof(buf));
read(client_sock,buf,sizeof(buf)); printf("client:# %s\n",buf); printf("server:$ "); memset(buf,'\0',sizeof(buf)); fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]='\0';
if(strncasecmp(buf,"quit",4)==0)
{
printf("quit\n");
break;
}
write(client_sock,buf,strlen(buf)+1);
printf("wait...\n");
}
close(client_sock);
} close(sockfd); return 0;
}

准备一张TCP状态转换图

三次握手的过程。

比较常会被问到的为什么3次握手?

其实就是需要3次确定连接。

其次就是对应的API的阶段是什么。

在服务器端调用listen以后,客户端开始进行连接的时候,

一般都会在第一次握手的时候,维护一个链表,表明已经进行过第一次握手的半连接。

其次就是在第三次握手以后,就会将这个连接,保存到另外一个全连接的队列,表示这个连接已经三次握手完毕,可以进行连接。

然后我们在服务端的时候,就可以调用accept进行连接的接受。

从我们的已经准备的好的全连接的队列中,取出一个连接,在进行消息的收发。

我们再讨论一下 listen中的backlog这个参数的作用。

这个参数根据文档来说是这样的

The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow.
If a connection request arrives when the queue is full, the client may receive an error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the request may be ignored so that a later reattempt at connection succeeds.

而我们可以从文档中看出来,这个队列主要指的是全连接队列的长度,指定我们全连接队列的长度的大小。

顺便说一下ddos的攻击问题,我的连接就是有大量的经过第一次握手的连接的客户端和目标服务器进行连接,导致新的连接。

数据发送阶段

这里我们只考虑我们可以控制的阶段,比如消息的收发,对于消息在公网区域是如何传输的,我们是无法进行控制以及追踪的,因此我们就考虑消息的收发。

普遍存在三种情况,

  • 单条send
  • 循环send
  • 发送很多的数据的send

    首先,有一点,在我们创建完一个TCP连接的时候,就会知道源IP,目的IP,源端口,目的端口,以及对应的协议类型,也就存在一个TCB的概念。

由于第一种的send的情况比较普遍,就是直接的收发就可以了,我们在实际调用send的时候,并不是返回是整数,就代表着我们的信息已经发送成功了,其实只是将我们想要发送的信息黏贴在内核的发送缓冲区中,TCP只是能保证我们的消息顺序是顺序的。这样就在我们循环发送的消息的时候,可能就会出现一个问题,就是TCP粘包的问题。

怎么解决粘包的问题?

  • 增加包长度的信息
  • 增加分隔符

    通过这两种方法就能解决TCP粘包的问题了。

最后一种就是发送一个文件之类的,规定一个消息的结构,并发送完毕就可以了。

连接断开

网线断了(网线剪短),网卡停止供电,网卡设备会重启,你所有的连接都会重启。

再次供电的时候,就会有变化。应用程序就通过心跳包,来判断连接是否已经断开。客户端直接宕机,也是通过心跳包来进行判断。

这里主要就是讨论就是如何解决close_wait的情况。

主要是由于recv返回0,没有调用close。

业务数据和网络接口,可以做成异步的。

推荐一个零声学院免费教程,个人觉得老师讲得不错,

分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,

fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,

TCP/IP,协程,DPDK等技术内容,点击立即学习:

服务器

音视频

dpdk

Linux内核

posix API的一些理解的更多相关文章

  1. 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(4)

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

  2. 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(3)

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

  3. 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(2)

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

  4. 对一个前端使用AngularJS后端使用ASP.NET Web API项目的理解(1)

    chsakell分享了一个前端使用AngularJS,后端使用ASP.NET Web API的项目. 源码: https://github.com/chsakell/spa-webapi-angula ...

  5. The POSIX API/nss/nscd

    https://code.google.com/p/nsscache/wiki/BackgroundOnNameServiceSwitch The POSIX API POSIX is a stand ...

  6. web api token验证理解

    最近一直在学习web api authentication,以Jwt为例,可以这样理解,token是身份证,用户名和密码是户口本,身份证是有有效期的(jwt 有过期时间),且携带方便(自己带有所有信息 ...

  7. Web API与AJAX:理解FormBody和 FormUri的WebAPI中的属性

    这是这一系列文章"与 AJAX 的 Web API".在这一系列我们都解释消耗 Web API rest 风格的服务使用 jQuery ajax() 和其他方法的各种方法.您可以阅 ...

  8. POSIX 多线程编程及理解

    最近开发基于ZYNQ的嵌入式linux程序,涉及到多线程使用,将一些内容整理如下: POSIX多线程编程最为基础和重要的可以分为两部分: 线程操作-Thread Management 线程同步-Syn ...

  9. .net web api 的route理解

    .NET web api 的特性是和MVC一样,通过Route 来控制action的访问方式.Route匹配规则是个奇特的方式,首先看一段Route的模板 Routes.MapHttpRoute( n ...

  10. 对一个前端AngularJS,后端OData,ASP.NET Web API案例的理解

    依然chsakell,他写了一篇前端AngularJS,后端OData,ASP.NET Web API的Demo,关于OData在ASP.NET Web API中的正删改查没有什么特别之处,但在前端调 ...

随机推荐

  1. 史上最大电池!小米智能家庭屏Pro 8图赏

    今天小米智能家庭屏 Pro 8正式开售,集智能家居中控,智能网关以及娱乐教育三大功能为一体,首发749元. 它是一款全新的智能生态产品中控屏,配备了7500mAh大容量电池以及通用性更好的USB Ty ...

  2. Cygwin,在windows中使用linux命令

    习惯了 linux 命令的快捷操作,使用 winodws 的 shell 感觉效率非常低下,于是开始搜寻工具支持. 刚开始搜到的是 GnuWin32,但是它已经停止更新维护了,于是找到了 Cygwin ...

  3. 【Flink入门修炼】1-1 为什么要学习 Flink?

    流处理和批处理是什么? 什么是 Flink?为什么要学习 Flink? Flink 有什么特点,能做什么? 本文将为你解答以上问题. 一.批处理和流处理 早些年,大数据处理还主要为批处理,一般按天或小 ...

  4. npm script 详解,tsc && electron . 直接编译后 运行,非常方便

    最终平时只需要用这个方法就可以了: tsc && electron . ======================================================== ...

  5. [Redis] Redis的三大缓存异常原因分析和解决方案

    Redis的三大缓存异常原因分析和解决方案 缓存的三个异常分别是缓存击穿.缓存雪崩.缓存穿透.这三个问题一旦发生,会导致大量的请求积压到数据库层,并发量巨大的情况下很有可能导致数据库宕机或是故障,造成 ...

  6. NC216012 Let'sPlayCurling

    题目链接 题目 题目描述 Curling is a sport in which players slide stones on a sheet of ice toward a target area ...

  7. STM32F401的PWM输出

    PWM的说明 PWM有三个关键指标: PWM频率, 占空比, 区分度 对于同一个时钟频率下工作的单片机, 区分度是和PWM工作频率相关的, 因为总频率是固定的, PWM工作频率越高, 留下给区分度的部 ...

  8. 【Unity3D】半球卷屏特效

    1 原理 ​ 凸镜贴图 和 渐变凸镜贴图 中介绍了使用 OpenGL 实现凸镜贴图及其原理,通过顶点坐标映射到纹理坐标,并构造三角形网格,构建了真正的三维凸镜模型.本文通过 Shader 实现半球卷屏 ...

  9. 【Unity3D】Tank大战

    1 需求实现 ​ 项目代码见→坦克大战1.1.0 ​ 1)人机交互 玩家通过 ↑ ↓ ← → 键(或 W.S.A.D)键控制己方坦克平移: 玩家通过滑动鼠标右键控制己方坦克左右旋转: 玩家通过鼠标左键 ...

  10. 我的小程序之旅七:微信公众号设置IP白名单

    一.为什么要配置IP白名单 此处IP为服务器对公网IP: 在IP白名单内的IP地址作为来源,获取access_token接口才可调用成功. 而想要调用公众号相关API,就必须获取access_toke ...