最近刚开始啃Unix网络编程(卷1:套接字联网API),为加深TCP连接的建立和终止的理解与记忆,记下本文,方便以后翻看。

  同时留下的还有简单的Socket(TCP)类:

  mySocket.h

 #pragma once

 #include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
#include <errno.h>
#include <fcntl.h> #include <iostream>
#include <string> using namespace std; const int MAXLISTEN = ;
const int MAXLINE = ; class mySocket
{
public:
mySocket();
~mySocket(); bool Init();
bool Bind(const long port);
bool Listen();
bool Accept(mySocket client);
bool Connect(const string host,const long port); bool Send(mySocket client,string msg);
int Receive(mySocket client,string& msg); //设置阻塞或非阻塞
bool setNonBlock(bool flag); struct sockaddr_in getAddr();
int getFD(); private:
int m_fd;
int m_rtn;
struct sockaddr_in m_addr;
};

  mySocket.cpp

 #include <iostream>

 #include "mySocket.h"

 mySocket::mySocket()
{
m_fd = -;
} mySocket::~mySocket()
{
if(m_fd >= )
{
close(m_fd);
m_fd = -;
}
} bool mySocket::Init()
{
m_fd = socket(AF_INET,SOCK_STREAM,);
if(m_fd < )
{
cout<<"init socket error:"<<endl;
return false;
}
return true;
} bool mySocket::Bind(const long port)
{
bzero(m_addr,sizeof(m_addr));
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons(port);
m_addr.sin_addr.s_addr = htonl(INADDR_ANY); if((m_rtn = bind(m_fd,(struct sockaddr*)&m_addr,sizeof(m_addr))) < )
{
cout<<"bind error"<<endl;
return false;
}
else
return true;
} bool mySocket::Listen()
{
if(listen(m_fd,MAXLISTEN) < )
{
cout<<"listen error"<<endl;
return false;
}
else
return true;
} bool mySocket::Accept(mySocket client)
{
int cliLen = sizeof(client.getAddr());
again:
if((m_rtn = accept(m_fd,(struct sockaddr*)&(client.getAddr()),&cliLen)) < )
{
if(errno == ECONNABORTED || errno == EINTR)
goto again;
else
{
cout<<"accept error"<<endl;
return false;
}
}
else
return true;
} bool mySocket::Connect(const string host,const long port)
{
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons(port);
m_addr.sin_addr.s_addr = inet_addr(host.c_str()); if(connect(m_fd,(struct sockaddr *)&m_addr,sizeof(m_addr)) < )
{
cout<<"connect error"<<endl;
return false;
}
else
return true;
} bool mySocket::Send(mySocket client,string msg)
{
m_rtn = send(client.m_fd,msg.c_str(),msg.size());
if(rtn < )
{
cout<<"send error"<<endl;
return false;
}
return true;
} int mySocket::Receive(mySocket client,string& msg)
{
char buf[MAXLINE] = {};
msg.clear(); tn = recv(client.m_fd,buf,sizeof(buf));
if(rtn < )
{
cout<<"receive error"<<endl;
return -;
}
else if(rtn == )
return ;
else
{
msg = buf;
return rtn;
}
} void mySocket::setNonBlock(bool flag)
{
int opt = fcntl(m_fd,F_GETFL);
if(opt < )
{
cout<<"SetNonBlock error"<<endl;
return;
} if(flag)
opt = (opt | O_NONBLOCK);
else
opt = (opt & O_NONBLOCK); fcntl(m_fd,F_SETFL,opt);
} struct sockaddr_in mySocket::getAddr()
{
return m_addr;
} int mySocket::getFD()
{
return m_fd;
}

  1、TCP连接的建立

  TCP通过三次握手建立连接。在建立连接之前,服务器必须准备好接受外来的连接,通常通过socket、bind、listen这3个函数来完成,此过程被称为被动打开。

  (1)客户端(外来连接)通过调用connect发起主动打开。此时客户端发送一个SYN(同步)分节,通知服务器客户端将在连接中发送的数据的初始序列号。通常SYN分节不携带数据,其所在的IP数据报只包含一个IP首部、一个TCP首部及可能有的TCP选项。

  (2)服务器必须确认(ACK)客户端的SYN,同时自己也得发送一个SYN分节,包含服务器将在同一连接中发送的数据的初始序列号。服务器在单个分节中发送SYN和对客户端SYN的ACK(确认)。

  (3)客户端必须确认服务器的SYN。

  具体过程如下图:

  

  2、TCP连接终止

  TCP断开连接需要通过四次挥手来完成,具体过程如下:

  (1)某个应用进程首先调用close函数,称为该端的主动关闭。该端TCP发送一个FIN分节,表示数据发送完毕。

  (2)接收到这个FIN的对端执行被动关闭。这个FIN由TCP确认。它的接收也作为一个文件结束符(eof)传递给接收端的应用进程,因为FIN的接收意味着接收端的应用进程在相应的连接上再无额外数据可接收。

  (3)一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字,导致它的TCP也发送一个FIN。

  (4)接收到这个最终的FIN的原发送端TCP确认这个FIN。

  图示如下:

  

码海拾遗:简单Socket(TCP)类实现的更多相关文章

  1. 码海拾遗:基于MySQL Connector/C++的MySQL操作(连接池)

    1.MySQL安装及简单设置 (1)安装:在OSX系统下,可以使用万能的“brew install”命令来进行安装:brew isntall mysql(默认安装最新版的MySQL) (2)启动:br ...

  2. 码海拾遗:Linux常用命令(一)

    一.Linux系统安装 系统安装可以分两类:实体机安装Linux,虚拟机(常用虚拟机软件有两种:VMware和VirtualBox)安装Linux. 安装过程网上有很多教程,这里就不赘述了. 二.常用 ...

  3. 码海拾遗:简述C++(一)

    C++是Bjarne Stroustrup博士于1982年,在C语言的基础上引入并扩充了面向对象的概念后发明的一种新的程序语言.就与C语言的渊源而言,C++可以说是C语言的超集,它兼容C的一切(可能是 ...

  4. 码海拾遗:strcpy()、strncpy()和strcpy_s()区别

    1.strcpy() 原型:char *strcpy(char *dst,const char *src) 功能:将以src为首地址的字符串复制到以dst为首地址的字符串,包括'\0'结束符,返回ds ...

  5. 码海拾遗:Linux多线程mutex锁

    多线程计数,每个线程累加10个数. 实现: #include <stdio.h> #include <stdlib.h> #include <string.h> # ...

  6. 码海拾遗:strstr()、strcmp()和strcpy()实现

    1.strstr()实现 原型:char * strstr(const char * str1, const char * str2) 说明:判断str2是否为str1的子串,如果是则返回str2第一 ...

  7. ActionScript简单实现Socket Tcp应用协议分析器

    转自..smark http://www.cnblogs.com/smark/archive/2012/05/15/2501507.html ActionScript简单实现Socket Tcp应用协 ...

  8. C#socket编程之实现一个简单的TCP通信

    TCP(TransmissionControl Protocol)传输控制协议. 是一种可靠的.面向连接的协议(eg:打电话).传输效率低全双工通信(发送缓存&接收缓存).面向字节流.使用TC ...

  9. 基于Tcp协议的简单Socket通信实例(JAVA)

    好久没写博客了,前段时间忙于做项目,耽误了些时间,今天开始继续写起~ 今天来讲下关于Socket通信的简单应用,关于什么是Socket以及一些网络编程的基础,这里就不提了,只记录最简单易懂实用的东西. ...

随机推荐

  1. 题解【DP100题1~10】

    哎~这事做晚了~ (Dp100计划T1) 只有蓝题及以上才会水题解 分行Dp,行间没有转移 \[ F[L][R] = max(F[L+1][R]+2^k \times V[L],F[L][R-1]+2 ...

  2. 2019深圳Android千人开发者大会【NEW·无界】

    报名地址:https://www.hdb.com/dis/mjcsegnslu 安卓巴士技术社区是中国领先的安卓开发者社区,现已聚集超过85万开发者,数年来一直致力于IT从业者的知识分享服务. 安卓巴 ...

  3. Python语言学习:字符串常用的方法

    python字符串常用的方法 1. find( ):在字符串中搜索指定的值并返回它被找到的位置,如果没有找到,则返回-1 string.find(value,start,end) #value:必需, ...

  4. MySQL出现错误1030-Got error 28 from storage engine

    磁盘空间不足引起的!1030-Got error 28 from storage engine df -h 清理空间

  5. Hibernate相关概念及序列化和持久化的区别

    hibernate是一种ORM(object relation mapping,对象关系映射)框架,所谓的对象关系映射,通俗的说,就是把JAVA对象保存到关系型数据库中. hibernate要做的事, ...

  6. VMware vSphere ESXi 和 vCenter Server 5.1 文档地址

    VMware vSphere ESXi 和 vCenter Server 5.1 文档地址       https://pubs.vmware.com/vsphere-51/index.jsp?top ...

  7. 简单的使用httpclient读取网页html例子

    public void clientPost(String url) {  /* 1 生成 HttpClinet 对象并设置参数*/    HttpClient httpClient=new Http ...

  8. Jmeter连接Mysql出现Cannot create PoolableConnectionFactory (Could not create connection to database server.)错误

    0 环境 系统环境:win10 1 正文 一般是数据库的驱动包版本不匹配(我是直接放在jmeter/lib下的) 当然有时候需要添加?useUnicode=true&characterEnco ...

  9. C/C++预处理指令#include,#define,#undef,#if,#ifdef,#ifndef,#elif,#endif,#error......

    本文主要记录了C/C++预处理指令,常见的预处理指令如下: #空指令,无任何效果 #include包含一个源代码文件 #define定义宏 #undef取消已定义的宏 #if如果给定条件为真,则编译下 ...

  10. python en(de)code

    python爬虫 代码写挺长的,也是边学边写,但一直搞不清楚python的encode(编码)和decode(解码).以下是我的探究之路. 一.当然先看官方文档 地址如下 里面提到encode函数'R ...