对recv和send的认识

1.ssize_t send (int s,const void *msg,size_t len,int flags);
  s,发送端Socket描述符。
  msg,表示要传输的消息
  len,表示要传输的字节数
  flags,一般为0
  0: 与write()无异
  MSG_DONTROUTE:告诉内核,目标主机在本地网络,不用查路由表
  MSG_DONTWAIT:将单个I/O操作设置为非阻塞模式
  MSG_OOB:指明发送的是带外信息
  send 只是将数据拷贝到发送端的Socket的发送缓充区。具体的发送数据的过程是由具体的连接协议来完成的。(TCP或者UDP),所以它成功返回后,并不表示数据已经成功发送到另一端。
2.int PASCAL FAR recv( SOCKET s, char FAR* buf, int len, int flags);
  s:接收端Socket的描述符
  buf:用于接收数据的缓冲区。
  len:buf的长度。
  flags:一般为0
   0:常规操作,与read()相同
   MSG_DONTWAIT:将单个I/O操作设置为非阻塞模式
   MSG_OOB:指明发送的是带外信息
   MSG_PEEK:可以查看可读的信息,在接收数据后不会将这些数据丢失
   MSG_WAITALL:通知内核直到读到请求的数据字节数时,才返回。
    recv 只是将数据从接收端的Socket的接收缓冲区拷贝到buf。具体的接收数据的过程是由具体的连接协议来完成的。(TCP或者UDP),如果返回值的大小和buf 的大小一样,说明数据还没有接收完毕。
3. send 的发送过程。
  <1> 如果 len 大于 发送端的Socket的发送缓冲区的大小,那么函数返回SOCKET_ERROR
  <2> 如果len 小于等于发送端的Socket 的发送缓冲区的大小,那么先判断Socket 是否正咋在发送数据,如果正在发送数据,则等待它发送完毕。
  <3> 如果 Socket 的缓冲区没有数据或者Socket 没有发送数据,那么就比较缓冲区剩余空间和len的大小。
  <4> 如果len小于Socket发送缓冲区剩余空间的大小,那么将msg 拷贝到发送缓冲区的剩余空间
  <5> 如果 len 大于Socket发送缓冲区剩余空间的大小,那么将等待Socket的发送缓冲区将数据发送完毕。
  <6> 如果拷贝数据成功,send就返回靠所拷贝数据的字节数。
  <7> 如果send在拷贝数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待Socket的发送缓冲区传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。
4.recv 的接收过程。
  调用recv函数时,recv先等待Socket的发送缓冲中的数据被传送完毕,如果Socket的发送缓冲中的数据传输时时出现网络错误,那么recv函数返回SOCKET_ERROR,如果Socket的发送缓冲中没有数据或者数据被成功发送完毕后,recv先检查Socket的接收缓冲区,如果Socket接收缓冲区中没有数据或者正在接收数据,那么recv就一直等待,直到数据接收完毕。当数据接收完毕,recv函数就把Socket的接收缓冲中的数据copy到buf中。recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待接收数据时网络中断了,那么它返回0。
5.send 和recv 有阻塞和非阻塞之分。
  通过flag参数可以设置阻塞与非阻塞的属性。
  send 的调用过程中,如果len大于Socket发送缓冲区剩余空间的大小,也就是说 Socket 没有足够的缓冲区来发送你的数据,那么默认情况下你必须等待有足够的缓冲区来拷贝数据。这就是阻塞的过程,如果设置了 MSG_DONTWAIT,那么Send就不会等待,直接返回。
  recv的调用过程中,如果Socket接收缓冲区没有数据,那么默认情况下你必须等待数据,这就是阻塞过程,如果设置了 MSG_DONTWAIT,那么recv 就不会等待,直接返回.

你可能感兴趣的:(对recv和send的认识)