当前位置: 首页 > news >正文

【socket】Socket send函数和recv函数详解

Socket send函数和recv函数详解

1.send 函数

int send( SOCKET s, const char FAR *buf, int len, int flags );  

    不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。

    该函数的第一个参数指定发送端套接字描述符;

    第二个参数指明一个存放应用程序要发送数据的缓冲区;

    第三个参数指明实际要发送的数据的字节数;

    第四个参数一般置0。 

    这里只描述同步Socket的send函数的执行流程。当调用该函数时,

   (1)send先比较待发送数据的长度len和套接字s的发送缓冲的长度, 如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;

   (2)如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len

   (3)如果len大于剩余空间大小,send就一直等待协议把s的发送缓冲中的数据发送完

   (4)如果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信号,进程对该信号的默认处理是进程终止。

通过测试发现,异步socket的send函数在网络刚刚断开时还能发送返回相应的字节数,同时使用select检测也是可写的,但是过几秒钟之后,再send就会出错了,返回-1。select也不能检测出可写了。

2. recv函数

int recv( SOCKET s, char FAR *buf, int len, int flags);   

    不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。该函数的第一个参数指定接收端套接字描述符;

    第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;

    第三个参数指明buf的长度;

    第四个参数一般置0。

    这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,

    (1)recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,

    (2)如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字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信号,进程对该信号的默认处理是进程终止。

相关文章:

  • 【OLTP与OLAP】OLTP与OLAP的区别
  • 【gcc】 gcc编译工具生成动态库(共享库)和静态库
  • 【cJSON】cJSON 实例
  • 【yum/apt-get】yum/apt-get/rpm/dpkg/brew之间的区别
  • 【删除重复记录】SQL删除重复记录
  • 【myISAM和innoDB】mySql的引擎myisam和innodb的区别/mysiam
  • 【文档/键值数据库】文档数据库和键值数据库有什么区别
  • 【JDBC与JPA】JDBC与JPA
  • Apache+Tomcat配置转发
  • 【SQLite】SQLServerCompact/SQLiteToolboxVS的SQLite插件使用
  • 【mysql索引】MySQL索引原理及慢查询优化
  • 【趋势和新技术】趋势和技术
  • 【mysql中文编码】mysql中文乱码中文编码问题
  • 【RPC】为什么需要RPC,而不是简单的HTTP接口
  • 【JAVA】java中implements和extends的使用小结
  • 2017-08-04 前端日报
  • Codepen 每日精选(2018-3-25)
  • JavaScript 奇技淫巧
  • Spring Cloud Feign的两种使用姿势
  • ucore操作系统实验笔记 - 重新理解中断
  • vue.js框架原理浅析
  • 如何选择开源的机器学习框架?
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 说说动画卡顿的解决方案
  • 通信类
  • 异常机制详解
  • 用Canvas画一棵二叉树
  • #define与typedef区别
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (十) 初识 Docker file
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • *p++,*(p++),*++p,(*p)++区别?
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .Net Core和.Net Standard直观理解
  • .Net MVC + EF搭建学生管理系统
  • .net 使用$.ajax实现从前台调用后台方法(包含静态方法和非静态方法调用)
  • .NET 中的轻量级线程安全
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .Net接口调试与案例
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .NET开源快速、强大、免费的电子表格组件
  • .net与java建立WebService再互相调用
  • /bin/rm: 参数列表过长"的解决办法
  • [ C++ ] STL_list 使用及其模拟实现
  • [ solr入门 ] - 利用solrJ进行检索
  • [ 云计算 | AWS ] AI 编程助手新势力 Amazon CodeWhisperer:优势功能及实用技巧
  • [ARC066F]Contest with Drinks Hard
  • [BZOJ4566][HAOI2016]找相同字符(SAM)
  • [C++]Leetcode17电话号码的字母组合
  • [C++核心编程](四):类和对象——封装