里面有疑问或者不正确的地方可以给我留言。
对TCP/IP、UDP、Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵。那么我想问:
- 什么是TCP/IP、UDP?
- Socket在哪里呢?
- Socket是什么呢?
- 你会使用它们吗?
TCP/IP(传输控制协议/互联网协议,Transmission Control Protocol/Internet Protocol)是用于网络通信的核心协议集,构成了互联网的基础。它定义了计算机和网络设备如何通过网络传输数据,并提供了可靠的端到端数据传输机制。
从上述这段话可以看出,TCP/IP是一个集合。什么集合?协议的集合,目的就是是实现 网络互联和数据通信,使不同设备能够通过网络可靠且有效地交换信息。它包括以下协议:
- Ethernet:局域网中使用的常见协议,定义了数据帧在有线网络上的传输方式。
- Wi-Fi (Wireless Fidelity):无线局域网协议,基于IEEE 802.11标准。
- PPP (Point-to-Point Protocol):用于在两个直接相连的节点之间传输数据,如电话线上。
- SLIP (Serial Line Internet Protocol):早期用于通过串行连接传输IP数据包的协议。
- IP (Internet Protocol):负责路由和寻址,将数据包从源主机发送到目标主机。包括:
- IPv4:最广泛使用的IP协议,使用32位地址。
- IPv6:升级版IP协议,使用128位地址,提供更多的IP地址。
- ICMP (Internet Control Message Protocol):用于发送错误报告和网络诊断信息(如ping操作)。
- ARP (Address Resolution Protocol):用于将IP地址转换为网络硬件地址(如MAC地址)。
- RARP (Reverse ARP):将硬件地址转换为IP地址(较少使用)。
- TCP (Transmission Control Protocol):提供可靠的、面向连接的数据传输协议,确保数据按顺序无错地到达。
- UDP (User Datagram Protocol):提供不可靠、无连接的数据传输协议,适用于对速度要求较高且能容忍少量数据丢失的应用,如视频流和在线游戏。
- HTTP (Hypertext Transfer Protocol):用于网页浏览,传输超文本。
- HTTPS (HTTP Secure):HTTP的加密版本,通过SSL/TLS保护数据 传输。
- FTP (File Transfer Protocol):用于在计算机之间传输文件。
- SMTP (Simple Mail Transfer Protocol):用于发送电子邮件。
- POP3 (Post Office Protocol 3):用于从邮件服务器下载电子邮件。
- IMAP (Internet Message Access Protocol):用于从服务器获取电子邮件,支持在服务器上管理邮件。
- DNS (Domain Name System):用于将域名转换为IP地址。
- Telnet:提供远程登录服务。
- SSH (Secure Shell):加密的远程登录协议,替代Telnet。
看到这里,是不是瞬间头大了,这什么东西?这么多!这么复杂!当时的人也觉得这一堆东西往这一堆,很磕碜,很不讲究,太TM影响心情了。
所以,就引出了教科书上经典的那句话,TCP/IP协议集是一个分层、多协议的通信体系。
一群聪明蛋按照协议的功能分工和网络通信过程中的逻辑顺序把协议划分为四层。这种分层设计使得网络协议更加灵活、可扩展,并能够解决不同通信问题。如下所示:
数据链路层(功能:处理硬件接口与底层网络通信,负责数据帧的发送与接收。)
- ARP (Address Resolution Protocol):用于将IP地址解析为物理网络地址(如MAC地址),适用于局域网。
- RARP (Reverse ARP):将物理地址(如MAC地址)映射为IP地址,较少使用,已被DHCP替代。
- Ethernet:局域网协议,定义了数据帧在有线网络中的传输方式。
- Wi-Fi (Wireless Fidelity):无线局域网协议,基于IEEE 802.11标准。
- PPP (Point-to-Point Protocol):用于在两点间通过串行链路传输数据。
- SLIP (Serial Line Internet Protocol):早期的串行数据传输协议,已被PPP取代。
网络层(功能:负责路由与寻址,确保数据包能够从源地址到达目的地址。)
- IP (Internet Protocol):负责路由和寻址,将数据包从源主机发送到目标主机。包括:
- IPv4:使用32位地址的IP协议,常用。
- IPv6:使用128位地址的升级版IP协议,解决了IPv4地址耗尽问题。
- ICMP (Internet Control Message Protocol):用于发送错误报告和网络诊断信息(如ping操作)。
- IGMP (Internet Group Management Protocol):用于管理多播组的成员,支持多播通信。
- NAT (Network Address Translation):允许多个设备使用一个公有IP地址,进行IP地址转换。
- OSPF (Open Shortest Path First):一种用于路由选择的内部网关协议,基于链路状态的路由。
- BGP (Border Gateway Protocol):用于不同自治系统之间的路由选择。
传输层(功能:负责提供端到端的通信服务,包括数据的分段、传输、错误检测与修复等。)
- TCP (Transmission Control Protocol):提供可靠、面向连接的数据传输,确保数据按顺序无差错地到达。
- UDP (User Datagram Protocol):提供不可靠、无连接的数据传输,适用于对速度要求高、能容忍少量数据丢失的应用(如视频流、在线游戏)。
应用层(功能:提供应用程序使用的网络服务。)
- HTTP (Hypertext Transfer Protocol):用于网页浏览,传输超文本。
- HTTPS (HTTP Secure):HTTP的加密版本,通过SSL/TLS保护数据传输。
- FTP (File Transfer Protocol):用于在计算机之间传输文件。
- SMTP (Simple Mail Transfer Protocol):用于发送电子邮件。
- POP3 (Post Office Protocol 3):用于从邮件服务器下载电子邮件。
- IMAP (Internet Message Access Protocol):用于从服务器获取电子邮件,支持在服务器上管理邮件。
- DNS (Domain Name System):用于将域名转换为IP地址。
- Telnet:提供远程登录服务,但不安全,因为数据是明文传输。
- SSH (Secure Shell):安全的远程登录协议,替代Telnet,支持加密通信。
看着是不是还是有些头大,其实主要结构如下:
举例说明分层:
- 当你使用浏览器访问一个网站时,浏览器使用应用层的HTTP协议来发送请求,这个请求会通过传输层的TCP协议分段并加上校验信息,再通过互联网层的IP协议选择路径传输到目标服务器,最后通过数据链路层的以太网协议发送数据帧到网络中。各层互不干扰,但又紧密配合完成整个通信过程。
那这些和Socket有什么关系呢?来个图就一目了然了,如下图所示:
Socket是应用层和传输层之间的接口,它将应用层的协议请求映射到传输层上的具体传输服务。Socket充当了网络通信的桥梁,既不属于应用层,也不属于传输层,而是应用程序用于访问传输层服务的一种API。
所以,Socket(套接字)是计算机网络编程中的一种通信机制,允许两个程序在不同的设备上进行数据交换。它提供了在不同主机之间通过网络传输数据的接口,是实现网络通信的重要工具。
常见的Socket类型:
(1)TCP Socket(面向连接,可靠的传输):TCP是一种面向连接的协议,确保数据包按顺序到达且不丢失。TCP Socket用于建立可靠的、持久的连接,如网页浏览器与服务器之间的通信。
(2)UDP Socket(无连接,非可靠的传输):UDP是一种无连接的协议,传输速度快,但不保证数据的可靠传输。UDP Socket常用于对实时性要求高但允许丢包的应用,如视频流、在线游戏等。
Socket 的工作原理基于“客户端-服务器”模型:
-
服务器端:
- 服务器程序在特定的IP地址和端口上“监听”(等待连接请求)。
- 当客户端请求连接时,服务器会接受连接,双方通过Socket进行数据传输。
-
客户端:
- 客户端程序向服务器发起连接请求,通过服务器的IP地址和端口号找到目标服务器。
- 连接建立后,客户端与服务器可以相互发送和接收数据。
服务端:
(1)创建套接字:
(2)绑定IP地址和端口:
(3)监听连接请求:
(4)接受客户端连接:
(5)发送和接收数据:
(6)关闭连接:
客户端:
(1)创建套接字:
(2)连接到服务器:
(3)发送和接收数据:
(4)关闭连接:
1.创建套接字:
在C++中, 函数用于创建套接字(socket),它是网络编程的基础。通过创建套接字,应用程序可以在网络上进行通信。
函数的语法
参数说明
(协议族/地址族): 指定使用的通信域,决定了套接字通信的地址格式。
常见的选项有:
- :IPv4协议的地址族。
- :IPv6协议的地址族。
- :本地通信(也称为域套接字,主要用于同一台计算机上的进程通信)。
(套接字类型): 指定通信类型,决定了套接字的特性。
常见的选项有:
- :提供面向连接的可靠数据传输(TCP协议)。
- :提供无连接的数据报传输(UDP协议)。
- :提供对底层协议的直接访问,通常用于高级网络编程和自定义协议。
(协议): 通常指定为 ,表示使用默认协议。如果有多个协议可供选择,可以明确指定协议编号。例如:
- :TCP协议。
- :UDP协议。
返回值
- 成功:返回一个文件描述符,表示新创建的套接字。
- 失败:返回 ,并设置 以指示错误原因。
示例代码:
运行指令:
在ubantu系统中(windows系统无法运行),先切换到代码文件所在路径,例如:文件名为socked.cpp,文件路径为/home/socket_learn/socked.cpp
然后运行 这条指令使用 GNU C++ 编译器()来编译 源代码文件,并生成一个名为 的可执行文件。
最后运行
代码运行结果:
说明
:首先创建一个 IPv4 (AF_INET)、面向连接的 TCP (SOCK_STREAM) 套接字。
:关闭套接字,释放资源。
错误处理
- 如果 返回 ,则表示套接字创建失败,可以通过 获取错误码,使用 打印错误信息。
- 常见错误:
- :权限问题,无法创建套接字。
- :系统中打开的文件(套接字)已达到上限。
- :进程中打开的文件(套接字)已达到上限。
总结
- 是 C++ 网络编程的基础,用于创建套接字。
- 套接字可用于 TCP 和 UDP 等协议,创建后需要结合 、、、 等函数来实现通信。
2.绑定IP地址和端口:
在网络编程中, 函数用于将创建的套接字绑定到一个特定的IP地址和端口号。它通常用于服务器端程序,允许服务器在特定的地址和端口上监听客户端的连接请求。
函数的语法
参数说明
- :由 函数返回的套接字文件描述符。
- :指向 结构体的指针,包含IP地址和端口号信息。
- : 结构体的大小,通常使用 。
结构体
在绑定 IPv4 地址时, 结构体通常用于表示IP地址和端口号。该结构体定义在 中,格式如下:
- :地址族,通常设置为 (表示 IPv4)。
- :端口号,必须使用 函数将端口号从主机字节序转换为网络字节序。
- :IP地址,使用 函数将字符串形式的IP地址转换为 类型,或者使用 表示绑定到本地所有可用的网络接口。
返回值
- 成功:返回 。
- 失败:返回 ,并设置 以指示错误原因。
常见错误
- :指定的IP地址或端口已经被占用。
- :套接字已经绑定过一次,不能重复绑定。
- :提供的文件描述符无效。
示例代码
以下示例演示如何在服务器端创建一个套接字,并将其绑定到本地IP地址和端口号 。
运行结果:
代码说明
:创建了一个 IPv4、TCP 套接字。
结构体:用于存储服务器的IP地址和端口信息。 表示服务器可以监听来自所有本地网络接口的连接。
:将套接字与指定的IP地址和端口绑定。如果绑定成功,套接字就可以在指定的端口上接收客户端的连接请求。
:将端口号从主机字节序转换为网络字节序,这是必要的步骤,因为不同的系统可能使用不同的字节序。
:关闭套接字,释放资源。
如何处理多网络接口
如果服务器主机有多个网络接口(多个IP地址),可以使用不同的IP地址进行绑定:
- 绑定到特定IP地址:将 设置为特定的IP地址(如 )。
- 绑定到所有接口:使用 ,这意味着套接字将绑定到主机的所有可用网络接口,可以接受来自任意接口的连接。例如:以太网接口(Ethernet):物理网络接口,通过网线连接到局域网。Wi-Fi 接口:无线网络接口,通过 Wi-Fi 连接到网络。环回接口(Loopback):通常是 ,用于本地程序之间的通信(即不经过网络,只在本机内部进行通信)。
绑定后的后续操作
通常,服务器端程序在成功绑定套接字后,会执行以下步骤:
- 监听连接请求:使用 函数开始监听来自客户端的连接请求。
- 接受连接:使用 函数接受客户端的连接,并生成一个新的套接字用于与客户端通信。
小结
- 函数将套接字绑定到一个IP地址和端口号,用于服务器端程序监听来自客户端的连接。
- 结构体用于指定绑定的IP地址和端口号。
- 绑定后,服务器可以使用 和 函数与客户端进行通信。
3.监听连接请求:
在网络编程中,服务器端需要监听客户端的连接请求,以便处理它们。 函数就是用来让服务器开始监听连接请求的。
函数的作用:
函数的作用是将套接字设为被动模式,从而告诉操作系统这个套接字将用于接受连接。这个函数的主要功能是:
- 让服务器开始监听来自客户端的连接请求。
- 设置连接队列的最大长度,即客户端连接请求的等待队列。
的函数原型(以 C/C++ 为例):
- :由 函数返回的套接字描述符,这个套接字已经通过 函数绑定到一个本地 IP 地址和端口号。
- :指定在处理客户端连接之前,内核允许的最大等待连接数。它表示在服务器开始处理请求前,客户端连接可以在队列中等待的数量上限。
3.2.使用 的步骤
(1)创建套接字:通过 函数创建套接字。
(2)绑定 IP 地址和端口:通过 函数将套接字绑定到一个本地 IP 地址和端口号。
(3)开始监听:调用 函数,开始监听客户端的连接请求。
代码示例(C/C++):
3.4.参数说明:
- :服务器套接字描述符,通过 函数创建。
- ():最大连接等待队列长度。当多个客户端几乎同时尝试连接服务器时,服务器会把这些请求放在一个队列中,这个参数决定队列的大小。超过这个数量的连接请求将被拒绝,返回错误。
3.5.监听的实际含义
(1)被动模式: 函数将套接字转变为被动模式,被动模式意味着这个套接字将用于接受传入的连接,而不会主动向其他服务器发出连接请求。服务器将处于等待状态,直到有客户端请求连接。
(2)连接队列:当有多个客户端请求连接时,操作系统会把这些请求放在一个队列中。 参数决定队列中最多可以有多少个未处理的连接请求。在队列满时,如果有新的连接请求,它们将被拒绝,客户端可能会收到错误信息。
3.6.队列的作用
- 服务器处理每个客户端连接的速度可能不同,而客户端请求连接的速度可能较快。 队列允许服务器有缓冲时间来处理请求。
- 如果服务器忙于处理现有的连接,其他客户端的连接请求可以暂时存放在队列中等待处理。如果队列已满,额外的连接请求将被拒绝。
4.接受客户端连接:
是服务器端网络编程中的一个关键函数,用于接受来自客户端的连接请求。服务器在调用 开始监听客户端的连接后,当有客户端尝试连接时, 函数负责接受该连接并为此生成一个新的套接字以进行数据传输。
函数的作用
- 函数从服务器的等待队列中取出一个连接请求并与客户端建立连接。
- 它为该连接分配一个新的套接字,该套接字将用于与客户端之间的实际通信。
- 原来的监听套接字继续监听其他连接请求。
的函数原型(以 C/C++ 为例):
- :服务器的监听套接字文件描述符(由 和 创建并监听)。
- :指向一个 结构体的指针,用于存储客户端的地址信息(客户端的 IP 和端口)。
- : 结构体的大小,传入时是该结构体的大小,返回时表示客户端地址的实际大小。
返回值
- 成功时, 返回一个新的套接字文件描述符,这个描述符用于与客户端进行后续的通信。
- 如果出错,返回值为 ,同时设置 以表示错误类型。
使用场景
通常和 、、 函数一起使用。以下是服务器接受客户端连接的典型步骤:
创建套接字:使用 创建服务器端的套接字。
绑定 IP 和端口:使用 将套接字绑定到特定的 IP 地址和端口。
监听连接请求:使用 函数监听客户端连接请求。
接受连接:使用 接受客户端连接并生成一个新的套接字进行通信。
代码示例(C/C++):
4.2.参数解释:
- :由 函数创建的服务器监听套接字。
- :这是一个 结构体,存储客户端的 IP 地址和端口号。
- :表示 结构体的大小。
的流程:
(1)阻塞行为: 是一个阻塞函数,意味着它会一直等待,直到有客户端连接请求到达。如果没有连接请求,服务器会在此函数上阻塞。
(2)返回客户端套接字:一旦连接请求到达, 从连接队列中取出请求,返回一个新的套接字,用于与客户端进行通信。
(3)服务器继续监听:原来的监听套接字 () 仍然处于监听状态,可以接受其他客户端连接请求,而当前客户端的通信使用新的套接字 () 进行。
4.4.常见用法:
- 服务器通过 获取与客户端通信的专用套接字。后续的数据接收和发送可以使用 和 或 和 。
- 通信结束后,服务器需要调用 关闭新的套接字以释放资源。
4.5.总结
- 用于从连接队列中取出客户端的连接请求,建立连接。
- 返回一个新的套接字,用于服务器与客户端的通信。
- 原监听套接字继续等待其他连接请求。
通过 ,服务器能够与多个客户端进行通信,每个客户端都有自己独立的套接字,而服务器的监听套接字则持续接收新的连接请求。
5.发送和接收数据:
在网络编程中,服务器和客户端建立连接后,可以通过 和 函数来发送和接收数据。这两个函数分别用于通过套接字向远程端发送数据和从远程端接收数据。
函数
函数用于通过套接字发送数据到连接的另一端。
的函数原型:
- :套接字描述符,用于标识连接。
- :指向存储待发送数据的缓冲区的指针。
- :要发送的数据长度(字节数)。
- :发送选项,通常设置为 0。可以设置不同的标志来控制发送行为,例如 (非阻塞发送)。
返回值:
- 返回实际发送的字节数。如果返回值小于 ,表示数据未完全发送。
- 如果返回 ,表示发送失败,并设置 。
函数
函数用于通过套接字从连接的另一端接收数据。
的函数原型:
- :套接字描述符,标识连接。
- :指向接收数据的缓冲区的指针。
- :缓冲区的大小(即最多接收多少字节)。
- :接收选项,通常设置为 0。可以设置不同的标志来控制接收行为,例如 (等待所有数据)。
返回值:
- 返回实际接收到的字节数。如果返回 0,表示连接已关闭。
- 如果返回 ,表示接收失败,并设置 。
5.3.发送和接收数据的流程
- 服务器和客户端建立连接。
- 服务器使用 函数接收来自客户端的数据。
- 客户端使用 函数向服务器发送数据,或反之。
- 在发送或接收完数据后,双方可以通过 关闭套接字。
5.4.代码示例
以下是使用 和 进行数据发送和接收的代码示例:
服务端代码:
关键点:
- 阻塞行为: 和 默认是阻塞的,意味着如果网络缓慢或没有数据到达,程序会等待。可以通过设置非阻塞模式改变这种行为。
- 返回值检查:检查 和 的返回值很重要,以确保数据正确发送和接收,并处理错误情况。
- 数据传输的长度: 可能不会一次发送所有数据,程序需要处理这种情况,确保所有数据都被发送。
- 连接关闭:如果 返回 0,表示对方关闭了连接。
总结:
- 用于通过套接字发送数据。
- 用于接收来自远程端的数据。
- 它们是实现服务器与客户端通信的基础工具,通常与 、、 等函数配合使用。
6.关闭连接:
在网络编程中, 函数用于关闭套接字并释放与该套接字相关的资源。当服务器或客户端不再需要与对方通信时,调用 可以终止连接。
函数的作用
函数不仅仅是关闭文件描述符(在这种情况下是套接字),还会终止与该套接字关联的 TCP 连接,释放所有资源。如果套接字是连接的一部分(如 TCP 连接),则会通知对端连接已关闭,后续通信不再可能。
函数的原型:
- :套接字描述符,标识要关闭的连接。
返回值:
- 返回 表示成功。
- 返回 表示失败,并设置 ,以提供错误的具体信息。
6.2.关闭连接的流程
- 当服务器或客户端调用 函数时,系统会开始执行 TCP 的四次挥手(Four-Way Handshake)协议,以优雅地关闭连接。
- 在这个过程中,系统会将套接字的状态从 ESTABLISHED(已建立连接)变为 FIN_WAIT 等不同状态,直到连接完全关闭。
- 调用 后,系统会释放与该套接字关联的所有内存资源,包括文件描述符、缓冲区等。
1.创建套接字:
2.连接到服务器:
3.发送和接收数据:
4.关闭连接:
Socket广泛应用于各种网络通信场景,如HTTP、FTP、电子邮件等协议的底层实现。
服务端:
客户端:
运行指令: