Fork me on GitHub

如何理解socket?

照片

Socket是系统提供的、为了使用TCP/IP协议栈而设置的网络编程调用接口(API).


Socket是什么?

概述

要写网络程序就必须用Socket,这是程序员都知道的。

socket是一个对tcp\ip这个网络通讯协议栈的全面封装与实现。

一般来说,很多人都会说Socket编程基本就是listen,accept以及send,write等几个基本的操作。是的,就跟常见的文件操作一样,只要写过就一定知道。对于网络编程,我们也言必称TCP/IP,似乎其它网络协议已经不存在了。

深入理解

一个疑问

我们知道,一个指定的端口号不能被多个程序共用。比如:如果IIS占用了80端口,那么Apache就不能也用80端口了很多防火墙只允许特定目标端口的数据包通过服务程序在listen某个端口并accept某个连接请求后,会生成一个新的socket来对该请求进行处理。

于是,一个困惑了我很久的问题就产生了。如果一个socket创建后并与80端口绑定后,是否就意味着该socket占用了80端口呢?

如果是这样的,那么当其accept一个请求后,生成的新的socket到底使用的是什么端口呢(我一直以为系统会默认给其分配一个空闲的端口号)?如果是一个空闲的端口,那一定不是80端口了,于是以后的TCP数据包的目标端口就不是80了–防火墙一定会组织其通过的!实际上,我们可以看到,防火墙并没有阻止这样的连接,而且这是最常见的连接请求和处理方式。

我的不解就是,为什么防火墙没有阻止这样的连接?它是如何判定那条连接是因为connet80端口而生成的?是不是TCP数据包里有什么特别的标志?或者防火墙记住了什么东西?

解决疑问

后来,我又仔细研读了TCP/IP的协议栈的原理,对很多概念有了更深刻的认识。

比如,在TCP和UDP同属于传输层,共同架设在IP层(网络层)之上。而IP层主要负责的是在节点之间(End to End)的数据包传送,这里的节点是一台网络设备,比如计算机。

因为IP层只负责把数据送到节点(计算机),而不能区分上面的不同应用,所以TCP和UDP协议在其基础上加入了端口的信息,端口于是标识的是一个节点上的一个应用。

除了增加端口信息,UPD协议基本就没有对IP层的数据进行任何的处理了。而TCP协议还加入了更加复杂的传输控制,比如滑动的数据发送窗口(Slice Window),以及接收确认和重发机制,以达到数据的可靠传送。

不管应用层看到的是怎样一个稳定的TCP数据流,下面传送的都是一个个的IP数据包,需要由TCP协议来进行数据重组。所以,我有理由怀疑,防火墙并没有足够的信息判断TCP数据包的更多信息,除了IP地址和端口号。

而且,我们也看到,所谓的端口,是为了区分不同的应用的,以在不同的IP包来到的时候能够正确转发。TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口。

就像操作系统会提供标准的编程接口,比如Win32编程接口一样,TCP/IP也必须对外提供编程接口,这就是Socket编程接口–原来是这么回事啊!


为什么要用Socket?

这个问题就要讨论一下socket与TCP/IP协议的关系了。

理论与实践

协议只是一个概念,是一种规范和约定俗成的东西,我想要操作和应用这些协议,那它必须要有一个实现,socket就是这个实现。

通过使用socket的一系列api,比如说connect,write,read 它能够依照tcp/ip的规范实现网络通讯。即socket是成对出现的,客户端一个socket,服务端一个socket,通过对它的一系列操作来实现tcp/ip的规范的功能。

即socket连接也就是tcp连接的实现。我们在平时开发的过程中,关于网络通讯,其实本质封装的就是socket。因为tcp/ip是协议,协议是概念,具体实现的还是socket。

抽象实现

socket跟TCP/IP并没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以,socket的出现只是可以更方便的使用TCP/IP协议栈而已,其对TCP/IP进行了抽象,形成了几个最基本的函数接口。比如create,listen,accept,connect,read和write等等。

socket只是对TCP/IP协议栈操作的抽象,而不是简单的映射关系。

实现细节

现在我们明白,如果一个程序创建了一个socket,并让其监听80端口,其实是向TCP/IP协议栈声明了其对80端口的占有。

以后,所有目标是80端口的TCP数据包都会转发给该程序(这里的程序,因为使用的是Socket编程接口,所以首先由Socket层来处理)。

所谓accept函数,其实抽象的是TCP的连接建立过程:accept函数返回的新socket其实指代的是本次创建的连接,而一个连接是包括两部分信息的,一个是源IP和源端口,另一个是宿IP和宿端口。所以,accept可以产生多个不同的socket,而这些socket里包含的宿IP和宿端口是不变的,变化的只是源IP和源端口。

这样的话,这些socket宿端口就可以都是80,而Socket层还是能根据源/宿对来准确地分辨出IP包和socket的归属关系,从而完成对TCP/IP协议的操作封装!


总结

  • SOCKET:套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
  • 应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
  • Socket是对TCP/IP协议的封装,Socket本身只是一个调用接口(API),方便程序员用Socket使用TCP/IP协议栈而已.

本文转载自知乎,原文链接:谈谈你对socket的理解

-------------Page's overThanks for reading-------------

如果文章内容对你有帮助,就赏博主一根棒棒糖吧~