网络编程 · 代码笔记1

news2024/10/23 22:23:03

目录

  • 前言
    • 1、编程环境
    • 2、编译命令
    • 3、标题名前缀解释
    • 4、注意事项
  • 0011客户端读取服务端字符_服务端
  • 0012客户端读取服务端字符_客户端
  • 0021回声测试_服务端
  • 0022回声测试_客户端
  • 0030启动端口复用解决端口绑定失败问题
  • 0041服务器不间断进行侦听通信_服务端
  • 0042服务器不间断进行侦听通信_客户端
  • 0050输入输出缓冲区大小
  • 0061TCP的粘包问题_服务端
  • 0062TCP的粘包问题_客户端
  • 0071使用shutdown关闭连接_服务端
  • 0072使用shutdown关闭连接_客户端
  • 0081使用TCP进行文件传输_服务端
  • 0082使用TCP进行文件传输_客户端
  • 0091网络字节序转换函数1
  • 0091网络字节序转换函数2
  • 0100进行域名解析

前言

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; // 程序结束
}

  运行结果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

liunx操作系统 环境变量

环境变量 main函数参数 命令行参数环境变量 环境变量的查看环境变量的获取 main函数参数 命令行参数 main函数是有参数的&#xff0c;只是我们一般不适用 这是main函数从bash中读取进程数据使用的一个基本入口。 下面进行简单演示。 o 好oo都是我们输入的命令行参数。其实&a…

如何查看前端的vue项目是vue2还是vue3项目

1. 检查package.json文件 在项目的根目录下&#xff0c;打开package.json文件&#xff0c;查找dependencies或devDependencies部分中的vue条目。版本号将告诉你是Vue 2还是Vue 3。例如&#xff1a; Vue 2.x: "vue": "^2.x.x"Vue 3.x: "vue": &…

【Linux基础(二)】进程管理

学习分享 1、程序和进程1.1、程序1.2、进程和进程ID 2、Linux下的进程结构3、init进程4、获取进程标识5、fork系统调用5.1、fork函数实例分析 6、进程的特性7、在Linux下进程指令7.1、终止进程指令7.2、查看进程指令&#xff1a;7.3、以树状图列出进程 8、多进程运行异常情况8.…

判断连续数据同意特征的方法:插旗法

bool isMonotonic(int* nums, int numsSize) {int flag 2;for (int i 1; i < numsSize; i) {if (nums[i-1] > nums[i]) {if (flag 0)return false;flag 1;}else if (nums[i-1] < nums[i]) {if (flag 1)return false;flag 0;}}return true; }此代码较为简单&…

Vue中如何处理组件间的耦合问题?

在Vue中处理组件间的耦合问题是前端开发中常见的挑战之一。耦合问题指的是组件之间的依赖关系过于紧密&#xff0c;一旦某个组件发生改动&#xff0c;则可能导致其它组件也需要作出相应调整。为了解决这个问题&#xff0c;我们可以采取以下几种方法&#xff1a; 使用事件总线&…

牛客每日一题之 前缀和

目录 题目介绍&#xff1a; 算法原理&#xff1a; 前缀和&#xff1a; 代码实现&#xff1a; 题目介绍&#xff1a; 题目链接&#xff1a;【模板】前缀和_牛客题霸_牛客网 算法原理&#xff1a; 先讲讲暴力解法每次求出数组下标r之前元素的和&#xff0c;再减去数组下标l-…

Docker容器的操作

目录 运行容器 查看容器 查看容器详细信息 删除容器 启动容器 停止容器 重启容器 暂停容器 激活容器 杀死容器 进入容器 常用 查看容器的日志 拷贝容器的文件到本地 容器改名 查看容器资源 查看容器内部的进程 监测容器发生的事件 检测容器停止以后的反回值…

vue3 + vite全局引入element-plus后使用 Message 消息提示

安装Element plus&#xff1a; pnpm install element-plus 安装unplugin-element-plus 自动导入组件 pnpm i -D unplugin-auto-import pnpm install -D unplugin-element-plus vite.config.ts 使用plugins数组里配置&#xff0c;自动导入 import { fileURLToPath, URL } fro…

【应用多元统计分析】--多元数据的描述和展示(R语言)

一元随机变量 我们用协方差来刻画两个变量的相关关系&#xff0c;这里指的是线性相关关系。 对于一元随机变量的可视化最简单的就是散点图&#xff0c;大致可以看出X和Y之间的相关关系。如果想更好的看X、Y之间的相关关系&#xff0c;可以画二维的散点图。 总结&#xff1a; 均…

蓝桥杯物联网竞赛_STM32L071_11_知识体系的查漏与补缺

太久没学单片机了&#xff0c;再重新过一遍查漏补缺&#xff0c;对其中之前没怎么在意的&#xff0c;而现在又发觉的问题进行再分析与补充 1. debug serial wire是干什么用的 这个东西我勾选不勾选都对我的程序没有什么影响&#xff0c;我很好奇是干什么用的&#xff0c;网上查…

【PCIe】初识PCIe

&#x1f525;博客主页&#xff1a;[PannLZ] &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 文章目录 PCIe简介PCIe速度 PCIe简介 计算机内部有很多电子元器件&#xff0c;他们之间会有数据沟通和传输的需求。如果A元件想给B元件传输数据&am…

JavaWeb04-Request,Response

目录 一、Request&#xff08;请求&#xff09; 1.作用 2.继承体系 3.获取请求数据 &#xff08;1&#xff09;请求行 &#xff08;2&#xff09;请求头 &#xff08;3&#xff09;请求体&#xff08;POST&#xff09; &#xff08;5&#xff09;Request通用方式获取请求…

Unity用Shader将一张图片变成描边图片素描风格。

环境&#xff1a; unity2021.3.x 效果&#xff1a; 实现核心思路(shader)&#xff1a; fixed4 frag (v2f i) : SV_Target {fixed4 col tex2D(_MainTex, i.uv);// 调整相似度bool isRedMatch abs(col.r - _TargetColor.r) < 0.15;bool isGreenMatch abs(col.g - _Target…

消息队列-Kafka-如何进行顺序消费

全局有序 只有 1 个分区&#xff0c;那这个时候就是能够保证消息的顺序消费。 分区有序 如果我们还是想同时消费多个分区并且保证有序&#xff0c;这个时候我们需要将需要保证顺序的消息路由到同一个分区。 在发送消息的时候我们可以看到&#xff1a; 上面的代码定义了消息…

【R语言实战】聚类分析及可视化

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

【自然语言处理】BitNet b1.58:1bit LLM时代

论文地址&#xff1a;https://arxiv.org/pdf/2402.17764.pdf 相关博客 【自然语言处理】【大模型】BitNet&#xff1a;用1-bit Transformer训练LLM 【自然语言处理】BitNet b1.58&#xff1a;1bit LLM时代 【自然语言处理】【长文本处理】RMT&#xff1a;能处理长度超过一百万t…

【Vue】sessionStorage存取数据

一. 需求 1.1 模板 Vab Admin Pro 1.2 组件 ElementUI 1.3 阐述 列表页面搜索【关键词】点击【查询】后&#xff0c;点击【查看】按钮跳转到【详情页】&#xff0c;详情页【返回】【保留原搜索关键词】 原图 搜索查询【关键词】 详情 返回后【保留】【搜索查询关键词…

一次简单操作代替所有异常处理

一、背景 在服务端处理前端发过来的响应的时候&#xff0c;开发者不可能穷尽用户的所有奇怪的操作。除此之外&#xff0c;我们还需要应付前端人员对我们的无情吐槽&#xff0c;你对XXXX请求返回的为啥是奇怪的响应数据呢&#xff1f;于是全局异常处理应运而生&#xff0c;一次处…

Java面试篇【并发编程·进阶】常见面试题(2024最新)

并发常见面试题进阶 1.synchronized synchronized关键字解决的是多线程之间访问资源的同步性&#xff0c;synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能被一个线程执行。 监视器锁&#xff08;monitor&#xff09;是依赖于底层的操作系统的 Mutex Lock来…

回溯算法07-子集(Java/子集问题)

.子集 题目描述 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[…