读写socket套接字的正确姿势

20001ef37d49f06749fc88e3e46cf936.gifa585bf97c892c605af6256f05fa511dc.png

差一点

我们就擦肩而过了

有趣

有用

有态度

5dcaec14bce22616733706b43a9eab15.jpeg

导学问题:

1. 增加缓冲区,可以提高程序的吞吐量吗?
2. 网络数据从发送到接受的过程,总共拷贝了多少次?
发送数据
ssize_t write (int socketfd, const void *buffer, size_t size)
ssize_t send (int socketfd, const void *buffer, size_t size, int flags)
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)

这三个都是发送程序时常用的接口,大部分人可以都很熟悉write函数了,经典的写文件接口。我们这里重点给大家介绍后两种。

如果我们想发送紧急数据,那么我们就可以使用send接口,给发送的数据加上紧急标记,那么我们的这一帧数据就会快速被发送出去。

如果想指定多重缓冲区进行数据传输,就需要使用第三个函数,以结构体msghdr的方式发送数据。

发送缓冲区

当tcp连接成功后,在linux内核里面会维护一个发送缓存区。它的大小可以通过调整套接字选项来进行设置。当我们应用程序调用write函数时,实际上是把数据从应用程序拷贝到操作系统内核的发送缓存区,它并不一定马上就会发送出去。具体情况如下:

  • 发送缓存区足够大,那么write的系统调用会马上退出,返回写入的字节数就是应用程序的大小。

  • 发送缓存区不足以容纳应用程序的数据,那么write函数会一直阻塞,直到应用数据完全填充到缓存区后返回,缓存区的数据由操作系统内核负责把它发送出去。

如下图:

d5cef91e47d4c4bf10c06d0acd932ac1.png

所以无限增大缓冲区肯定不行,内核缓冲区总是充满数据时会产生粘包问题,同时网络 的传输大小MTU也会限制每次发送的大小,最后由于数据堵塞需要消耗大量内存资源,资 源使用效率不高。相当于让仓库变大,可以存储了更多的货物,如果出货的速度有限,会有更多的货物烂在仓库里。

读取数据

最简单的数据读取方式就是read函数了,它的函数原型如下:

ssize_t read (int socketfd, void *buffer, size_t size)

read函数要求操作系统内核从套接字描述子socketfd读取固定数量的字节,并将读取的结果存储到buffer中。返回值告诉我们读取的实际字节数量。特殊情况下,如果它的返回值为0,那么代表EOF,表示网络中对端发送了FIN,我们也要相应地进行断开连接处理。而如果返回-1,则代表出错。

阻塞式套接字最终发送返回的实际写入字节数和请求字节数是相等的。发送成功仅仅表示的是数据被拷贝到了发送缓冲区中,并不意味着连接对端已经收到所有的数据。至于什么时候发送到对端的接收缓冲区,或者更进一步说,什么时候被对方应用程序缓冲所接收,对我们而言完全都是透明的。

总结

对于send发送数据来说,返回成功仅代表数据写到发送缓存区成功,并不代表对端已经接收成功。而对于read来说,需要循坏读取数据,并且要考虑EOF等异常条件

52f588eb325e892a75dda4ff1dc85365.gif

b370e311783abc32906bd031975119bc.gif

怎样学好网络编程?

socket套接字地址介绍

分享一款Linux平台下的tcp协议栈!超级透彻!

TCP/IP和Unix的发展轨迹

0adef1909ebcbd7e3423ab12778d8f93.gif

扫码二维码

获取更多精彩

just enjoy it!

3bd6c69133b5ad37566c5ccbe87f52ef.png

7d7731918fde63210aee0943a454f0fc.gif

fa8c1891741645c394c4d49b214225e9.png

点在看~

b2c74140b632f91bddd4922588c373d8.gif

捧个人场就行~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值