C++网络编程:基础知识的探讨(引言)

发表时间: 2023-12-15 21:40

从今天开始将开始写一些关于C++网络编程的文章,主要是涉及到TCP编程。将由浅入深给大家介绍C++网络编程的过程,由于本人只在Linux环境下编程,所以后面讲的技术点和示例程序都是基于Linux系统。

在正式开始讲TCP编程之前先预习一些基础知识,方便后面大家理解,也由于大家对网络编程熟悉程度不一,这里也可能会啰嗦些。

C++主要应用在后端系统,后端系统基本上都离不开网络编程;但是目前大多数系统已经封装好了网络通信部分的接口,绝大多数开发人员都接触不到网络编程;而且大多数系统框架都已经搭好,开发人员也只是填充业务代码罢了。但是呢,开发人员也需要熟悉网络编程知识,为可能维护网络通信部分代码准备,为系统可能出现的网络问题做准备,也为自己有机会参与网络编程、框架设计做准备。

下面开始介绍网络编程的一些术语和基础知识点,这里主要讲跟我们要开发的应用相关的、需要我们特别注意的点:

一、TCP(Transmission Control Protocol)

它是互联网协议家族中的一个关键协议,它工作在 OSI 模型的传输层,负责为两台计算机之间的应用程序提供可靠的、端到端的数据传输服务。TCP 是一种面向连接、流式传输的协议,这意味着在数据传输开始之前,必须先建立一条连接,而在数据传输结束之后,这条连接会被正常关闭。

面向连接:在数据传输之前,TCP 会通过三次握手过程建立连接。只有在连接建立成功后,数据才能开始传输。

可靠性:TCP 使用序列号和确认应答来确保数据包的正确传输。如果数据包丢失或者损坏,TCP 会重新发送该数据包,直到数据包被正确接收。

数据顺序保证:TCP 给每个数据包分配一个唯一的序列号,接收方按照序列号的顺序重组数据,确保数据的正确顺序。

全双工通信:TCP 支持同时进行双向数据传输,即发送方和接收方都可以同时发送和接收数据。

二、套接字(socket)

它是网络编程中一种用于进行数据交换的软件机制,为应用程序提供了一个接口,使其能够利用网络协议栈进行通信。换言之,套接字是一个用来建立和管理网络连接的工具,它位于应用层和传输层之间,向上提供给应用进程访问,向下与网络协议栈交互。

套接字通常与 IP 地址和端口号一起使用,以标识网络中的唯一实体。它们可以根据需要使用不同的传输协议,如 TCP(Transmission Control Protocol,传输控制协议)或 UDP(User Datagram Protocol,用户数据报协议)。TCP 提供可靠的数据传输,而 UDP 则提供无连接的数据报服务。

在创建套接字时,通常需要指定以下三个参数:

  1. 目标 IP 地址 - 指定要连接的远程主机的 IP 地址。
  2. 使用的传输层协议 - 通常是 TCP 或 UDP。
  3. 使用的端口号 - 确定目标服务或应用程序,因为每个运行的服务都在特定的端口上监听。

三、阻塞(Blocking)和非阻塞(Non-blocking)

阻塞和非阻塞指的是网络 I/O 操作的行为模式。

在阻塞模式下,网络 I/O 操作会一直等待,直到操作完成或者出现错误。也就是说,当一个进程调用了某个阻塞 I/O 函数,比如 accept(),如果套接字是阻塞的,那么这个进程会暂停执行,直到有连接请求准备好为止。在此期间,进程无法做其他事情。

非阻塞模式下的网络 I/O 操作不会导致进程暂停。例如程序在非阻塞的套接字上accept,函数会立即返回,程序根据返回值判断accept的结果是否可用;如果此时没有客户端请求建立连接,程序就可以做其它的事情,而不需要等待。

非阻塞模式通常需要配合循环或者其他形式的轮询机制,以便在条件合适的时候再次尝试执行 I/O 操作。

四、IO多路复用(I/O Multiplexing)

是一种同步I/O模型,允许一个进程或线程同时监听多个文件描述符(通常是网络套接字),等待它们中的任何一个变为可读或可写状态。当某个文件描述符准备好进行I/O操作时,操作系统会通知进程,然后进程可以进行相应的读写操作。

在Linux系统中,常用的IO多路复用实现包括select、poll和epoll。这些函数可以让进程阻塞在一个调用上,直到有文件描述符变得可读或可写。当这样的事件发生时,进程会被唤醒,然后它可以检查哪些文件描述符准备好了,以及如何相应地处理它们。

五、TCP 的半连接队列(SYN Queue 或 Half-Open Queue)与全连接队列(Accept Queue 或 Established Queue)

半连接队列用于存储那些已经收到了客户端 SYN 报文但还未完成三次握手过程的连接请求。

全连接队列用于存储已经完成三次握手过程,即已经建立了完整连接,但还没有被应用程序通过 accept() 调用来获取的连接。

暂时先介绍这几点术语,大家感兴趣可以自己网上搜索其它知识点。在后续的文章中,有需要展开讲解的再在文章里体现。


#文章首发挑战赛#