1 TCP协议数据发送与接收的过程
发送:
首先拷贝数据到发送缓冲区,send干的活,send实质是数据拷贝。
其次,协议栈将发送缓冲区中的数据发送出去,至于是不是能发,或者能够发送多少字节,取决于滑动窗口与拥塞窗口,清除被发送的数据。
2 心跳包
抄百度的,心跳包是用于判断是否掉线的,就是在客户端和服务器间定时通知对方自己状态的一个自己定义的消息包,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。网络中的接收和发送数据都是使用SOCKET进行实现。但是如果此套接字已经断开,那发送数据和接收数据的时候就一定会有问题。可是如何判断这个套接字是否还可以使用呢?对于程序员来说,很难确认有效性,这个就需要在系统中创建心跳机制。其实TCP中已经为我们实现了一个叫做心跳的机制。如果你设置了心跳,那TCP就会在一定的时间(比如你设置的是3秒钟)内发送你设置的次数的心跳(比如说2次),并且此信息不会影响你自己定义的协议。所谓“心跳”就是定时发送一个自定义的结构体(心跳包或心跳帧),让对方知道自己“在线”。 以确保链接的有效性。
3 长连接与短连接
长连接就是在TCP建立连接后,读写一次数据完成之后并不立即释放连接, 一般需要自己做在线维持。 比如上面讲到的心跳机制,而短连接是在一次TCP连接之后只进行一次数据的读写就释放连接。
4 套接字编程函数
4.1 send函数
int send(SOCKET s,const char FAR *buf,int len,int flags)
参数:
第一个参数指定套接字描述符。
第二个参数
第二个参数指明一个存放应用程序要发送数据的缓冲区;
第三个参数指明实际要发送的数据的字节数;
第四个参数一般置0。
由于套接字同步,send函数比较发送数据的长度与发送缓冲区的长度,如果数据长度大,函数返回SOCKET_ERROR,如果小于或者等于,函数先检查协议是否正在发送发送缓冲区的数据,如果是则等待发送完成,否则执行发送。如果协议空闲或发送缓冲区为空,那么比较剩余空间,如果待发数据长度大于剩下的空间,则继续等待发送缓冲区中数据发送完成,直至小于,send执行数据拷贝,
如果send函数copy数据成功,此时,并不代表完成了所有的数据拷贝,就返回实际copy的字节数,普遍用法,循环发送,
int nTotal;
int nSend;
while(nSend<nTOtal)
{
nSend = send(s,pBuff[nSend],nTTotal-nSend,0);
nSend+=nSend;
}
如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。Send函数的返回值有三类:
(1)返回值=0:
(2)返回值<0:发送失败,错误原因存于全局变量errno中
(3)返回值>0:表示发送的字节数(实际上是拷贝到发送缓冲中的字节数)
4.2 recv
int recv( SOCKET s, char FAR *buf, int len, int flags )
参数
第一个参数指定接收端套接字描述符;
第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
第三个参数指明buf的长度;
第四个参数一般置0。
这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,recv先等待s的发送缓冲 中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,如果s的发送缓冲中没有数 据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,只到 协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中,recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。