网络编程 · 代码笔记1

前言

1、编程环境

  编码所用IDE:VScode 1.87.0
  编译工具:gcc version 11.4.0

在这里插入图片描述

  运行环境:
    1、Windows Subsystem for Linux (WSL) 2
    2、Ubuntu 22.04.4 LTS

在这里插入图片描述

2、编译命令

  如无特别说明,通用编译命令为:

gcc -o server -g -Wall -std=gnu99 filename.c
或
gcc -o client -g -Wall -std=gnu99 filename.c

3、标题名前缀解释

  XXX1或XXX2中,XXX代表一个主题,凡是具有相同的XXX,都是同一主题。
  1代表服务端内容(代码),2代表客户端内容(代码)。

4、注意事项

  所有代码都需要先运行服务端,而后再运行客户端,或者先运行接收端,再运行发送端。


0011客户端读取服务端字符_服务端

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <string.h>     // 引入字符串操作库
#include <stdlib.h>     // 引入标准库
#include <unistd.h>     // 引入unistd库,主要用到close函数
#include <arpa/inet.h>  // 引入arpa/inet.h库,主要用到socket地址操作函数
#include <sys/socket.h> // 引入sys/socket.h库,主要用到socket函数
#include <netinet/in.h> // 引入netinet/in.h库,主要用到socket地址结构体

int main(int argc, char const *argv[])
{
    int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // 创建TCP套接字

    struct sockaddr_in serv_addr;             // 定义服务器socket地址结构体
    memset(&serv_addr, 0, sizeof(serv_addr)); // 初始化服务器socket地址结构体为0

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器IP地址为本地回环地址
    serv_addr.sin_port = htons(1234);                   // 设置服务器端口号为1234

    bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); // 绑定socket地址到套接字

    listen(serv_sock, 10); // 监听套接字,最大连接数为10

    struct sockaddr_in clnt_addr;                 // 定义客户端socket地址结构体
    socklen_t clnt_addr_size = sizeof(clnt_addr); // 定义客户端socket地址结构体大小

    int clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_addr_size); // 接受客户端连接

    char str[] = "这是服务的的信息。\n"; // 定义发送给客户端的信息
    write(clnt_sock, str, sizeof(str));  // 向客户端发送信息

    close(clnt_sock); // 关闭客户端套接字
    close(serv_sock); // 关闭服务器套接字

    return 0; // 程序正常退出
}

0012客户端读取服务端字符_客户端

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <string.h>     // 引入字符串操作库
#include <unistd.h>     // 引入Unix标准函数库
#include <stdlib.h>     // 引入标准库定义
#include <arpa/inet.h>  // 引入IP地址转换库
#include <sys/socket.h> // 引入套接字库

int main(int argc, char const *argv[])
{
    int sock = socket(AF_INET, SOCK_STREAM, 0); // 创建一个IPv4的TCP套接字

    struct sockaddr_in serv_addr;        // 定义一个IPv4的套接字地址结构
    memset(&serv_addr, 0, sizeof(sock)); // 将套接字地址结构清零,避免脏数据

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器的IP地址为本地回环地址
    serv_addr.sin_port = htons(1234);                   // 设置服务器的端口号为1234,并转换为网络字节序

    connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); // 连接到服务器

    char buffer[128];                       // 定义一个缓冲区用于接收数据
    read(sock, buffer, sizeof(buffer) - 1); // 从套接字读取数据到缓冲区,留一个字节用于字符串结束符

    printf("客户端读取到的信息为:%s\n", buffer); // 打印从服务器接收到的信息

    close(sock); // 关闭套接字

    return 0; // 程序结束
}

  运行结果:

在这里插入图片描述

0021回声测试_服务端

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <string.h>     // 引入字符串操作库
#include <stdlib.h>     // 引入标准库,提供多种函数
#include <unistd.h>     // 引入Unix标准函数库
#include <arpa/inet.h>  // 引入IP地址转换函数库
#include <sys/socket.h> // 引入套接字API
#include <netinet/in.h> // 引入Internet地址族相关的定义

int main(int argc, char const *argv[]) // 主函数
{
    int serv_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字

    struct sockaddr_in serv_addr;             // 定义服务器地址结构
    memset(&serv_addr, 0, sizeof(serv_addr)); // 初始化地址结构为0

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_port = htons(1234);                   // 设置端口号为1234,网络字节序
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置IP地址为本地环回地址

    if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) // 绑定地址到套接字
    {
        perror("绑定地址出错!"); // 如果绑定失败,打印错误信息
        return -1;
    }

    listen(serv_sock, 1); // 监听套接字,最大连接数为1

    struct sockaddr_in clnt_addr;                 // 定义客户端地址结构
    socklen_t clnt_addr_size = sizeof(clnt_addr); // 定义客户端地址结构大小
    int clnt_sock = accept(serv_sock,             // 接受客户端连接
                           (struct sockaddr *)&clnt_addr,
                           &clnt_addr_size);

    char buffer[1024];                 // 定义缓冲区
    memset(buffer, 0, sizeof(buffer)); // 初始化缓冲区为0

    read(clnt_sock, buffer, sizeof(buffer));  // 从客户端读取数据到缓冲区
    printf("客户端发来的信息:%s\n", buffer); // 打印客户端发来的信息

    write(clnt_sock, buffer, sizeof(buffer)); // 将缓冲区中的数据写回客户端

    close(clnt_sock); // 关闭客户端套接字
    close(serv_sock); // 关闭服务器套接字

    printf("关闭连接成功!\n"); // 打印关闭连接成功的消息

    return 0; // 程序结束
}

0022回声测试_客户端

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <string.h>     // 引入字符串操作库
#include <unistd.h>     // 引入Unix标准函数库
#include <stdlib.h>     // 引入标准库,提供多种函数
#include <arpa/inet.h>  // 引入IP地址转换函数库
#include <sys/socket.h> // 引入套接字API

int main(int argc, char const *argv[]) // 主函数
{
    int clnt_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字

    struct sockaddr_in serv_addr;             // 定义服务器地址结构
    memset(&serv_addr, 0, sizeof(serv_addr)); // 初始化地址结构为0

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_port = htons(1234);                   // 设置端口号为1234,网络字节序
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置IP地址为本地环回地址

    if (connect(clnt_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) // 连接到服务器
    {
        perror("连接失败!"); // 如果连接失败,打印错误信息
        return -1;            // 返回-1表示连接失败
    }

    char buffer[1024];                      // 定义缓冲区
    memset(buffer, 0, sizeof(buffer));      // 初始化缓冲区为0
    printf("连接成功!输入发送的内容:\n"); // 提示用户输入内容
    scanf("%s", buffer);                    // 从标准输入读取字符串到缓冲区

    write(clnt_sock, buffer, sizeof(buffer)); // 将缓冲区中的数据发送到服务器
    memset(buffer, 0, sizeof(buffer));        // 清空缓冲区

    read(clnt_sock, buffer, sizeof(buffer)); // 从服务器读取数据到缓冲区
    printf("接收到的信息为:%s\n", buffer);    // 打印接收到的信息

    close(clnt_sock);       // 关闭客户端套接字
    printf("关闭连接!\n"); // 打印关闭连接的消息

    return 0; // 程序结束
}

  运行结果:

在这里插入图片描述

0030启动端口复用解决端口绑定失败问题

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <string.h>     // 引入字符串操作库
#include <stdlib.h>     // 引入标准库,提供多种函数
#include <unistd.h>     // 引入Unix标准函数库
#include <arpa/inet.h>  // 引入IP地址转换函数库
#include <sys/socket.h> // 引入套接字API
#include <netinet/in.h> // 引入Internet地址族相关的定义

int main(int argc, char const *argv[]) // 主函数
{
    int serv_sock1 = socket(AF_INET, SOCK_STREAM, 0); // 创建第一个TCP套接字

    // 设置SO_REUSEADDR来允许端口复用
    int reuse = 1;
    if (setsockopt(serv_sock1, SOL_SOCKET, SO_REUSEADDR, (const void *)&reuse, sizeof(reuse)) < 0)
    {
        perror("设置SO_REUSEADDR 1 失败"); // 如果设置失败,打印错误信息
        return -1;                         // 返回-1表示设置失败
    }

    struct sockaddr_in serv_addr1;                       // 定义第一个服务器地址结构
    memset(&serv_addr1, 0, sizeof(serv_addr1));          // 初始化地址结构为0
    serv_addr1.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr1.sin_port = htons(1234);                   // 设置端口号为1234,网络字节序
    serv_addr1.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置IP地址为本地环回地址

    if (bind(serv_sock1, (struct sockaddr *)&serv_addr1, sizeof(serv_addr1)) != 0) // 绑定地址到第一个套接字
    {
        perror("serv_sock1 绑定sock失败!"); // 如果绑定失败,打印错误信息
        return -1;                           // 返回-1表示绑定失败
    }

    int serv_sock2 = socket(AF_INET, SOCK_STREAM, 0); // 创建第二个TCP套接字

    // 同样为第二个套接字设置SO_REUSEADDR
    if (setsockopt(serv_sock2, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
    {
        perror("设置SO_REUSEADDR 2 失败"); // 如果设置失败,打印错误信息
        return -1;                         // 返回-1表示设置失败
    }

    if (bind(serv_sock2, (struct sockaddr *)&serv_addr1, sizeof(serv_addr1)) != 0) // 绑定地址到第二个套接字
    {
        perror("serv_sock2 绑定sock失败!"); // 如果绑定失败,打印错误信息
        return -1;                           // 返回-1表示绑定失败
    }

    printf("端口复用成功!\n"); // 打印端口复用成功的消息

    close(serv_sock1); // 关闭第一个套接字
    close(serv_sock2); // 关闭第二个套接字

    return 0; // 程序结束
}

  运行结果:

在这里插入图片描述

0041服务器不间断进行侦听通信_服务端

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <string.h>     // 引入字符串操作库
#include <stdlib.h>     // 引入标准库,提供多种函数
#include <unistd.h>     // 引入Unix标准函数库
#include <arpa/inet.h>  // 引入IP地址转换函数库
#include <sys/socket.h> // 引入套接字API
#include <netinet/in.h> // 引入Internet地址族相关的定义

int main(int argc, char const *argv[]) // 主函数
{
    int serv_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字
    struct sockaddr_in serv_addr;                    // 定义服务器地址结构
    memset(&serv_addr, 0, sizeof(serv_addr));        // 初始化地址结构为0

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_port = htons(1234);                   // 设置端口号为1234,网络字节序
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器IP为本地环回地址

    bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); // 绑定地址到套接字

    listen(serv_sock, 3); // 监听套接字,最大连接数为3

    while (1) // 无限循环等待客户端连接
    {
        char buffer[128];                  // 定义缓冲区用于接收和发送数据
        memset(buffer, 0, sizeof(buffer)); // 初始化缓冲区为0

        struct sockaddr_in clnt_addr;                 // 定义客户端地址结构
        socklen_t clnt_sock_size = sizeof(clnt_addr); // 定义客户端地址结构大小
        int clnt_sock = accept(serv_sock,             // 接受客户端连接
                               (struct sockaddr *)&clnt_addr,
                               &clnt_sock_size);

        read(clnt_sock, buffer, sizeof(buffer));  // 读取客户端发送的数据
        printf("客户端发来的消息:%s\n", buffer); // 打印客户端发送的消息
        write(clnt_sock, buffer, sizeof(buffer)); // 将收到的消息写回客户端

        close(clnt_sock); // 关闭与客户端的连接

        if (strcmp(buffer, "exit") == 0) // 如果客户端发送的消息是"exit"
        {
            break; // 退出循环
        }
    }

    close(serv_sock); // 关闭服务器套接字

    printf("关闭一切连接。\n"); // 打印关闭连接的信息

    return 0; // 程序结束
}

0042服务器不间断进行侦听通信_客户端

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <string.h>     // 引入字符串操作库
#include <unistd.h>     // 引入Unix标准函数库
#include <stdlib.h>     // 引入标准库定义
#include <arpa/inet.h>  // 引入IP地址转换库
#include <sys/socket.h> // 引入套接字库

int main(int argc, char const *argv[])
{
    struct sockaddr_in serv_addr;             // 定义服务器地址结构体
    memset(&serv_addr, 0, sizeof(serv_addr)); // 初始化服务器地址结构体为0

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_port = htons(1234);                   // 设置端口号为1234,网络字节序
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器IP地址为本地回环地址

    while (1)
    {                                                    // 循环处理连接
        int clnt_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建客户端套接字

        if (connect(clnt_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0)
        {
            perror("连接失败!"); // 连接失败,打印错误信息
        }

        char buffer[1024];                      // 定义缓冲区
        memset(buffer, 0, sizeof(buffer));      // 初始化缓冲区为0
        printf("连接成功!输入发送的内容:\n"); // 提示用户输入内容
        scanf("%s", buffer);                    // 从标准输入读取字符串到缓冲区

        write(clnt_sock, buffer, sizeof(buffer)); // 向服务器发送数据
        memset(buffer, 0, sizeof(buffer));        // 重置缓冲区

        read(clnt_sock, buffer, sizeof(buffer)); // 从服务器读取数据到缓冲区
        printf("接收到的信息为:%s\n", buffer);  // 打印接收到的信息

        close(clnt_sock); // 关闭套接字

        if (strcmp(buffer, "exit") == 0)
        {          // 如果接收到的信息是"exit"
            break; // 退出循环
        }
    }

    printf("关闭连接!\n"); // 打印关闭连接信息

    return 0; // 程序结束返回0
}

  运行结果:

在这里插入图片描述

0050输入输出缓冲区大小

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <arpa/inet.h>  // 引入IP地址转换函数库
#include <sys/socket.h> // 引入套接字API

int main(int argc, char const *argv[]) // 主函数
{
    int serv_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字
    unsigned int opt_val;                            // 定义一个无符号整数变量用于存储选项值

    socklen_t opt_len = sizeof(int);                                          // 定义一个socklen_t类型的变量用于存储选项长度
    getsockopt(serv_sock, SOL_SOCKET, SO_SNDBUF, (char *)&opt_val, &opt_len); // 获取发送缓冲区大小
    printf("发送缓冲区大小: %d\n", opt_val);                                  // 打印发送缓冲区大小

    getsockopt(serv_sock, SOL_SOCKET, SO_RCVBUF, (void *)&opt_val, &opt_len); // 获取接收缓冲区大小
    printf("接收缓冲区大小: %d\n", opt_val);                                  // 打印接收缓冲区大小

    return 0; // 程序结束
}

  运行结果:
在这里插入图片描述

0061TCP的粘包问题_服务端

  相关代码:

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

#define BUF_SIZE 100

int main(int argc, char const *argv[])
{
    // 创建套接字
    int servSock = socket(AF_INET, SOCK_STREAM, 0);

    // 绑定套接字
    struct sockaddr_in sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));            // 每个字节都用0填充
    sockAddr.sin_family = AF_INET;                     // 使用IPv4地址
    sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 具体的IP地址
    sockAddr.sin_port = htons(1234);                   // 端口
    bind(servSock, (struct sockaddr *)&sockAddr, sizeof(sockAddr));

    // 进入监听状态
    listen(servSock, 20);

    // 接收客户端请求
    struct sockaddr_in clntAddr;
    socklen_t nSize = sizeof(clntAddr);
    char buffer[BUF_SIZE] = {0}; // 缓冲区
    int clntSock = accept(servSock, (struct sockaddr *)&clntAddr, &nSize);

    // 注意暂停10秒!在这10秒期间,客户端发送过来的任意数据都会堆积在缓冲区中
    sleep(10);

    // 接收客户端发来的数据,并原样返回
    int recvLen = recv(clntSock, buffer, BUF_SIZE, 0);
    send(clntSock, buffer, recvLen, 0);

    // 关闭套接字并终止DLL的使用
    close(clntSock);
    close(servSock);

    return 0;
}

0062TCP的粘包问题_客户端

  相关代码:

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

#define BUF_SIZE 100

int main(int argc, char const *argv[])
{
    // 向服务器发起请求
    struct sockaddr_in sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr)); // 每个字节都用0填充
    sockAddr.sin_family = PF_INET;
    sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    sockAddr.sin_port = htons(1234);

    // 创建套接字
    int sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    connect(sock, (struct sockaddr *)&sockAddr, sizeof(sockAddr));

    // 获取用户输入的字符串并发送给服务器
    char bufSend[BUF_SIZE] = {0};
    printf("输入内容: ");
    scanf("%s", bufSend);
    for (int i = 0; i < 3; i++)
    {
        send(sock, bufSend, strlen(bufSend), 0);
    }

    // 接收服务器传回的数据
    char bufRecv[BUF_SIZE] = {0};
    recv(sock, bufRecv, BUF_SIZE, 0);
    // 输出接收到的数据
    printf("来源于服务器的信息为: %s\n", bufRecv);

    close(sock); // 关闭套接字

    return 0;
}

  运行结果:

在这里插入图片描述

0071使用shutdown关闭连接_服务端

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <stdlib.h>     // 引入标准库,提供多种函数
#include <string.h>     // 引入字符串操作库
#include <unistd.h>     // 引入Unix标准函数库
#include <arpa/inet.h>  // 引入IP地址转换函数库
#include <sys/socket.h> // 引入套接字API
#include <netinet/in.h> // 引入Internet地址族相关的定义

int main(int argc, char const *argv[]) // 主函数
{
    int serv_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字

    struct sockaddr_in serv_addr;             // 定义服务器地址结构
    memset(&serv_addr, 0, sizeof(serv_addr)); // 初始化地址结构为0

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_port = htons(1234);                   // 设置端口号为1234,网络字节序
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器IP为本地环回地址

    bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); // 绑定地址到套接字

    listen(serv_sock, 1); // 监听套接字,最大连接数为1

    struct sockaddr_in clnt_addr;             // 定义客户端地址结构
    socklen_t clnt_size = sizeof(clnt_addr);  // 定义客户端地址结构大小
    memset(&clnt_addr, 0, sizeof(clnt_addr)); // 初始化客户端地址结构为0

    int clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_size); // 接受客户端连接

    char buffer[128];                  // 定义缓冲区用于接收和发送数据
    memset(buffer, 0, sizeof(buffer)); // 初始化缓冲区为0

    read(clnt_sock, buffer, sizeof(buffer));  // 读取客户端发送的数据
    printf("客户端的数据为:%s\n", buffer);   // 打印客户端发送的数据
    write(clnt_sock, buffer, sizeof(buffer)); // 将收到的数据写回客户端

    // shutdown 仅关闭连接,但没释放套接字资源
    shutdown(clnt_sock, SHUT_RDWR); // 关闭客户端套接字的读写操作
    shutdown(serv_sock, SHUT_RDWR); // 关闭服务器套接字的读写操作

    // close 不仅关闭连接,还释放所有套接字资源
    close(clnt_sock); // 关闭客户端套接字
    close(serv_sock); // 关闭服务器套接字

    printf("关闭已连接\n"); // 打印关闭连接的信息

    return 0; // 程序结束
}

0072使用shutdown关闭连接_客户端

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <stdlib.h>     // 引入标准库定义
#include <string.h>     // 引入字符串操作库
#include <unistd.h>     // 引入Unix标准函数库
#include <arpa/inet.h>  // 引入IP地址转换库
#include <sys/socket.h> // 引入套接字库
#include <netinet/in.h> // 引入网络结构体定义

int main(int argc, char const *argv[])
{
    int clnt_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建客户端套接字

    struct sockaddr_in serv_addr;             // 定义服务器地址结构体
    memset(&serv_addr, 0, sizeof(serv_addr)); // 初始化服务器地址结构体为0

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_port = htons(1234);                   // 设置端口号为1234,网络字节序
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器IP地址为本地回环地址

    if (connect(clnt_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0)
    {
        perror("连接错误!"); // 连接失败,打印错误信息
        return -1;            // 返回错误码-1
    }

    char buffer[128];                  // 定义缓冲区
    memset(buffer, 0, sizeof(buffer)); // 初始化缓冲区为0

    printf("请输入给服务端发送的数据信息:\n"); // 提示用户输入数据
    scanf("%s", buffer);                        // 从标准输入读取字符串到缓冲区
    write(clnt_sock, buffer, sizeof(buffer));   // 向服务器发送数据

    memset(buffer, 0, sizeof(buffer));       // 重置缓冲区
    read(clnt_sock, buffer, sizeof(buffer)); // 从服务器读取数据到缓冲区

    printf("从服务端读取到的数据为:%s\n", buffer); // 打印接收到的数据

    // shutdown 仅关闭连接,但没释放套接字资源
    shutdown(clnt_sock, SHUT_RDWR);

    // close 不仅关闭连接,还释放所有套接字资源
    close(clnt_sock);

    printf("关闭已连接\n"); // 打印关闭连接信息

    return 0; // 程序结束返回0
}

  运行结果:

在这里插入图片描述

0081使用TCP进行文件传输_服务端

  注意!要确保服务器存在该文件!

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <unistd.h>     // 引入Unix标准函数库
#include <stdlib.h>     // 引入标准库,提供多种函数
#include <string.h>     // 引入字符串操作库
#include <arpa/inet.h>  // 引入IP地址转换函数库
#include <sys/socket.h> // 引入套接字API
#include <netinet/in.h> // 引入Internet地址族相关的定义

#define BUF_SIZE 1024 // 定义缓冲区大小为1024字节

int main(int argc, char const *argv[]) // 主函数
{
    char *filename = "./picture.webp"; // 指定要传输的文件名
    FILE *fp = fopen(filename, "rb");  // 以二进制读取方式打开文件
    if (fp == NULL)                    // 如果文件打开失败
    {
        perror("文件不存在!"); // 打印错误信息
        return -1;              // 返回-1表示程序执行失败
    }

    int serv_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字

    struct sockaddr_in serv_addr;             // 定义服务器地址结构
    memset(&serv_addr, 0, sizeof(serv_addr)); // 初始化地址结构为0

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_port = htons(1234);                   // 设置端口号为1234,网络字节序
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器IP为本地环回地址

    bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); // 绑定地址到套接字

    listen(serv_sock, 1); // 监听套接字,最大连接数为1

    struct sockaddr_in clnt_addr;                 // 定义客户端地址结构
    socklen_t clnt_addr_size = sizeof(clnt_addr); // 定义客户端地址结构大小
    memset(&clnt_addr, 0, sizeof(clnt_addr));     // 初始化客户端地址结构为0

    int clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_addr_size); // 接受客户端连接

    char buffer[BUF_SIZE] = {0};                                  // 定义缓冲区用于读取文件内容
    int read_data_size = 0;                                       // 定义读取数据大小的变量
    while ((read_data_size = fread(buffer, 1, BUF_SIZE, fp)) > 0) // 循环读取文件内容到缓冲区
    {
        send(clnt_sock, buffer, read_data_size, 0); // 发送缓冲区中的数据到客户端
    }

    // 给客户端发FIN包,告诉客户端已经发送完毕
    shutdown(clnt_sock, SHUT_RDWR); // 关闭客户端套接字的读写操作

    close(serv_sock);           // 关闭服务器套接字
    close(clnt_sock);           // 关闭客户端套接字
    fclose(fp);                 // 关闭文件
    printf("数据传输完毕。\n"); // 打印数据传输完成的信息

    return 0; // 程序结束
}

0082使用TCP进行文件传输_客户端

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <unistd.h>     // 引入Unix标准函数库
#include <stdlib.h>     // 引入标准库定义
#include <string.h>     // 引入字符串操作库
#include <arpa/inet.h>  // 引入IP地址转换库
#include <sys/socket.h> // 引入套接字库
#include <netinet/in.h> // 引入网络结构体定义

#define BUF_SIZE 1024 // 定义缓冲区大小为1024字节

int main(int argc, char const *argv[])
{
    char buffer[BUF_SIZE] = {0};          // 定义并初始化缓冲区
    printf("请输入文件路径和文件名:\n"); // 提示用户输入文件路径和文件名
    scanf("%s", buffer);                  // 从标准输入读取文件路径和文件名到缓冲区
    FILE *fp = fopen(buffer, "wb");       // 以二进制写模式打开文件
    if (fp == NULL)
    {
        perror("打开文件失败!"); // 打开文件失败,打印错误信息
        return -1;                // 返回错误码-1
    }

    int clnt_sock = socket(AF_INET, SOCK_STREAM, 0); // 创建客户端套接字

    struct sockaddr_in serv_addr;             // 定义服务器地址结构体
    memset(&serv_addr, 0, sizeof(serv_addr)); // 初始化服务器地址结构体为0

    serv_addr.sin_family = AF_INET;                     // 设置地址家族为IPv4
    serv_addr.sin_port = htons(1234);                   // 设置端口号为1234,网络字节序
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器IP地址为本地回环地址

    connect(clnt_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); // 连接服务器

    memset(buffer, 0, BUF_SIZE);                                           // 重置缓冲区
    int receive_data_size = 0;                                             // 定义接收数据大小变量
    while ((receive_data_size = recv(clnt_sock, buffer, BUF_SIZE, 0)) > 0) // 循环接收数据直到没有数据可接收
    {
        fwrite(buffer, receive_data_size, 1, fp); // 将接收到的数据写入文件
    }

    fclose(fp);       // 关闭文件
    close(clnt_sock); // 关闭套接字

    printf("数据接收完毕。\n"); // 打印数据接收完成信息

    return 0; // 程序结束返回0
}

  运行结果:

在这里插入图片描述

在这里插入图片描述

0091网络字节序转换函数1

  相关代码:

#include <stdio.h>      // 引入标准输入输出库
#include <stdlib.h>     // 引入标准库,提供多种函数
#include <arpa/inet.h>  // 引入IP地址转换函数库
#include <sys/socket.h> // 引入套接字API
#include <netinet/in.h> // 引入Internet地址族相关的定义

int main(int argc, char const *argv[]) // 主函数
{
    unsigned short host_port = 0x1234, net_port;    // 定义主机字节序的端口号和网络字节序的端口号
    unsigned long host_addr = 0x12345678, net_addr; // 定义主机字节序的IP地址和网络字节序的IP地址

    net_port = htons(host_port); // 将主机字节序的端口号转换为网络字节序
    net_addr = htonl(host_addr); // 将主机字节序的IP地址转换为网络字节序

    printf("主机端口为:%#x\n", host_port);  // 打印主机字节序的端口号
    printf("网络端口为:%#x\n", net_port);   // 打印网络字节序的端口号
    printf("主机地址为:%#lx\n", host_addr); // 打印主机字节序的IP地址
    printf("网络地址为:%#lx\n", net_addr);  // 打印网络字节序的IP地址

    return 0; // 程序结束
}

  运行结果:

在这里插入图片描述

0091网络字节序转换函数2

  相关代码:

#include <stdio.h> // 引入标准输入输出库
#include <stdlib.h> // 引入标准库定义
#include <arpa/inet.h> // 引入IP地址转换库
#include <sys/socket.h> // 引入套接字库
#include <netinet/in.h> // 引入网络结构体定义

int main(int argc, char const *argv[])
{
    char *addr1 = "1.2.3.4"; // 定义一个有效的IP地址字符串
    char *addr2 = "1.2.3.256"; // 定义一个无效的IP地址字符串进行测试

    unsigned long conv_addr = inet_addr(addr1); // 将IP地址字符串转换为网络字节序的整数
    if (conv_addr == INADDR_NONE) // 如果转换失败,inet_addr返回INADDR_NONE
    {
        perror("转换错误!"); // 打印错误信息
    }
    else
    {
        printf("网络地址为:%#lx\n", conv_addr); // 打印转换后的网络地址
    }

    conv_addr = inet_addr(addr2); // 尝试转换无效的IP地址字符串
    // inet_addr函数可以检测出错误的地址并返回INADDR_NONE
    if (conv_addr == INADDR_NONE)
    {
        perror("转换错误!"); // 打印错误信息
    }
    else
    {
        printf("网络地址为:%#lx\n", conv_addr); // 打印转换后的网络地址
    }

    return 0; // 程序结束返回0
}

  运行结果:

在这里插入图片描述

0100进行域名解析

  相关代码:

#include <stdio.h>     // 引入标准输入输出库
#include <arpa/inet.h> // 引入IP地址转换函数库
#include <netdb.h>     // 引入网络数据库操作库,包含gethostbyname函数和struct hostent结构体

int main(int argc, char const *argv[])
{
    struct hostent *host = gethostbyname("www.baidu.com"); // 使用gethostbyname函数获取网址"www.baidu.com"的主机信息

    if (host == NULL) // 如果获取主机信息失败
    {
        perror("解析网址失败!"); // 打印错误信息
        return -1;                // 返回-1表示程序执行失败
    }

    for (int i = 0; host->h_aliases[i]; i++) // 遍历地址别名列表
    {
        printf("地址别名 %i 为:%s\n", i, host->h_aliases[i]); // 打印每个地址别名
    }

    printf("地址类型为:%s\n", (host->h_addrtype == AF_INET) ? "IPV4" : "IPV6"); // 打印地址类型

    for (int i = 0; host->h_addr_list[i]; i++) // 遍历IP地址列表
    {
        printf("IP地址 %d:%s\n", i + 1, inet_ntoa(*(struct in_addr *)host->h_addr_list[i])); // 打印每个IP地址
    }

    return 0; // 程序结束
}

  运行结果:

在这里插入图片描述

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值