【Linux】网络通信

【Linux】网络通信

文章目录

  • 【Linux】网络通信
    • 1、网络基础
      • 1.1 计算机网络
      • 1.2 网络模型
        • TCP & UDP
          • 1)IP地址
          • 2)端口
          • 3)TCP协议与UDP协议的比较
      • 1.3 网络传输
        • 1.3.1 传输逻辑
        • 1.3.2 传输条件
        • 1.3.3 传输流程
      • 1.4 地址管理
    • 2、网络编程
      • 2.1 基本概念
        • 2.1.1 IP地址
          • 与协议关系
        • 2.1.2 端口号
        • 2.1.3 网络字节序
      • 2.2 基于TCP的socket通信
        • 2.2.1 认识socket
        • 2.2.2 通信模型
        • 2.2.3 服务端编写
        • 2.2.4 客户端编写
      • 2.3 基于UDP
        • 2.3.1 服务端实现
        • 2.3.2 客户端实现

1、网络基础

1.1 计算机网络

计算机网络的发展可以从独立模式逐步演进为网络互连模式,这个过程可以分为以下几个阶段:

  1. 独立模式
    在计算机网络的早期阶段,每台计算机都是相对独立的实体,没有连接到其他计算机。每台计算机仅用于单独的任务,数据和资源的共享非常有限。这个阶段中,计算机主要用于科学计算和数据处理。

  2. 点对点连接
    随着计算机数量的增加,人们开始意识到将计算机连接起来可以实现更高效的资源共享和通信。于是,点对点连接的网络模式出现了,其中两台计算机通过专用的通信线路直接连接,可以进行数据传输。这种模式在早期局域网中比较常见。

  3. 局域网(LAN)的兴起
    随着计算机数量的进一步增加,局域网(LAN)开始兴起。局域网允许位于同一地理位置的计算机互相连接,实现资源共享和通信。以太网技术的发展使得计算机可以通过共享的物理媒介(如同一根电缆)进行通信,从而使局域网得以实现。

  4. 广域网(WAN)的出现
    随着计算机网络的发展,人们希望能够跨越较大的地理范围进行通信。广域网(WAN)应运而生,通过连接多个局域网和点对点连接,实现了更大范围内的计算机互连。这种网络模式通过使用路由器和交换机来实现数据在不同网络之间的传输。

  5. 互联网的崛起
    互联网是计算机网络发展的最高阶段。它将全球范围内的计算机网络互相连接,实现了无缝的数据交换和资源共享。互联网使用 TCP/IP 协议套件作为通信基础,允许不同类型的网络和设备互相通信,从而形成了全球性的信息交流平台。

1.2 网络模型

计算机网络模型是一种抽象框架,用于描述计算机网络中各个组件之间的关系和通信方式。常见的计算机网络模型有以下几种:

  1. OSI模型(开放系统互联模型)
    OSI模型是一个由国际标准化组织(ISO)制定的七层网络模型,每一层都代表着特定的网络功能。从下到上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。这个模型的主要目标是促进不同厂商开发的设备能够相互通信。然而,实际上,大多数网络采用的是下面提到的TCP/IP模型。

  2. TCP/IP模型
    TCP/IP模型是实际上在互联网上使用的模型,它由四个层次组成:网络接口层、网络层、传输层和应用层。虽然层数较少,但它包含了与OSI模型中相似的功能。这个模型的名称来自于它的两个核心协议:传输控制协议(TCP)和Internet协议(IP)。

  3. 四层网络模型
    有一些网络模型将网络分为四个层次:物理层、数据链路层、网络层和应用层。这个模型省略了会话层、表示层和传输层,更简化了网络的结构。

  4. 五层网络模型
    这个模型将网络分为五个层次:物理层、数据链路层、网络层、传输层和应用层。它在功能上与TCP/IP模型相似,但只包含五个层次。

image-20230810113050172

TCP/IP是一组协议的代名词,它还包括许多协议,组成了TCP/IP协议簇。 TCP/IP协议簇分为四层,IP位于协议簇的第二层(对应OSI的第三层),TCP位于协议簇的第三层 (对应OSI的第四层)。TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供 的网络来完成自己的需求。这4层分别为:

  • 应用层:应用程序间沟通的层,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、 网络远程访问协议(Telnet)等。
  • 传输层:在此层中,它提供了节点间的数据传送服务,如传输控制协议(TCP)、 用户数据报协议(UDP)等,TCP和UDP给数据包加入传输数据并把它传输到下一层中, 这一层负责传送数据,并且确定数据已被送达并接收。
  • 网络互连层:负责提供基本的数据封包传送功能,让每一块数据包都能够到达目 的主机(但不检查是否被正确接收),如网际协议(IP)。
  • 主机到网络层:对实际的网络媒体的管理,定义如何使用实际网络 (如Ethernet、Serial Line等)来传送数据。

TCP & UDP

1)IP地址

img

2)端口

1. 用于区分不同的应用程序

2. 端口号的范围为0-65535,其中0-1023未系统的保留端口,我们的程序尽可能别使用这些端口!

3. IP地址和端口号组成了我们的Socket,Socket是网络运行程序间双向通信链路的终结点, 是TCP和UDP的基础!

4. 常用协议使用的端口:HTTP:80,FTP:21,TELNET:23

img

3)TCP协议与UDP协议的比较

TCP协议流程详解:

首先TCP/IP是一个协议簇,里面包括很多协议的。UDP只是其中的一个。之所以命名为TCP/IP协议, 因为TCP,IP协议是两个很重要的协议,就用他两命名了。

下面我们来讲解TCP协议和UDP协议的区别:

TCP(Transmission Control Protocol,传输控制协议)是面向连接的协议,即在收发数据钱 ,都需要与对面建立可靠的链接,这也是面试经常会问到的TCP的三次握手以及TCP的四次挥手三次握手: 建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立, 在Socket编程中,这一过程由客户端执行connect来触发,具体流程图如下:

img

  • 第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server, Client进入SYN_SENT状态,等待Server确认。
  • 第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位 SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求 ,Server进入SYN_RCVD状态。
  • 第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK 置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则 连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以 开始传输数据了。
  • 四次挥手: 终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。 在Socket编程中,这一过程由客户端或服务端任一方执行close来触发,具体流程图如下:

img

  • 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入 FIN_WAIT_1状态
  • 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同, 一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
  • 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK 状态。
  • 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。 另外也可能是同时发起主动关闭的情况:

img

另外还可能有一个常见的问题就是:为什么建立连接是三次握手,而关闭连接却是四次挥手呢? 答:因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里 发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还 能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些 数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。


UDP协议详解

UDP(User Datagram Protocol)用户数据报协议,非连接的协议,传输数据之前源端和终端不 建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。 在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽 的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。 相比TCP就是无需建立链接,结构简单,无法保证正确性,容易丢包

1.3 网络传输

网络传输和网络模型之间存在密切的联系,网络模型为网络传输提供了一种结构化的框架和指导原则,帮助理解和组织网络中的数据传输过程。

TCP/IP协议簇是一组协议,它包括物理层、数据链路层、网络层、传输层和应用层五个层次。每一层都有特定的功能和任务:

  1. 物理层:负责传输光/电信号,包括以太网、光纤、无线网络等。集线器工作在此层。

  2. 数据链路层:传送和识别数据帧,处理帧同步、冲突检测、数据差错校验。交换机工作在此层。

  3. 网络层:进行地址管理和路由选择,通过IP地址标识主机,并规划数据传输路径。路由器工作在此层。

  4. 传输层:负责主机间数据传输,如TCP协议确保数据可靠传输。

  5. 应用层:处理应用程序间的通信,如电子邮件传输(SMTP)、文件传输(FTP)、远程访问(Telnet)等。

这五层结构协同工作,构成了TCP/IP协议簇,支撑了现代计算机网络的各项通信和数据传输功能。

对于一台主机, 它的操作系统内核实现了从传输层到物理层的内容

对于一台路由器, 它实现了从网络层到物理层

对于一台交换机, 它实现了从数据链路层到物理层

对于集线器, 它只实现了物理层

1.3.1 传输逻辑

数据传输的逻辑可以归纳如下:

  1. 准备阶段

    • 在应用层,准备要传输的数据,定义数据格式和处理逻辑。
    • 选择适当的应用层协议,如HTTP、FTP等,以确定数据的传输方式和规则。
  2. 传输层协议选择

    • 根据应用需求选择传输层协议,如可靠性要求高则选择TCP,实时性要求高则选择UDP。
  3. 建立连接和监听

    • 对于TCP,建立连接是必要的。发送端和接收端之间建立连接,以确保数据的可靠传输。
    • 对于UDP,连接不是必需的,但需要确定数据发送和接收的目标地址。
  4. 数据封装和加头部信息

    • 在发送端,将应用层数据封装为数据包,并添加适当的传输层和网络层头部信息。
    • 头部信息包括IP地址、端口号等,用于路由和目标设备的标识。
  5. 数据传输

    • 传输层协议负责将封装后的数据包传输到目标设备,同时执行错误检测、流量控制等操作。
    • 网络层协议根据目标IP地址选择适当的路由,确定数据包的传输路径。
  6. 物理传输

    • 链路层将数据包封装为帧,添加链路层头部和尾部,通过物理介质传输到接收端。
  7. 数据解封和处理

    • 在接收端,链路层接收帧并解析,将数据交给网络层。
    • 网络层根据IP地址确定目标设备,将数据交给传输层。
  8. 数据重组和解析

    • 传输层协议负责将接收到的数据包按序重组,执行错误检测和纠正,将数据交给应用层。
  9. 应用层处理

    • 应用程序解析数据包,根据定义的数据格式处理数据内容,执行相应的业务逻辑。

这个逻辑流程涵盖了数据传输从应用层到物理层的各个阶段和过程,确保数据能够按照一定的规则和流程进行传输和处理。

1.3.2 传输条件

将数据传输的必备条件按照应用层、传输层、网络层和链路层进行分类如下:

应用层

  1. 通信设备:需要至少两台通信设备。
  2. IP地址和端口号:每台设备需要唯一的IP地址和适当的端口号。
  3. 数据格式定义:需要定义数据的格式,以便发送方和接收方正确解析和处理数据。
  4. 安全性考虑:需要考虑数据的安全性和加密,特别是对于敏感信息的传输。

传输层

  1. 协议选择:需要选择适当的传输层协议,如TCP或UDP,根据数据传输需求进行选择。
  2. 传输机制:需要了解如何建立连接、传输数据、管理流量和关闭连接等操作。
  3. 错误处理机制:需要考虑数据传输中可能发生的错误情况,如丢包、重传等。

网络层

  1. 网络连接:通信设备需要通过网络连接在一起,可以是有线或无线连接。
  2. IP地址:每台设备需要唯一的IP地址,用于在网络中标识设备。
  3. 路由选择:需要使用路由协议选择数据包的传输路径。

链路层

  1. 物理连接:通信设备需要通过物理层面的连接,如以太网、无线电波等。
  2. 链路地址:链路层需要确定每个设备的物理地址,如MAC地址。

1.3.3 传输流程

日常生活中发送电子邮件时,TCP/IP协议传输的具体流程如下表所示:

步骤层次动作与报头
1应用层编写邮件,准备邮件内容。
2应用层使用电子邮件客户端。
3应用层封装邮件数据。
4传输层选择TCP协议。
5传输层建立TCP连接。
6传输层封装邮件数据为TCP数据包。
7网络层选择IP地址。
8网络层封装TCP数据包为IP数据包。
9链路层分帧和添加链路层头部。
10链路层通过物理介质传输数据。
11链路层解析数据帧,移除链路层头部。
12网络层解析IP数据包,获取目标IP。
13传输层TCP重组和校验数据包。
14传输层将数据包传递给应用层。
15应用层解析邮件数据,处理邮件内容。
16应用层继续处理邮件,可能转发。

1.4 地址管理

网络地址是为了在计算机网络中标识不同设备和主机而存在的。不同层次的网络模型在数据传输过程中都需要使用网络地址来确定数据的发送和接收方。

  • 物理层:物理层负责信号传输,但为了确保信号到达正确的设备,每个设备都需要在网络中有唯一的物理地址,即MAC地址。这是一个在数据链路层中使用的地址,用于在局域网中识别设备。

  • 数据链路层:在数据链路层,数据帧需要带有目标MAC地址和源MAC地址,以便设备可以正确地发送和接收数据。这些地址用于在局域网内识别设备。

  • 网络层:在网络层,IP地址被用来标识不同的主机和路由器。IP地址用于在全球范围内寻找目标设备,使数据能够跨越不同网络进行传输。

  • 传输层:在传输层,数据包含源端口号和目标端口号。这些端口号一起构成了一个套接字,用于标识不同的应用程序和服务。它们帮助传输层将数据传递给正确的应用程序。

总之,地址在不同的网络层中扮演着关键的角色,用于标识不同的设备、主机和服务。它们帮助确保数据在网络中正确传输,并使通信能够顺利进行。

2、网络编程

2.1 基本概念

2.1.1 IP地址

IP地址(Internet Protocol Address)是用于在计算机网络中唯一标识和定位设备的数字标签。它是Internet协议族的一部分,用于在网络中进行数据包的路由和传递。IP地址充当了类似于邮寄地址的作用,以确保数据能够准确地从发送者传递到接收者。

以下是IP地址的基本概念:

  1. 唯一标识性: 每个设备(如计算机、服务器、路由器、移动设备等)在网络中都被分配了一个唯一的IP地址。这有助于确保数据包能够正确地路由和传递。

  2. 分层结构: IP地址通常被分为两个主要版本:IPv4(Internet Protocol version 4)和IPv6(Internet Protocol version 6)。IPv4使用32位二进制数表示,通常以点分十进制表示法(例如,192.168.1.1)呈现。IPv6使用128位二进制数表示,以一种更复杂的方式显示(例如,2001:0db8:85a3:0000:0000:8a2e:0370:7334)。

  3. IPv4地址枯竭: 由于互联网的迅速扩展,IPv4地址空间已经基本上耗尽。这导致了IPv6的引入,因为它提供了更大的地址空间,能够支持未来更多的互联设备。

  4. 公共和私有地址: IP地址可以是公共的或私有的。公共IP地址是全球范围内唯一的,用于直接访问互联网。私有IP地址在局域网(例如家庭或企业内部网络)中使用,不直接暴露给互联网。

  5. 子网掩码: 子网掩码是与IP地址结合使用的参数,用于指示哪些部分是网络部分,哪些部分是主机部分。它有助于将IP地址划分为网络和主机,以便在子网内进行更有效的路由。

  6. DHCP和静态IP: IP地址可以通过动态主机配置协议(DHCP)自动分配,也可以手动配置为静态IP地址。DHCP允许网络设备在加入网络时自动获取IP地址和其他网络配置信息。

  7. 网络层地址: IP地址位于网络层(第三层)协议中,负责将数据包从源主机传输到目标主机。它与MAC地址(在数据链路层,第二层)一起协作,以实现数据在不同网络之间的传递。

IP地址是互联网通信的基础,通过它,数据能够在全球范围内进行准确和可靠的传递。不论是浏览网页、发送电子邮件还是进行视频通话,IP地址在背后都发挥着至关重要的作用。

与协议关系

IP地址是互联网协议族中的一个关键概念,它与其他多个协议相互配合,以实现数据在网络中的传输和通信。以下是IP地址与其他一些重要协议之间的关系:

  1. TCP/IP协议栈: TCP/IP是一组网络协议,它们一起构成了互联网的基础。IP地址是TCP/IP协议栈中的核心组成部分。TCP(Transmission Control Protocol)负责在通信双方建立可靠的连接和数据传输,而IP则负责将数据包从源主机路由到目标主机。

  2. MAC地址: MAC地址(Media Access Control Address)是数据链路层(第二层)的一个标识符,用于在局域网中唯一标识网络设备。IP地址(位于网络层,第三层)与MAC地址相互配合,通过ARP(Address Resolution Protocol)等机制,将IP地址映射到对应的MAC地址,以实现数据在局域网内的传输。

  3. ARP协议: ARP(Address Resolution Protocol)用于将IP地址解析为对应的MAC地址。当设备需要发送数据到另一个设备时,需要知道目标设备的MAC地址。ARP协议帮助主机在同一局域网中查找IP地址对应的MAC地址。

  4. DHCP协议: DHCP(Dynamic Host Configuration Protocol)用于自动分配IP地址和其他网络配置信息给新加入网络的设备。DHCP服务器分配可用的IP地址给客户端,使设备能够快速连接网络而不需要手动配置IP地址。

  5. DNS协议: DNS(Domain Name System)将易于记忆的域名转换为IP地址。在互联网上,人们更容易记住域名(如www.example.com),而不是复杂的IP地址。DNS协议允许将域名解析为相应的IP地址,使得用户能够访问网站和资源。

  6. ICMP协议: ICMP(Internet Control Message Protocol)用于在IP网络中传递错误消息和控制消息。例如,当数据包在传输过程中发生问题时,ICMP可以生成错误消息并通知源主机。

这些协议相互合作,共同构成了互联网通信的基础架构。IP地址在这些协议之间扮演着桥梁的角色,使得数据能够在不同层级的网络中传输和交换。

2.1.2 端口号

在计算机网络中,端口号是用于标识特定应用程序或服务的数字标识符。它是在传输层协议中使用的概念,例如在TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)中。通过将IP地址与端口号结合使用,网络中的不同应用程序可以在同一设备上同时运行,实现数据的多路复用和分发。

以下是端口号的一些关键含义:

  1. 标识应用程序: 端口号用于标识在一个设备上运行的不同应用程序或服务。每个应用程序可以监听一个或多个特定的端口号,以便与其他设备通信。

  2. 多路复用: 通过使用端口号,多个应用程序可以在同一设备上同时运行,而无需相互干扰。传输层协议可以根据目标端口号将数据包传递给正确的应用程序。

  3. 数据传输: 端口号与IP地址一起构成了网络套接字(socket),从而允许应用程序通过网络进行数据传输。发送端使用源端口号,接收端使用目标端口号,以确定数据应该交付给哪个应用程序。

  4. 服务识别: 一些标准端口号已经被分配给特定的服务或协议。例如,HTTP通常使用端口号80,HTTPS使用端口号443,SMTP(邮件传输)使用端口号25等。这样,网络设备和应用程序可以识别常见的服务并将数据传递给正确的端口。

  5. 安全性: 端口号也与网络安全有关。防火墙和网络安全设备可以基于端口号来控制数据流量,允许或阻止特定的应用程序或服务通信。

  6. 动态分配: 除了一些常见的标准端口号外,应用程序也可以使用动态分配的端口号。这些端口号在通信过程中临时分配给应用程序,以便在通信结束后可以被释放并重新使用。

端口号是网络通信中的一个重要概念,它使得不同的应用程序能够在同一设备上通过网络进行通信,并确保数据能够准确传递到目标应用程序。

2.1.3 网络字节序

网络字节序(Network Byte Order)是在讨论在计算机网络中跨不同计算机体系结构(如大端序和小端序)传输数据时的字节顺序问题。不同的计算机体系结构在内存中以不同的方式存储多字节数据(如整数、浮点数等)的字节顺序,这可能导致在网络通信中数据的混淆和解释错误。

网络通信涉及多台计算机或设备之间的数据交换。如果不同的设备使用不同的字节序,那么在发送数据时可能会导致以下问题:

  1. 数据解释错误: 接收方可能会错误地解释数据,因为字节的顺序与发送方不同。这会导致数据在接收方的应用程序中被错误地解释和处理。

  2. 数据截断: 如果数据在发送和接收时以不同的字节序传输,可能会导致数据的部分截断或丢失。这会损坏数据的完整性。

为了解决这些问题,网络通信需要使用一种一致的字节序,以确保数据可以在不同设备之间正确传递和解释。这种一致的字节序被称为网络字节序,通常采用大端字节序。

网络字节序的讨论涉及如何在数据传输过程中,确保发送和接收双方都能正确地解释数据。为了实现这一点,需要使用字节序转换函数(如htonl()htons()ntohl()ntohs())来在不同字节序之间进行转换。这样可以确保数据在网络中的传输和解释是一致的,无论使用的是大端序还是小端序。

2.2 基于TCP的socket通信

2.2.1 认识socket

img

Socket(套接字)是一种用于在计算机网络中进行通信的编程接口(API)。它提供了一种机制,使得不同计算机之间可以通过网络进行数据传输,实现进程间的通信。

背景和问题: 在早期的计算机网络中,需要一种方法来在不同设备之间进行通信。最初的网络通信是通过低层的网络协议进行的,但这对于应用程序来说过于繁琐。开发人员需要一种更高层次的抽象来处理通信细节,从而实现应用程序之间的数据交换。

解决问题和方法: Socket接口的出现解决了上述问题。它提供了一种标准的API,使得应用程序可以方便地创建、连接、发送和接收数据。通过Socket,应用程序不需要关心底层的网络细节,而只需要使用Socket函数来实现通信。

作用: Socket在网络通信中起到了关键作用,它使得应用程序能够轻松地在不同设备之间进行数据交换。通过Socket,开发人员可以构建各种网络应用,如网络游戏、聊天应用、文件传输工具、网络服务器等。

发展过程和变化: Socket的发展经历了不同的阶段。起初,它是基于传统的Unix文件I/O,后来随着计算机网络的发展,Socket逐渐被标准化,出现了不同的Socket类型(如流套接字、数据报套接字等)和Socket函数(如socket()、bind()、connect()、send()、recv()等)。随着网络技术的进步,Socket在不同操作系统和编程语言中得到了广泛支持。

此外,随着互联网的迅速发展,Socket的应用范围变得更加广泛,从传统的网络通信延伸到了Web开发、实时音视频传输、云计算等领域。同时,各种高级通信协议也在Socket基础上构建,如HTTP、FTP、SMTP等。

总之,Socket是网络编程中的核心概念,它在计算机网络通信中扮演了极其重要的角色,提供了一种通用的接口,使得应用程序可以方便地进行跨网络通信,不需要处理底层细节。从最初的Unix文件I/O发展到现代的网络通信,Socket一直在不断演进,适应不断变化的网络需求。

2.2.2 通信模型

img

Socket通信实现步骤解析

Step 1:创建ServerSocket和Socket

Step 2:打开连接到的Socket的输入/输出流

Step 3:按照协议对Socket进行读/写操作

Step 4:关闭输入输出流,以及Socket

接下来写一个简单的例子,开启服务端后,客户端点击按钮然后链接服务端, 并向服务端发送一串字符串,表示通过Socket链接上服务器

2.2.3 服务端编写

服务端要做的事有这些

Step 1:创建ServerSocket对象,绑定监听的端口

Step 2:调用accept()方法监听客户端的请求

Step 3:连接建立后,通过输入流读取客户端发送的请求信息

Step 4:通过输出流向客户端发送响应信息

Step 5:关闭相关资源

代码实现:

#include <iostream>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {int serverSocket, clientSocket;struct sockaddr_in serverAddr;struct sockaddr_in clientAddr;socklen_t clientAddrLen = sizeof(clientAddr);// 1. 创建服务器端 SocketserverSocket = socket(AF_INET, SOCK_STREAM, 0);// 配置服务器地址memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = INADDR_ANY; // 任意地址serverAddr.sin_port = htons(12345); // 端口号转换为网络字节序// 2. 绑定端口和地址bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));// 3. 监听连接请求listen(serverSocket, 5); // 允许最大排队连接数为5std::cout << "~~~ 服务端已就绪,等待客户端接入 ~~~" << std::endl;// 4. 等待客户端连接clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);char clientIp[INET_ADDRSTRLEN];inet_ntop(AF_INET, &(clientAddr.sin_addr), clientIp, INET_ADDRSTRLEN);std::cout << "客户端接入,客户端 IP 地址:" << clientIp << std::endl;// 5. 读取客户端信息char buffer[1024];memset(buffer, 0, sizeof(buffer));while (recv(clientSocket, buffer, sizeof(buffer), 0) > 0) {std::cout << "客户端发送过来的信息:" << buffer << std::endl;memset(buffer, 0, sizeof(buffer));}// 6. 关闭连接close(clientSocket);close(serverSocket);return 0;
}

2.2.4 客户端编写

客户端要做的事有这些

Step 1:创建Socket对象,指明需要链接的服务器的地址和端号

Step 2:链接建立后,通过输出流向服务器发送请求信息

Step 3:通过输出流获取服务器响应的信息

Step 4:关闭相关资源

代码实现:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {// 创建客户端 Socketint clientSocket = socket(AF_INET, SOCK_STREAM, 0);if (clientSocket == -1) {std::cerr << "Error creating socket!" << std::endl;return 1;}// 配置服务器地址和端口struct sockaddr_in serverAddr;memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(12345); // 端口号转换为网络字节序if (inet_pton(AF_INET, "172.16.2.54", &serverAddr.sin_addr) <= 0) {std::cerr << "Invalid address or address family!" << std::endl;return 1;}// 连接到服务器if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {std::cerr << "Error connecting to server!" << std::endl;close(clientSocket);return 1;}// 获取客户端 IP 地址char clientIp[INET_ADDRSTRLEN];if (inet_ntop(AF_INET, &serverAddr.sin_addr, clientIp, INET_ADDRSTRLEN) == nullptr) {std::cerr << "Error converting IP address!" << std::endl;close(clientSocket);return 1;}// 发送消息到服务器const char* message = "客户端:";send(clientSocket, message, strlen(message), 0);send(clientSocket, clientIp, strlen(clientIp), 0);send(clientSocket, " 接入服务器!", strlen(" 接入服务器!"), 0);// 关闭连接close(clientSocket);return 0;
}

2.3 基于UDP

2.3.1 服务端实现

服务端实现步骤:

Step 1:创建DatagramSocket,指定端口号
Step 2:创建DatagramPacket
Step 3:接收客户端发送的数据信息
Step 4:读取数据

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <unistd.h>int main() {/** 接收客户端发送的数据*/// 1. 创建服务器端套接字int serverSocket = socket(AF_INET, SOCK_DGRAM, 0);if (serverSocket == -1) {std::cerr << "Error creating socket!" << std::endl;return 1;}// 2. 配置服务器地址struct sockaddr_in serverAddr;memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = INADDR_ANY; // 使用本地所有可用地址serverAddr.sin_port = htons(12345); // 端口号转换为网络字节序// 3. 绑定端口和地址if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {std::cerr << "Error binding socket!" << std::endl;close(serverSocket);return 1;}// 4. 接收客户端发送的数据struct sockaddr_in clientAddr;socklen_t clientAddrLen = sizeof(clientAddr);char data[1024];memset(data, 0, sizeof(data));std::cout << "**** 服务器端已经启动,等待客户端发送数据 ****" << std::endl;ssize_t bytesRead = recvfrom(serverSocket, data, sizeof(data), 0, (struct sockaddr*)&clientAddr, &clientAddrLen);if (bytesRead == -1) {std::cerr << "Error receiving data!" << std::endl;close(serverSocket);return 1;}data[bytesRead] = '\0'; // 添加字符串结尾标志std::cout << "我是服务器,客户端说:" << data << std::endl;/** 向客户端响应数据*/// 1. 获取客户端的地址和端口struct sockaddr_in responseAddr = clientAddr;socklen_t responseAddrLen = sizeof(responseAddr);// 2. 定义响应的数据const char* responseMsg = "欢迎您!";// 3. 响应客户端ssize_t bytesSent = sendto(serverSocket, responseMsg, strlen(responseMsg), 0, (struct sockaddr*)&responseAddr, responseAddrLen);if (bytesSent == -1) {std::cerr << "Error sending response!" << std::endl;}// 4. 关闭套接字close(serverSocket);return 0;
}

2.3.2 客户端实现

客户端实现步骤:

Step 1:定义发送信息
Step 2:创建DatagramPacket,包含将要发送的信息
Step 3:创建DatagramSocket
Step 4:发送数据

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <unistd.h>int main() {/** 向服务器端发送数据*/// 1. 定义服务器地址和端口号struct sockaddr_in serverAddr;memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8800); // 端口号转换为网络字节序if (inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr) <= 0) {std::cerr << "Invalid address or address family!" << std::endl;return 1;}// 2. 定义要发送的数据const char* data = "用户名:admin;密码:123";// 3. 创建 UDP 套接字int clientSocket = socket(AF_INET, SOCK_DGRAM, 0);if (clientSocket == -1) {std::cerr << "Error creating socket!" << std::endl;return 1;}// 4. 发送数据报到服务器ssize_t bytesSent = sendto(clientSocket, data, strlen(data), 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr));if (bytesSent == -1) {std::cerr << "Error sending data!" << std::endl;close(clientSocket);return 1;}/** 接收服务器端响应的数据*/// 1. 创建用于接收数据的缓冲区char reply[1024];memset(reply, 0, sizeof(reply));// 2. 接收服务器响应的数据struct sockaddr_in responseAddr;socklen_t responseAddrLen = sizeof(responseAddr);ssize_t bytesRead = recvfrom(clientSocket, reply, sizeof(reply), 0, (struct sockaddr*)&responseAddr, &responseAddrLen);if (bytesRead == -1) {std::cerr << "Error receiving data!" << std::endl;} else {std::cout << "我是客户端,服务器说:" << reply << std::endl;}// 3. 关闭套接字close(clientSocket);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/86411.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【面试八股文】每日一题:谈谈你对集合的理解

每日一题-Java核心-谈谈你对集合的理解【面试八股文】 谈谈你对集合的理解 Java集合是Java编程语言中用于存储数据的容器。它提供了一系列的类和接口&#xff0c;用于操作和管理数据集合。Java集合框架主要包括以下几个重要的接口和类&#xff1a; List&#xff1a;List是一个有…

ubuntu 如何命令行打开系统设置(Wifi,网络,应用程序...)

关于GNOME GNOME 是一个自由、开放源代码的桌面环境&#xff0c;它运行在 Linux 和其他类 UNIX 操作系统上。它是 GNU 项目的一部分&#xff0c;旨在为 Linux 操作系统提供一个现代化、易于使用的用户界面。 GNOME 桌面环境包括许多应用程序&#xff0c;例如文件管理器、文本编…

Centos7源码安装redis

1、下载redis Index of /releases/ 2、解压redis tar -xvf redis-6.2.9.tar.gz 3、进入解压后的目录 cd redis-6.2.9/4、指定内存分配器为 libc make MALLOClibc 5、进入src目录&#xff0c;安装 cd src && make install6、运行 ./redis-server 7、添加开机…

BI技巧丨利用Index计算半累计

在实际的业务场景中&#xff0c;特别是财务模块和库存管理模块&#xff0c;经常需要我们针对每个月的期初期末进行相关指标计算&#xff0c;这也是我们之前曾经提到的Calculate基础应用——半累计计算。 现在我们也可以通过微软新推出的Index开窗函数来解决这一问题。 INDEX函…

Linux 终端操作命令(3)内部命令用法

Linux 终端操作命令 内部命令用法 A- alias NAME alias - Define or display aliases. SYNOPSIS alias [-p] [name[value] ... ] DESCRIPTION Define or display aliases. Without arguments, alias prints the list of aliases in the reusable form al…

Seata - 入门笔记

1、事务 访问并可能更新数据库中数据库中各种数据线的一个程序执行单元 原子性&#xff1a;事务是一个不可分割的工作单位&#xff0c;一个事务要么都做要么都不做 一致性&#xff1a;必须是使数据库从一个一致性到另一个一致性的状态&#xff0c;中间状态不能被观察到 隔离…

JDBC快速入门操作

一、jdbc简介 JDBC是java用于连接数据库的api&#xff0c;数据库软件有多种&#xff0c;像MySQL,SQLsever&#xff0c;Oracle等数据库&#xff0c;这些数据库都是由不同的团队开发的&#xff0c;所以相同的功能的api的名字不同&#xff0c;当一个后端工程需要切换一个数据库软件…

tomcat的多实例,动静分离(web服务基础结束)

多实例 多实例就是在一台服务器上有多个tomcat的服务&#xff08;核心是改端口&#xff09; 实验&#xff1a;多实例 安装步骤 1.安装好 jdk 2.安装 tomcat cd /opt tar zxvf apache-tomcat-9.0.16.tar.gz mkdir /usr/local/tomcat mv apache-tomcat-9.0.16 /usr/local/tomca…

ChatGPT将会成为强者的外挂?—— 提高学习能力

目录 前言 一、提高学习力 &#x1f9d1;‍&#x1f4bb; 1. 快速找到需要的知识 2. 组合自己的知识体系 3. 内化知识技能 二、提问能力❗ 三、思维、创新能力 &#x1f31f; 1. 批判性思维 1.1 八大基本结构进行批判性提问 1.2 苏格拉底的提问分类方法 2. 结构化思…

【Java可执行命令】(十八)可视化监控和管理工具 jconsole:获取 JVM的内存使用情况、线程活动、GC 行为等重要指标的可视化工具 ~

Java可执行命令之jconsole 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法格式3.2 注意事项 4️⃣ 应用场景&#x1f33e; 总结 1️⃣ 概念 jconsole 是 Java Development Kit (JDK) 自带的一款图形化监控和管理工具。它旨在提供一个简单而强大的界面&#xff0c;用于监视和管…

一百五十一、Kettle——Linux上安装的kettle8.2开启carte服务以及配置子服务器

一、目的 kettle8.2在Linux上安装好可以启动界面、并且可以连接MySQL、Hive、ClickHouse等数据库后&#xff0c;准备在Linux上启动kettle的carte服务 二、实施步骤 &#xff08;一&#xff09;carte服务文件路径 kettle的Linux运行的carte服务文件是carte.sh &#xff08;二…

大语言模型之一 Attention is all you need ---Transformer

大语言模型已经在很多领域大显身手&#xff0c;其应用包括只能写作、音乐创作、知识问答、聊天、客服、广告文案、论文、新闻、小说创作、润色、会议/文章摘要等等领域。在商业上模型即产品、服务即产品、插件即产品&#xff0c;任何形态的用户可触及的都可以是产品&#xff0c…

AWS——04篇(AWS之Amazon S3(云中可扩展存储)-02——EC2访问S3存储桶)

AWS——04篇&#xff08;AWS之Amazon S3&#xff08;云中可扩展存储&#xff09;-02——EC2访问S3存储桶&#xff09; 1. 前言2. 创建EC2实例 S3存储桶3. 创建IAM角色4. 修改EC2的IAM 角色5. 连接EC2查看效果5.1 连接EC25.2 简单测试5.2.1 查看桶内存储情况5.2.2 复制本地文件…

PHP利用PCRE回溯次数限制绕过某些安全限制实战案例

目录 一、正则表达式概述 有限状态自动机 匹配输入的过程分别是&#xff1a; DFA&#xff08;确定性有限状态自动机&#xff09; NFA&#xff08;非确定性有限状态自动机&#xff09; 二、回溯的过程 三、 PHP 的 pcre.backtrack_limit 限制利用 例题一 回溯绕过步骤 &…

Springboot整合Druid

导入依赖 <!-- druid连接--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency> #配置数据源 spring:datasource:driver…

JavaScript中的交互的方式alert,prompt,confirm的用法

一.alert的用法 1.alert 它会显示一条信息,弹出的这个带有信息的小窗口被称为模态窗。“modal” 意味着用户不能与页面的其他部分&#xff08;例如点击其他按钮等&#xff09;进行交互&#xff0c;直到他们处理完窗口。在上面示例这种情况下 —— 直到用户点击“确定”按钮。 …

信息安全:防火墙技术原理与应用.

信息安全&#xff1a;防火墙技术原理与应用. 防火墙是网络安全区域边界保护的重要技术。为了应对网络威胁&#xff0c;联网的机构或公司将自己的网络与公共的不可信任的网络进行隔离&#xff0c;其方法是根据网络的安全信任程度和需要保护的对象&#xff0c;人为地划分若干安全…

本地项目如何连接git远程仓库

在本地新建项目后&#xff0c;如何连接git远程仓库呢&#xff1f;步骤如下&#xff1a; 第一步&#xff0c; 首先我们在git上新建仓库&#xff0c;设置模板可勾选Readme文件。&#xff08;readme文件的创建是为了介绍所写代码的一些详细信息,为了之后更好的维护。&#xff09;…

安卓改透明屏有哪些方法和步骤?壁纸、主题、软件

安卓改透明屏是指将安卓手机的屏幕背景变为透明&#xff0c;使得手机的背景图像或者壁纸能够透过屏幕显示出来。 这样的改变可以让手机的界面更加个性化&#xff0c;也能够增加手机的美观度。 要实现安卓手机的透明屏&#xff0c;可以通过以下几种方法&#xff1a; 1. 使用透…

[保研/考研机试] KY80 进制转换 北京大学复试上机题 C++实现

题目链接&#xff1a; KY80 进制转换https://www.nowcoder.com/share/jump/437195121691735660774 描述 写出一个程序&#xff0c;接受一个十六进制的数值字符串&#xff0c;输出该数值的十进制字符串(注意可能存在的一个测试用例里的多组数据)。 输入描述&#xff1a; 输…