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

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

在另外一边的客户端,我们分析一下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, 
0
sizeof
(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://www.cnblogs.com/yin-jingyu/archive/2012/06/06/2537564.html

你可能感兴趣的文章
【原】小程序常见问题整理
查看>>
C# ITextSharp pdf 自动打印
查看>>
【Java】synchronized与lock的区别
查看>>
django高级应用(分页功能)
查看>>
【转】Linux之printf命令
查看>>
关于PHP会话:session和cookie
查看>>
STM32F10x_RTC秒中断
查看>>
display:none和visiblity:hidden区别
查看>>
C#double转化成字符串 保留小数位数, 不以科学计数法的形式出现。
查看>>
SpringMVC学习总结(三)——Controller接口详解(1)
查看>>
牛的障碍Cow Steeplechase
查看>>
Zookeeper选举算法原理
查看>>
3月29日AM
查看>>
利用IP地址查询接口来查询IP归属地
查看>>
HTML元素定义 ID,Class,Style的优先级
查看>>
构造者模式
查看>>
http和https的区别
查看>>
Hbuild在线云ios打包失败,提示BuildConfigure Failed 31013 App Store 图标 未找到 解决方法...
查看>>
找到树中指定id的所有父节点
查看>>
今天新开通了博客
查看>>