int send( SOCKET s,const char FAR *buf,int len,int flags );
不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。
客户程序一般用send函数向服务器发送请求,
而服务器则通常用send函数来向客户程序发送应答。
该函数的第一个参数
第二个参数指明
第三个参数指明
第四个参数一般置0。
这里只描述同步Socket的send函数的执行流程。
当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲的
长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;
如果len小于或者等于s的发送缓冲区的长度,
那么send先检查协议 是否正在发送s的发送缓冲中的数据,
如果是就等待协议把数据发送完,
如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,
那么 send就比较s的发送缓冲区的剩余空间和len,
如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,
如果len小于剩余 空间大小send就仅仅把buf中的数据copy到剩余空间里
(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,
而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)
。如果send函数copy数据成功,就返回实际copy的字节数,
如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;
如果send在等待协议传送数据时网络断开的话,
那么send函数也返回SOCKET_ERROR。
要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里
后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。
如 果协议在后续的传送过程中出现网络错误的话,
那么下一个Socket函数就会返回SOCKET_ERROR。
(每一个除send外的Socket函数在执 行的最开始总要先等待套接字的
发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,
那么该Socket函数就返回 SOCKET_ERROR)
注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,
调用send的进程会接收到一个SIGPIPE信号,
进程对该信号的默认处理是进程终止。
recv函数
int recv( SOCKET s,char FAR *buf,int len, int flags);
不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。
该函数的第一个参数 指定接收端套接字描述符;
第二个参数指明 一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
第三个参数指明 buf的长度;
第四个参数一般置0。
这里只描述同步Socket的recv函数的执行流程。
当应用程序调用recv函数时,recv先等待s的发送缓冲
如果协议在传送s的发送缓冲中的数据时出现网络错误,
那么recv函数返回SOCKET_ERROR,如果s的发送缓冲中没有数
如果s接收缓冲区中没有数据或者协议正在接收数据,
那么recv就一直等待,直到 协议把数据接收完毕。
当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中
(注意协议接收到的数据可能大于buf的长度,所以
在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。
recv函数仅仅是copy数据,真正的接收数据是协议来完成的),
recv函数返回其实际copy的字节数。如果recv在copy时出错,
那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,
那么它返回0。
注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,
那么调用recv的进程会接收到一个SIGPIPE信号,
进程对该信号的默认处理是进程终止。
int send (
);
请问send函数每次最多可以发送多少数据?是int的最大值吗?
不是int的最大值
理论上似乎是一个窗口大小减去协议头的大小
不是, send
int send (
);
Send分为阻塞和非阻塞,阻塞模式下,如果正常的话,
会直到把你所需要发送的数据发完再返回;
非阻塞,会根据你的socket在底层的可用缓冲区的大小,
来将你的缓冲区当中的数据拷贝过去,有多大缓冲区就拷贝多少,
缓冲区满了就立即返回,这个时候的返回值,
只表示拷贝到缓冲区多少数据,但是并不代表发送多少数据,
同时剩下的部分需要你再次调用send才会再一次拷贝到底层缓冲区。