- 我是一个线程(修订版)
- 我是一个 Java class
- Javascript:一个屌丝的逆袭
- Java : 一个帝国的诞生
- JSP 一个装配工的没落
- TCP/IP 之 大明王朝邮差
- TCP/IP 之大明内阁
- TCP/IP 之蓟辽督师
- CPU 阿甘
- CPU 阿甘之烦恼
- CPU 阿甘:函数调用的秘密
- 我是一个网卡
- 我是一个路由器
- 我是一个进程
- 我是一块硬盘(上)
- 我是一块硬盘(下)
- 我是一个键盘
- 张大胖的 socket
- 张大胖学递归
- 学习面向对象的令狐冲
- 张大胖学数据库
- 数据库村的旺财和小强
- 小李的数据库之旅(上)
- 小李的数据库之旅(下)
- 漫画:什么是机器学习?
- 那些烦人的同步和互斥问题
- IE 为什么把火狐和 Chrome 给打伤了?
- 对浏览器村的第二次采访
- 节约标兵 IE 的自述
- EMail 诞生记
- Email 诞生记(下)
- Http 历险记(上)
- Http 历险记(下)-- Struts 的秘密
- 动物王国的面向对象
- 冯·诺伊曼计算机的诞生
- Http Server : 一个差生的逆袭
- 张大胖的加法器
- 从 1 加到 100:一道简单的数学题挑战下你的大脑
- 编程语言
- Javascript:一个屌丝的逆袭
- 计算机语言之战
- 我和编程语言的爱恨情仇(上)
- 我和编程语言的爱恨情仇(下)
- Android 为什么选择了 Java
- iOS 为什么选择了 Object-C?
- Basic : 一个老兵的自述
- Node.js : 我只需要一个店小二
- 命令式编程 vs 声明式编程
- 编译还是解释?
- 程序人生
- “架构师"小赵
- 师兄说
- 师姐说
- 小王的架构师之路
- 小李的版本管理系统
- 小超穿越记
- 小李的 Build 之路(上)
- 小李的 Build 之路(下)
- 张大胖改 Bug
- 我的编程之路--大学趣事
- 码农小王的一天
- 小李在外企
- 张大胖的需求估算
- 从厨师到码农
- 聊一聊那些神一样的程序员们(上)
- 聊一聊那些神一样的程序员们(中)
- 聊一聊那些神一样的程序员们(下)
- 谁是互联网之父?
- 一个价值百万的创业教训
- 让自己与众不同 - 提升工作的价值
- 看看你的“易燃性”
- 从无聊的工作中寻找价值
- 什么样的学生适合报考计算机?
- 谈谈程序员的职业方向(上)
- 谈谈程序员的职业方向(中)
- 谈谈程序员的职业方向(下)
- 谈谈培训班的作用
- 码农需要知道的“潜规则”
- 学习编程的加速度
- 码农在工作中的必备能力
- 码农和英语
- 老司机经验
- 假如时光能够倒流, 我会这么学习 Java
- 假如我是计算机系老师
- 学会编程, 而不是学会 Java
- 从增删改查中突围
- 抽象:程序员必备的能力
- 懒就一个字
- 编程的自学方法
- 小王买房记
- 从一道面试题谈谈一线码农应该具备的基本素质
- 想写框架的看过来
- 苹果手机变砖头以后
- 如何快速的学习一门技术?
- 唯一不变的是变化: 谈谈微信应用号
- 什么是企业应用?
- 勿以浮沙筑高台
- 为什么敏捷开发难于成功?
- localhost vs 127.0.0.1
- GitHub/Stackoverflow 找工作时有什么用?
- 动词 or 名词 :这是一个问题
- 如何选择入行语言
- 有时候,沉默是金
- 零 Bug 的代码是怎么炼成的?
- 浮点数为什么不精确?
- 文章错误大全
- Open Source--不要为了开源而开源
- 一不留神,代码就腐化了
- 先做个“键盘侠”, 再来写程序
- 不加断点调试的程序员是好程序员
- 码农必备技能:烂代码的处理之道(上)
- 码农必备技能:烂代码的处理之道(下)
- 学习数据结构有用吗?
- 从现在开始,丰富你的简历
- 那些永不过时的书,你看过几本吗?
- 学好编程必备的一个品质你知道吗?
- 你最爱的 Java
- 搞懂了这几点,你就学会了 Web 编程
- Spring 的本质系列(1) -- 依赖注入
- Spring 本质系列(2)-AOP
- 三层架构和 MVC 那点事儿
- Java 帝国之拨云见日识回调
- 小张的 Duck Typing
- JDBC 的诞生
- JDBC 后传
- 一个不安分的 JDBC 驱动
- Java 帝国之 Java bean (上)
- Java 帝国之 Java bean(下)
- Java 帝国之函数式编程
- Java 帝国之函数式编程(下)
- 关于 Java 初学者需要知道的 10 件事
- JUnit 你不知道的那些事儿
- 圣诞礼物:Java EE 的历史
- Java EE 读书指南
- 给小白的 Java EE 指南
- 给小白的 Java EE 指南(2)
- 给小白的 Java EE 生存指南(3) : XML
- 给小白的 Java EE 生存指南(4) : 一只叫 Tom 的猫
- 给小白的 Java EE 指南(5) : AJAX
- 给小白的 Java EE 生存指南(6) :Java 反射
- 闲聊
- "饿了么"初体验
- 来自大脑的控诉
- 一个高中生是怎么玩自媒体的?
- 尝试 分答
- 到底应不应该上培训班?
- 自学编程中遇到问题怎么办?
- 据说 99%的初级程序员看完后都不迷茫了
- 一行代码引发的“血案”
- 对一个死锁问题的思考
- 通过外包进入名企
- 请开往十年前的今天
- 为什么自学中最好有个师傅指导一下?
- 这个网站值得你花时间投入
- 为什么你无法坚持自学编程?
张大胖的 socket
张大胖研究 TCP/IP 已经有段时间了。
他终于明白了所谓 IP 层就是把数据分组从一个主机跨越千山万水搬运到另外一主机, 并且这搬运服务一点都不可靠, 丢包、重复、失序可以说是家常便饭, 怪不得说是“尽力而为”, 基本上无所作为。
脏活累活只好让 TCP 来做了, 在两个主机的应用(进程)之间通过失败重传来实现可靠性的传输。
张大胖经常感慨:这建立一个 TCP 连接可是相当的复杂, 我的程序得先和远端的服务器打个招呼, 然后它再给我打个招呼确认, 我还得再给它确认下。 这还不算完, 我们的招呼中还得各自带上各自的序号, 这将来传输真正的数据时用到。
具体的传输就更麻烦了, 什么滑动窗口,什么累积确认、分组缓存、流量控制, 简直不是人做的事情。
到了断开连接的时候, 还得考虑友好分手!
可是领导竟然让张大胖用这个超级复杂的 TCP 协议来编程, 来设计一个客户端和服务器端的通信系统。
张大胖掂量了下自己, 觉得肯定搞不定, 于是赶紧向自己的好基友,编程大神 Bill 求救, Bill 在电话里说: “这很简单啊,你去看看 TCP/IP 协议的 RFC, 然后用 C 语言编程实现不就行了吗。”
张大胖心想这等于啥也没说, 继续“跪求” 。 Bill 终于说:“等着吧, 我下周给你”
Socket 周一, Bill 果然带着 7、8 张软盘来找张大胖了, 把软盘的程序分别 Copy 到了两个电脑里, 一个模拟客户端, 一个模拟服务器。 很快程序运行起来了, 两个电脑可以通过 TCP 通信了。
张大胖说: “大神, 你是怎么做到的?”
Bill 说:“TCP 协议的确很复杂, 我们不能要求每个程序员都去实现建立连接的 3 次握手, 累积确认,分组缓存, 这些应该是属于操作系统内核的部分, 没必要重复开发, 但是对于应用程序来讲, 操作系统需要抽象出一个概念, 让上层应用去编程 。 “
“什么概念?”
“socket”
”为啥叫 socket? “
"一个比喻而已, 就像插座一样, 一个插头插进插座, 建立了连接。 不过我设计这个 socket 可以理解为 (客户端 IP, 客户端 Port, 服务器端 IP, 服务器端 Port) , 对了, Port 就是端口, 通俗点讲就是一个数字而已"
“好像不用 port 就可以吧, 因为我们这是两个机器之间的通信, IP 是不是就够了?”
Bill 说:“看来你忘了, TCP 是两个进程之间的通信, 客户端上可以有很多进程同时访问多个服务器, 服务器上也有多个进程对外提供服务, 肯定要区分开啊”
张大胖不好意思的说: “原来端口号就是用来区分进程的, 这样 IP 层发过来的数据包, 到达 TCP 层以后就可以分发给各个应用程序了。 ”
“对的, 这叫多路复用。 一般来说, 服务器端都是被动访问的, 所以大家需要知道它提供服务的端口号, 要不然怎么连接? 例如 80, 443 等, 就是所谓知名端口号; 而客户端访问服务器的时候,自己的端口号可以随机生成一个, 只要不和别的应用冲突即可。”
张大胖说: “果然是复杂多了, listenfd ,从名称看就是为了要监听而创建的 socket 描述符吧, bind 是干嘛? 嗯, 我猜是为了声明说我要占用这个端口了啊, 你们都别用了, listen 函数才是真正开始监听了。
慢着,我赛, 接下来是个死循环啊, 啊对对,服务器端一直提供服务, 永不停歇。 可是这个 accept 是干嘛, 为什么使用了 listenfd , 然后返回了一个新的 connfd ???”
Bill 满意的说: “不错,思考就有进步, 可是你忘了我刚说的东西了, 服务器要区分开各个客户端, 怎么区分呢? 那只有用一个新的 socket 来表示喽, 你看后面的操作都是基于 connfd 来做的。 还有 这个 accept 相当于和客户端的 connect 一起完成了 TCP 的三次握手 ! 至于之前的 listenfd , 它只起到一个大门的作用了, 意思是说,欢迎敲门, 进门之后我将为你生成一个独一无二的 socket 描述符! ”
张大胖说:“唉, 这底层做了这么多工作啊, 看来 socket 必须得通过 (客户端 IP, 客户端 Port, 服务器端 IP, 服务器端 Port) 来确定”
“其实这个四元组还不太准确, 因为咱们说了半天,都是 TCP 协议的 socket, 因为你们领导只要你实现这一个, 你看过 UDP 没有? 就是那个无连接的运输层协议, 也有 socket, 所以更准确的定义的话,还得加上协议这一项, 变成五元组 (协议, 客户端 IP, 客户端 Port, 服务器端 IP, 服务器端 Port) ”
“大神,咱们什么时候讲讲 UDP 的 socket ? ”
"下次再说吧!"
题外话: 文中提到的 Bill 是向 Bill Joy 致敬, 这是一个天才程序员,主要工作包括 BSD Unix 操作系统, 实现 TCP/IP 协议栈, vi 编辑器,c shell , NFC, SPARC 处理器,jini 等。
当年 DARPA(美国国防部先进研究项目局)和一个叫做 BBN 的公司签署了一个合同,要把 TCP/IP 协议加入到 Berkeley Unix 当中, 当研究生 Bill Joy 看到 BBN 写的 TCP/IP 实现时, 觉得非常差劲,拒绝把它加入内核, 后来干脆卷起袖子自己实现了一个高性能的 TCP/IP 栈, 这个协议栈至今是互联网的基石。
别人问他是怎么实现这么复杂的软件的, 这位大神说: “很简单啊, 你只需要看看协议, 然后把代码写出来就行了”
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论