网络编程实战
盛延敏
前大众点评云平台首席架构师
立即订阅
6034 人已学习
课程目录
已完结 39 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 学好网络编程,需要掌握哪些核心问题?
免费
第一模块:基础篇 (9讲)
01 | 追古溯源:TCP/IP和Linux是如何改变世界的?
02 | 网络编程模型:认识客户端-服务器网络模型的基本概念
03丨套接字和地址:像电话和电话号码一样理解它们
04 | TCP三次握手:怎么使用套接字格式建立连接?
05 | 使用套接字进行读写:开始交流吧
06 | 嗨,别忘了UDP这个小兄弟
07 | What? 还有本地套接字?
08 | 工欲善其事必先利其器:学会使用各种工具
09丨答疑篇:学习网络编程前,需要准备哪些东西?
第二模块:提高篇 (10讲)
10 | TIME_WAIT:隐藏在细节下的魔鬼
11 | 优雅地关闭还是粗暴地关闭 ?
12 | 连接无效:使用Keep-Alive还是应用心跳来检测?
13 | 小数据包应对之策:理解TCP协议中的动态数据传输
14丨UDP也可以是“已连接”?
15 | 怎么老是出现“地址已经被使用”?
16 | 如何理解TCP的“流”?
17 | TCP并不总是“可靠”的?
18 | 防人之心不可无:检查数据的有效性
19丨提高篇答疑:如何理解TCP四次挥手?
期中复习周 (2讲)
期中大作业丨动手编写一个自己的程序吧!
免费
期中大作业丨题目以及解答剖析
免费
第三模块:性能篇 (12讲)
20 | 大名⿍⿍的select:看我如何同时感知多个I/O事件
21 | poll:另一种I/O多路复用
22 | 非阻塞I/O:提升性能的加速器
23 | Linux利器:epoll的前世今生
24 | C10K问题:高并发模型设计
25 | 使用阻塞I/O和进程模型:最传统的方式
26 | 使用阻塞I/O和线程模型:换一种轻量的方式
27 | I/O多路复用遇上线程:使用poll单线程处理所有I/O事件
28 | I/O多路复用进阶:子线程使用poll处理连接I/O事件
29 | 渐入佳境:使用epoll和多线程模型
30 | 真正的大杀器:异步I/O探索
31丨性能篇答疑:epoll源码深度剖析
第四模块:实战篇 (4讲)
32 | 自己动手写高性能HTTP服务器(一):设计和思路
33 | 自己动手写高性能HTTP服务器(二):I/O模型和多线程模型实现
34 | 自己动手写高性能HTTP服务器(三):TCP字节流处理和HTTP协议实现
35 | 答疑:编写高性能网络编程框架时,都需要注意哪些问题?
结束语 (1讲)
结束语丨我相信这不是结束,让我们江湖再见
网络编程实战
登录|注册

03丨套接字和地址:像电话和电话号码一样理解它们

盛延敏 2019-08-07
在网络编程中,我们经常会提到 socket 这个词,它的中文翻译为套接字,有的时候也叫做套接口。
socket 这个英文单词的原意是“插口”“插槽”, 在网络编程中,它的寓意是可以通过插口接入的方式,快速完成网络连接和数据收发。你可以把它想象成现实世界的电源插口,或者是早期上网需要的网络插槽,所以 socket 也可以看做是对物理世界的直接映射。
其实计算机程序设计是一门和英文有着紧密联系的学科,很多专有名词使用英文原词比翻译成中文更容易让大家接受。为了方便,在专栏里我们一般会直接使用英文,如果需要翻译就一律用“套接字”这个翻译。

socket 到底是什么?

在网络编程中,到底应该怎么理解 socket 呢?我在这里先呈上这么一张图,你可以先看看。
这张图表达的其实是网络编程中,客户端和服务器工作的核心逻辑。
我们先从右侧的服务器端开始看,因为在客户端发起连接请求之前,服务器端必须初始化好。右侧的图显示的是服务器端初始化的过程,首先初始化 socket,之后服务器端需要执行 bind 函数,将自己的服务能力绑定在一个众所周知的地址和端口上,紧接着,服务器端执行 listen 操作,将原先的 socket 转化为服务端的 socket,服务端最后阻塞在 accept 上等待客户端请求的到来。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《网络编程实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(63)

  • 业余爱好者 置顶
    unix系统有一种一统天下的简洁之美:一切皆文件,socket也是文件。

    1.像sock_addr的结构体里描述的那样,几种套接字都要有地址族和地址两个字段。这容易理解,你要与外部通信,肯定要至少告诉计算机对方的地址和使用的是哪一种地址。与远程计算机的通信还需要一个端口号。而本地socket的不同之处在于不需要端口号,那么就有了问题2;

    2.本地socket本质上是在访问本地的文件系统,所以自然不需要端口。远程socket是直接将一段字节流发送到远程计算机的一个进程,而远程计算机可能同时有多个进程在监听,所以用端口号标定要发给哪一个进程。

    作者回复: 回答的很好,给你点赞

    2019-08-07
    73
  • 早起不吃虫 置顶
    希望老师讲解的时候多讲一下为什么,譬如为什么 -- IPv4 和 IPv6 套接字地址结构的长度是固定的,而本地地址是可变的 --

    作者回复: 因为本地地址的文件路径是不同的,比如/var/a.sock, /var/lib/a.sock

    2019-08-07
    7
  • conanforever22
    1. 我觉得这样设计的目的是为了给用户提供一个统一的接口, 不用每个地址族成员都增加个函数原型; 只用通过sockaddr.sa_family来确定具体是什么类型的地址, 有点工厂模式的意思; 如果是C++的话就可以用函数重载来实现了
    2. socket主要还是为了进程间通信, 本地套接字主要用于本地IPC, 网络套接字用于跨机器通信; 如果把socket抽象成文件的话, 通信进程双方需要能够根据一个唯一的fd来找到彼此, 跨机器的话可以用端口, 本地的话直接用文件inode就可以了

    作者回复: 你的理解很到位,工厂模式我倒是没有仔细想过,有点独辟蹊径

    2019-08-07
    1
    10
  • xcoder
    老师能讲下关于WebSocket、Http和socket之间的联系吗?

    作者回复: Http是应用层协议,是基于Tcp socket的实现,websocket是http的增强,利用了Tcp双向的特性,增强了服务器端到客户端的传输能力


    以前客户端是需要不断通过轮询来从服务端得到信息,使用websocket以后就可以服务端直接推送信息到客户端

    2019-08-07
    1
    10
  • nil
    第一问,通用网络地址结构是所有具体地址结构的抽象,有了统一可以操作的地址结构,那么就可以涉及一套统一的接口,简化了接口设计。通用地址结构中第一个字段表明了地址的类型,后面的数据可以通过具体类型解析出来,一般只有将具体地址类型的指针强制转化成通用类型,这样操作才不会造成内存越界。
    第二问,本地socket基于文件操作的,因此只需要根据文件路径便可区分,不需要使用端口的概念。

    作者回复: 正解

    2019-08-07
    1
    7
  • Sweety
    打卡。感觉评论区的人都好厉害。

    作者回复: 我也觉得

    2019-08-07
    5
  • Linuxer
    2字节表示地址族很富裕,知道地址族,基本确定地址结构,通用地址结构,能够很好区分这两部分,一个字符数组就能知道每一种地址结构的起始地址,高明

    作者回复: 回答的也很高明

    2019-08-07
    4
  • (☆_☆)
    讲的太好了,越来越懂网络编程了

    作者回复: 渐渐进入状态了

    2019-08-07
    3
  • 衬衫的价格是19美元
    通用地址格式sockaddr长度只有16字节,实际存放ip地址的只有14字节,怎么存的下ip6的地址的?这里还是不太明白

    作者回复: 实际上这个通用地址格式,你可以理解为void *,我在文章里也指出了,设计套接字的时候,还没有提供void *类型的指针,所以用通用地址格式来表示。

    在IPV6地址时,实际上传入的还是28个字节的数据,通用地址只是一个"参数类型",在函数处理时,实际上可以根据AF_xxx的类型来判断,真正的地址是IPV6,那么是28个字节的数据需要被使用,而不是16个字节。

    2019-09-30
    1
    2
  • 俩孩儿他爸
    个人感觉“Pv4、IPv6、本地套接字格式以及通用地址套接字”的思想类似于OOP中的继承和多态。通用套接子为抽象类,其他套接字实现该抽象类。这样,可以定义基于通用套接字这个抽象类各种通用接口,其他套接字,也就是具体类,可以完全复用这套接口,即,实现了socket编程的多态!

    作者回复: 这个理解我给满分。

    2019-08-10
    2
    2
  • Kean
    第一个问题,各个地址的模式一致,都是标志加数据的组织形式,这种模式有三个好处:一是方便,我们可以用头两个字节知道采用的地址族,进而进行对应的解析;其次是节省空间,不用按照最大长度来使用统一的长度;最后是灵活,各个地址可以自由定义数据部分。这种模式在很多框架里都有运用,比如redis源码里面就大量的用到了这个模式。第二个问题是文件没有端口可言,因为文件路径可以唯一标识文件资源
    2019-10-12
    1
  • 神经蛙
    开头那张图,在数据传输过程中,“服务端将得到的结果以相同的方式写给客户端”,那么是否在服务端的write操作应该有个虚线箭头指向客户端的read,就像客户端的write指向服务端read一样?(因为数据传输是双向的)

    作者回复: 没有这样画的意思是read/write是没有直接的对应关系的。

    2019-08-14
    1
  • QQ怪
    这篇是讲socket最牛逼的一篇,学到了
    2019-08-12
    1
  • tdytaylor
    老师,看了专栏之后,思考后面的问题,发现根本答不上来,看了评论区的一些大牛的解答之后,感觉需要回答这些问题需要很多相关知识(如计算机操作系统),他们的答案感觉是从不同方面回答的,看着都不知道哪个说的更准确。突然觉得之前学的东西太片面了,不能把这些知识串联起,借此希望老师在讲知识点的时候,能稍微提一下,看到不懂的还能把相关知识复习一下,谢谢老师

    作者回复: 好的,我会留意。

    2019-08-09
    1
  • pyhhou
    请教老师一下,看完文章,了解了 socket 在 “客户端-浏览器” 这样一个架构中扮演的角色,但是我对 socket 的概念还不是特别理解,不太明白的是,socket 的定义到底是什么?它是和 HTTP、TCP 类似的约定俗成的协议吗?还是说是一个文件,亦或是一段程序代码,里面记录了一些当前网络通信中涉及到的协议、地址、端口号以及其他的一些必要参数?

    作者回复: socket是一个抽象概念,你写代码的时候需要和socket打交道,后面代码片段看到就会明白的。

    2019-08-09
    1
    1
  • 星亦辰
    Listen 和 accept 什么区别 总感觉是一种操作

    作者回复: 其实后面这块设计也被人不断挑战,现实就是有两个操作,其实真的可以搞成一个

    2019-08-07
    3
    1
  • zhchnchn
    请问老师,实际编程中一般使用sockaddr_in,sockaddr_in6,sockaddr_un结构,那么通用套接字地址结构sockaddr的作用是什么?一般在什么场景下使用?

    作者回复: 通用套接字就是所有函数的入口参数,用通用套接字就不需要为Tcp udp等各定义一组socket函数了,前面一位同学总结它为工厂模式,我认为挺到位的

    2019-08-07
    1
  • 萌妻的路飞
    c语言还是有点生疏,搜索一下才明白了文中的代码。所以想问下老师,需不需要去补一些c语言,补的话重点看哪些就够了

    作者回复: 基本的函数,指针就可以了

    2019-08-07
    1
  • 小崔
    第一:本地地址可变长度有限是否意味着socket路径不能太长
    第二:本地地址通信时,如果两对不同的C/S指定了同一个路径怎么办?后启动的server会报错么?
    第三:本地socket如果是作为文件形式通讯的话,是否会遇到文件权限问题?如果client没有权限访问那个路径也会报错吧

    作者回复: 实践出真知,期待你跑一下真实的程序

    第一,是的,路径是有限制的

    第二,我认为会

    第三,我认为不会

    2019-08-07
    1
  • 摘星星种星星
    1 共性是固定长度,有IP地址和端口号,m这么设计的原因是为了让网络的各个设备通信更加便利,如果没有统一规范,你的是这个格式,他的是那个格式,通信就GG了。

    2 把主机想象成一栋大楼,一个进程就是一户人家,网络通信就是和外面的人互相寄快递,本地的话就邻居之间的交流,外面的人要给你就需要你的地址(IP地址)和户号(端口号)不然快递员不知道送给那家那户。而邻居家之间的,只需要你住在那户(因为有共同地址)就行了。

    期待ing

    作者回复: 期待你下节课的总结

    2019-08-07
    1
收起评论
63
返回
顶部