C语言——网络编程(上)

目录

 

1、Internet

1.1、OSI模型

1.2、OSI模型图

1.3、TCP/IP协议族 

1.4、TCP/IP协议族模型

1.5、 TCP/IP协议与OSI的对应

2、TCP与UDP 

2.1、TCP

2.2、UDP

2.3、TCP与UDP对比

2.4、 小结

3、网络通信

3.1、TCP API接口(Berkeley Sockets)

3.2、服务器

3.3、客户端

3.4、释义


 

1、Internet

互联网(Internet)是指一种全球性、开放的、基于分组 packet 交换的计算机网络,通过互联网,可以实现全球范围内的数据交换和通信

1.1、OSI模型

OSI模型(开放系统互联模型)是一个七层抽象模型,用于描述网络通信的各个层次及其相互作用。 每一层都有其特定的功能,并通过与相邻层进行交互来实现网络通信。从下到上,七层分别是:

  1. 物理层 (Physical Layer): 定义了网络设备之间物理连接的特性,例如电缆类型、电压、数据传输速率等。 关注的是比特的传输。

  2. 数据链路层 (Data Link Layer): 负责在相邻节点之间可靠地传输数据帧。 包括寻址、错误检测和纠正等功能,常用的协议有以太网。

  3. 网络层 (Network Layer): 负责在网络之间路由数据包,确定数据包的路径。 IP协议是该层的核心协议。

  4. 传输层 (Transport Layer): 提供端到端的可靠数据传输,负责数据的分割、重组、流量控制和错误检测。 TCP和UDP协议是该层的代表性协议。

  5. 会话层 (Session Layer): 负责建立、管理和终止两个应用程序之间的会话。 它提供了一种机制来同步和协调通信。

  6. 表示层 (Presentation Layer): 负责数据的格式转换和编码,确保不同系统之间的数据能够相互理解。 例如,字符编码转换。

  7. 应用层 (Application Layer): 直接为用户提供网络服务,例如HTTP、FTP、SMTP等协议都属于这一层。 用户使用的各种网络应用都运行在这一层。

每一层都封装了来自上层的数据,并将其传递给下层,最终到达物理层进行传输。 接收端则按照相反的顺序进行解封装,直到数据到达应用层。 这种分层结构使得网络的设计、维护和升级更加方便。

1.2、OSI模型图

94a0d73e9a1b4b58bbf122d9d29046b2.png

1.3、TCP/IP协议族 

TCP/IP协议族是一组网络协议,用于在互联网上进行数据传输。它并非单个协议,而是一组相互协作的协议的集合。 最主要的两个协议是TCP(传输控制协议)和IP(互联网协议)。

  • IP协议 (Internet Protocol): 负责数据的寻址和路由。它将数据包从源地址传递到目标地址,类似于邮递员负责将信件投递到正确的地址。IP协议是无连接的,不保证数据的可靠传输,可能会出现数据丢失或顺序错乱的情况。 IPv4和IPv6是IP协议的两个主要版本,IPv6是IPv4的升级,解决了IPv4地址空间不足的问题。

  • TCP协议 (Transmission Control Protocol): 负责数据的可靠传输。它在IP协议的基础上,提供面向连接、可靠、有序的数据传输服务。TCP协议会进行数据校验、流量控制、拥塞控制等,确保数据完整、有序地到达目的地。 你可以把它想象成快递服务,确保包裹安全送达,并提供追踪信息。

除了TCP和IP,TCP/IP协议族还包含许多其他协议,例如:UDP(用户数据报协议)、ICMP(互联网控制报文协议)、ARP(地址解析协议)、DHCP(动态主机配置协议)等等,这些协议协同工作,才能实现互联网的正常运作。 它们分别负责不同的功能,共同构成了互联网的通信基础。

1.4、TCP/IP协议族模型

620d3df25e7b46b69426e12d0a5e96c2.png

1.5、 TCP/IP协议与OSI的对应

09b1810a9cb8438b9f626b6255b656ac.png

2、TCP与UDP 

TCP(Transmission Control Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协议)都是网络传输层协议,但它们在可靠性、效率和应用场景方面存在显著差异。

2.1、TCP

  • 特点: 面向连接、可靠、有序、流控。 在数据传输前需要建立连接,确保数据完整性和顺序到达。它通过序号、确认、重传等机制来保证可靠性,并使用滑动窗口机制进行流量控制,避免网络拥塞。
  • 可靠性: TCP提供端到端可靠的数据传输,保证数据不丢失、不重复、按序到达。
  • 效率: 由于需要建立连接和进行各种校验,TCP的效率相对较低。
  • 应用场景: 对可靠性要求高的应用,例如:Web浏览(HTTP)、电子邮件(SMTP)、文件传输(FTP)、远程登录(SSH)等。

2.2、UDP

  • 特点: 面向无连接、不可靠、无序、无流控。 数据传输无需建立连接,直接发送数据包。它不保证数据的完整性和顺序到达,也不进行流量控制。
  • 可靠性: UDP不提供可靠性保证,数据可能丢失、重复或乱序到达。
  • 效率: 由于无需建立连接和进行各种校验,UDP的效率很高。
  • 应用场景: 对实时性要求高、对可靠性要求低的应用,例如:在线游戏、视频直播、语音聊天、DNS查询等

2.3、TCP与UDP对比

3dbd3381090f4dd5b1e32c2e87df42f2.png

2.4、 小结

选择TCP还是UDP取决于应用的需求。如果需要保证数据的可靠性,则选择TCP;如果需要保证数据的实时性,即使牺牲一些可靠性也在所不惜,则选择UDP。 很多应用也可能同时使用TCP和UDP,例如一些网络游戏可能使用UDP传输游戏数据,使用TCP传输聊天信息。

3、网络通信

结合前面学习的C语言——套接字以及C语言——文件IO,咱们就可以用TCP或者UDP网络协议开始进行网络编程了~

3.1、TCP API接口(Berkeley Sockets

Berkeley Sockets (BSD sockets): 这是最常用的TCP API接口,被大多数Unix-like系统(如Linux、macOS、BSD)采用。 其核心函数包括:

  • socket(): 创建一个套接字,指定协议族(AF_INET表示IPv4,AF_INET6表示IPv6)、套接字类型(SOCK_STREAM表示TCP,SOCK_DGRAM表示UDP)和协议(通常为0,由系统选择合适的协议)。
  • bind(): 将套接字绑定到一个特定的本地IP地址和端口号。
  • listen(): 对于服务器端,监听来自客户端的连接请求,指定最大等待连接数。
  • accept(): 对于服务器端,接受一个客户端的连接请求,返回一个新的套接字用于与该客户端通信。
  • connect(): 对于客户端,连接到服务器指定的IP地址和端口号。
  • send() / recv(): 发送和接收数据。
  • close(): 关闭套接字。
  • getsockopt() / setsockopt(): 获取和设置套接字选项,例如超时时间、缓冲区大小等。

3.2、服务器

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8080

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);
    char buffer[256];

    // 创建服务器套接字
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("socket");
        exit(1);
    }

    // 设置服务器套接字地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);

    // 绑定服务器套接字
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind");
        exit(1);
    }

    // 监听客户端连接
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(1);
    }

    printf("Server started. Listening on port %d...", PORT);

    while (1) {
        // 接收客户端连接
        client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);
        if (client_fd < 0) {
            perror("accept");
            continue;
        }

        printf("Client connected. Address: %s:%d", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        // 处理客户端数据
        while (1) {
            int n = read(client_fd, buffer, 256);
            if (n < 0) {
                perror("read");
                break;
            } else if (n == 0) {
                printf("Client disconnected.");
                break;
            }

            printf("Received: %s", buffer);
            write(client_fd, "Hello, client!", 13);
        }

        close(client_fd);
    }

    close(server_fd);
    return 0;
}

3.3、客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8080

int main() {
    int client_fd;
    struct sockaddr_in server_addr;
    char buffer[256];

    // 创建客户端套接字
    client_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (client_fd < 0) {
        perror("socket");
        exit(1);
    }

    // 设置服务器套接字地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);

    // 连接服务器
    if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect");
        exit(1);
    }

    printf("Connected to server.");

    // 发送数据
    while (1) {
        printf("Enter message: ");
        fgets(buffer, 256, stdin);
        write(client_fd, buffer, strlen(buffer));

        // 接收服务器响应
        read(client_fd, buffer, 256);
        printf("Received: %s", buffer);
    }

    close(client_fd);
    return 0;
}

3.4、释义

服务器端将监听端口8080,客户端将连接到服务器端,并发送数据。服务器端将接收客户端数据,处理数据,并将响应发送回客户端。 

在write与read函数中输入自己想要传输的数据,就可以实现通信拉~

比如用来实现,服务器与客户端的聊天~

自己copy去尝试吧

有问题随时评论

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨染新瑞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值