博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
socket 编程入门教程(三)TCP原理:4、设计TCP socket的类(下)
阅读量:6070 次
发布时间:2019-06-20

本文共 2055 字,大约阅读时间需要 6 分钟。

hot3.png

在另外一边的客户端,我们分析一下TCPClientSock的建立过程。

class TCPClientSock: public BaseSock{

private:
    sockaddr_in serverSockAddr;
protected:
    
char* preBuffer;
    
int preBufferSize;
    mutable 
int preReceivedLength;
public:
    TCPClientSock(
        
const char* server_IP,
        unsigned 
short server_port,
        
int pre_buffer_size = 32);
    
virtual ~TCPClientSock();
    
int TCPReceive() const;
    
int TCPSend(const char* send_data,
            
const int& data_length) const;
};

我们看到TCPClientSock的类与TCPServerSock很类似,构造函数的差别是,TCPClientSock需要提供server端的IP地址和端口号。

TCPClientSock::TCPClientSock(

                    const char *server_IP,
                    unsigned 
short server_port,
                    
int pre_buffer_size):
preBufferSize(pre_buffer_size),
preReceivedLength(
0)
{
    preBuffer 
= new char[preBufferSize];
    sockFD 
= socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    
if (sockFD < 0) {
        sockClass::error_info(
"sock() failed.");
    }
    memset(
&serverSockAddr, 0sizeof(serverSockAddr));
    serverSockAddr.sin_family 
= AF_INET;
    serverSockAddr.sin_addr.s_addr 
= inet_addr(server_IP);
    serverSockAddr.sin_port 
= htons(server_port);
    
if (connect(sockFD,
                (
struct sockaddr*)&serverSockAddr,
                
sizeof(serverSockAddr)) < 0 ) {
        sockClass::error_info(
"connect() failed.");
    }
}
TCPClientSock::
~TCPClientSock()
{
    delete [] preBuffer;
    close(sockFD);
}

TCPClientSock通过socket()建立起sockFD,然后指定服务器的serverSockAddr,然后通过connect()向serverSockAddr指定的服务器发出握手请求。需要说明的是,调用connect()的时候,系统会检查TCPClientSock的sockFD是否已经绑定了本机的SockAddr,事实上我们也可以通过bind()将本机的IP和指定的端口号绑定在这个sockFD上,但是我们并不关心这个IP地址和端口号(况且很多主机并没有公网IP,特别在中国),所以通常我们不自己去绑定,这样系统就会帮我们完成绑定工作,分配一个空闲的端口号作为本机地址的端口号。

这样TCPClientSock具有来向(本机地址,通常由系统自动完成绑定,也可以指定)和去向(指定的server端地址)的地址信息,所以可以收发信息。于是,TCPClientSock发出的第一个数据报是发给server监听socket的握手请求数据报,TCPListenSock接收这个数据报后,将相关信息传递给TCPServerSock建立新的sockFD,我们上一节讲到,这个新的sockFD建立起来之后马上就向client端返回一个数据报:一方面表示接受第一次握手请求,另外一方面发出第二次握手请求。
收到第二次握手请求后,connect()才会返回,不然就会阻塞,非常“尽力”的去连接server。这个“尽力”的程度跟系统有关,在我的试验中,windows下很快,就几秒;而Debian则接近6分钟!
connect()返回的同时,向server发出了第三次握手的信息,这个信息是对第二次握手请求的认可。所以,第一次和第二次握手包含着连接的请求;而第二次和第三次握手则包含着对握手请求的认可,他们都是在告诉对方:我知道并同意你连接上我了。
至此,TCP三次握手的概念在socket中完整的实现,建立起数据流的TCP通信通道。

转载于:https://my.oschina.net/GeorgeSu/blog/264195

你可能感兴趣的文章
Linux 获取文件夹下的所有文件
查看>>
对 Sea.js 进行配置(一) seajs.config
查看>>
dom4j解析xml文件
查看>>
第六周
查看>>
斯坦福大学公开课机器学习:梯度下降运算的学习率a(gradient descent in practice 2:learning rate alpha)...
查看>>
解释一下 P/NP/NP-Complete/NP-Hard 等问题
查看>>
javafx for android or ios ?
查看>>
微软职位内部推荐-Senior Software Engineer II-Sharepoint
查看>>
sql 字符串操作
查看>>
【转】Android布局优化之ViewStub
查看>>
网络安全管理技术作业-SNMP实验报告
查看>>
根据Uri获取文件的绝对路径
查看>>
Fundebug前端JavaScript插件更新至1.6.0,新增test()方法用于测试
查看>>
Flutter 插件开发:以微信SDK为例
查看>>
.NET[C#]中NullReferenceException(未将对象引用到实例)是什么问题?如何修复处理?...
查看>>
边缘控制平面Ambassador全解读
查看>>
Windows Phone 7 利用计时器DispatcherTimer创建时钟
查看>>
程序员最喜爱的12个Android应用开发框架二(转)
查看>>
vim学习与理解
查看>>
DIRECTSHOW在VS2005中PVOID64问题和配置问题
查看>>