网络: 套接字

套接字: 在网络上进行进程间通信

网络字节序与主机字节序的转化

sockaddr

sockaddr

struct sockaddr {
    sa_family_t sa_family; // 地址族
    char        sa_data[14]; // 地址数据,具体内容与地址族相关
};

sockaddr_in :主要是地址类型, 端口号, IP地址. 基于IPv4编程时, 使用的数据结构sockaddr_in

struct sockaddr_in {
    sa_family_t    sin_family;  // 地址族,通常为 AF_INET
    in_port_t      sin_port;    // 端口号,网络字节顺序
    struct in_addr sin_addr;    // IPv4 地址结构
    char           sin_zero[8]; // 无用字段,通常用零填充
};

struct in_addr {
    in_addr_t s_addr; // IPv4 地址,32 位无符号整数,网络字节顺序
};

地址转换函数

字符串转in_addr的函数

in_addr转字符串的函数

sock常见API

头文件: <sys/socket.h>  <netinet/in.h>  <arpa/inet.h>  <sys/types.h>

// 创建 socket 文件描述符(TCP/UDP, 客户端 + 服务器) (返回一个套接字描述符,失败返回 -1)
int socket(int domain, int type, int protocol);

// 绑定端口号 (TCP/UDP, 服务器) (成功绑定返回 0,失败返回 -1)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);

// 开始监听socket (TCP, 服务器) (成功返回 0,失败返回 -1)
int listen(int socket, int backlog);

// 接收请求 (TCP, 服务器) (成功返回一个套接字描述符,失败返回 -1)
int accept(int socket, struct sockaddr* address,socklen_t* address_len);

// 建立连接 ((TCP, 客户端) (成功返回0, 失败返回-1)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

//关闭文件描述符 (成功返回 0, 失败返回-1)
close(sockfd);


// 发送数据 (TCP/UDP) (返回发送的字节数,失败返回 -1)
ssize_t send(int sockfd, const void *buf, size_t len, int flags);

// 接收数据 (TCP/UDP) (返回接收的字节数,失败返回 -1)
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

// 发送数据到指定目标 (UDP)
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, 
             const struct sockaddr *dest_addr, socklen_t addrlen);

// 接收数据并记录发送端地址信息 (UDP)
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
               struct sockaddr *src_addr, socklen_t *addrlen);

TCP套接字

  • 客户端
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main() 
{
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[1024];

    // 1.创建套接字 (-1表示失败)
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    // 设置服务器地址信息
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080); // 服务器端口
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器 IP 地址

    // 2.连接服务器 
    connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));

    // 3.发送数据
    send(sockfd, "Hello, server!", strlen("Hello, server!"), 0);

    // 4.接收数据
    recv(sockfd, buffer, sizeof(buffer), 0);
    printf("Server says: %s\n", buffer);

    // 5.关闭套接字
    close(sockfd);

    return 0;
}
  • 服务端
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main() 
{
    int sockfd, newsockfd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len;
    char buffer[1024] = "Hello, client!";

    // 1.创建套接字 (-1表示失败)
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    // 设置服务器地址信息
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);       // 监听端口
    server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网络接口

    // 2.绑定端口(-1表示失败)
    bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)

    // 3.监听连接(-1表示失败)
    listen(sockfd, 5);

    // 4.接受连接(-1表示失败)
    client_len = sizeof(client_addr);
    newsockfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);

    // 5.接收数据
    recv(newsockfd, buffer, sizeof(buffer), 0);
    printf("Client says: %s\n", buffer);

    // 6.发送数据
    send(newsockfd, "Hello, client!", strlen("Hello, client!"), 0);

    // 7.关闭连接
    close(newsockfd);
    close(sockfd);

    return 0;
}

UDP套接字

  • 客户端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

#define SERVER_IP "127.0.0.1"
#define PORT 12345
#define MAX_LINE 100

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[MAX_LINE];
    socklen_t server_len;
    ssize_t bytes_sent, bytes_received;

    // 1.创建套接字(返回值 < 0 表示失败)
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // 设置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    //将一个文本格式的 IPv4 或 IPv6 地址转换为网络字节序(大端序)的二进制形式
    inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr);


    // 发送数据 (返回值 < 0 表示失败)
    char *message = "Hello, server!";
    server_len = sizeof(server_addr);
    bytes_sent = sendto(sockfd, message, strlen(message), 0, 
                (struct sockaddr*)&server_addr, server_len);

    // 接收数据 (返回值< 0 表示出错)
    bytes_received = recvfrom(sockfd, buffer, MAX_LINE, 0, NULL, NULL);
    buffer[bytes_received] = '\0';
    printf("Received from server: %s\n", buffer);

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

    return 0;
}
  • 服务端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

#define PORT 12345
#define MAX_LINE 100

int main() 
{
    int sockfd;
    struct sockaddr_in server_addr, client_addr;
    char buffer[MAX_LINE];
    socklen_t client_len;
    ssize_t bytes_received, bytes_sent;

    // 1.创建套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // 设置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(PORT);

    // 2.绑定端口
    bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));

    // 3.接收数据
    client_len = sizeof(client_addr);
    bytes_received = recvfrom(sockfd, buffer, MAX_LINE, 0, 
            (struct sockaddr *)&client_addr, &client_len);
    buffer[bytes_received] = '\0';

    // 4.发送数据
    char *message = "Hello, client!";
    bytes_sent = sendto(sockfd, message, strlen(message), 0, 
                (struct sockaddr *)&client_addr, client_len);

    // 5.关闭套接字
    close(sockfd);

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux:文件增删 文件压缩指令

Linux&#xff1a;文件增删 & 文件压缩指令 文件增删touch指令mkdir指令cp指令rm指令rmdir指令 文件压缩zip & unzip 指令tar指令 文件增删 touch指令 功能&#xff1a;touch命令参数可更改文档或目录的日期时间&#xff0c;包括存取时间和更改时间&#xff0c;或者新…

vitepress builld报错

问题&#xff1a;build时报错&#xff1a;document/window is not defined。 背景&#xff1a;使用vitepress展示自定义的组件&#xff0c;之前build是没有问题了&#xff0c;由于新增了qr-code以及quill富文本组件&#xff0c;导致打包时报错。 原因&#xff1a;vitepress官…

密码学 总结

群 环 域 群 group G是一个集合&#xff0c;在此集合上定义代数运算*&#xff0c;若满足下列公理&#xff0c;则称G为群。 1.封闭性 a ∈ G , b ∈ G a\in G,b\in G a∈G,b∈G> a ∗ b ∈ G a*b\in G a∗b∈G 2.G中有恒等元素e&#xff0c;使得任何元素与e运算均为元素本…

vue实现把Ox格式颜色值转换成rgb渐变颜色值(开箱即用)

图示&#xff1a; 核心代码&#xff1a; //将0x格式的颜色转换为Hex格式&#xff0c;并计算插值返回rgb颜色 Vue.prototype.$convertToHex function (colorCode1, colorCode2, amount) {// 确保输入是字符串&#xff0c;并检查是否以0x开头let newCode1 let newCode2 if (t…

YOLOv9改进策略:block优化 | Transformer架构ConvNeXt 网络在检测中大放异彩

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a;Transformer架构 ConvNeXt 网络在图像分类和识别、分割领域大放异彩&#xff0c;同时对比 Swin-T 模型&#xff0c;在多种任务中其模型的大小和准确率均有一些提升&#xff0c;模型的 FLOPs 较大的减小且 Acc …

Solana 低至 0.4 Sol 创建OpenBook市场ID教程

Raydium上线代币之前&#xff0c;需要OpenBook ID&#xff0c;但是Raydium官方提供的链接创建需要花费 3-4 SOL。这成本使得我们对发行代币望而却步。 本篇文章介绍OpenBook的概念和教大家如何更低成本 (最低0.4 SOL) 创建 OpenBook Market ID。 目录 1、Raydium加池子创建为什…

机器学习中的 K-Means算法及其优缺点(包含Python代码样例)

一、简介 K-Means算法是一种经典的无监督学习算法&#xff0c;用于将数据集中的样本分为 K 个不同的类别。K-均值聚类算法的工作原理如下&#xff1a; 随机选择 K 个中心点作为初始聚类中心。将每个样本点分配到离其最近的聚类中心&#xff0c;形成 K 个初始聚类。通过计算每…

亮数据——让你的IP走出去,让价值返回来

亮数据——让你的IP走出去&#xff0c;让价值返回来 前言跨境电商最最最大的痛点——让IP走出去超级代理服务器加速网络免费的代理管理软件亮数据解决痛点亮数据优势介绍亮数据浏览器的使用示例总结 前言 当前社会信息的价值是不可想象的&#xff0c;今天在亮数据中看到了个【…

大话设计模式之模板方法模式

模板方法模式&#xff08;Template Method Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一个算法的框架&#xff0c;将特定步骤的实现延迟到子类中。模板方法模式通过在父类中定义算法的骨架&#xff0c;而将具体步骤的实现留给子类来完成&#xff0c;从而使子类…

用搜索引擎收集信息-常用方式

1&#xff0c;site csdn.net &#xff08;下图表示只在csdn网站里搜索java&#xff09; 2&#xff0c;filetype:pdf &#xff08;表示只检索某pdf文件类型&#xff09; 表示在浏览器里面查找有关java的pdf文件 3&#xff0c;intitle:花花 &#xff08;表示搜索网页标题里面有花…

linux查找指定目录下包含指定字符串文件,包含子目录

linux查找指定目录下包含指定字符串的文件&#xff0c;包含子目录 linux查找指定目录下包含指定字符串的指定文件格式&#xff0c;包含子目录 指定目录 cd /home/www/linux查找指定目录下包含指定字符串的文件&#xff0c;包含子目录 grep -r "指定字符串"注释 gr…

微信开发者工具接入短剧播放器插件

接入短剧播放插线 申请添加插件基础接入app.jsonapp.jsplayerManager.js数据加密跳转到播放器页面运行出错示例小程序页面页面使用的方法小程序输入框绑定申请添加插件 添加插件:登录微信开发者平台 ——> 设置 ——> 第三方设置 ——> 插件管理 ——> 搜索“短剧…

操作系统导论-py2文件修改为py3文件快捷解决方法

在操作系统导论作业中&#xff0c;我们需要用到HW文件。但是这个代码包中&#xff0c;所有.py文件都是py2格式的&#xff0c;需要我们修改为py3文件后运行&#xff0c;即将.py文件开头的 #! /usr/bin/env python 修改为&#xff1a; #! /usr/bin/env python3 在前面小部分文件中…

【快捷部署】010_MySQL(5.7.27)

&#x1f4e3;【快捷部署系列】010期信息 编号选型版本操作系统部署形式部署模式复检时间010MySQL5.7.27Ubuntu 20.04Docker单机2024-03-28 一、快捷部署 #!/bin/bash ################################################################################# # 作者&#xff1a…

idea类已经存在却报错

一句话导读 在idea中导入新的项目&#xff0c;很多类都飘红报错&#xff0c;mvn compile可以通过&#xff0c;可能是因为idea缓存问题导致。 由于这个项目是由老项目复制过来后&#xff0c;再继续开发新的功能&#xff0c;很多同事导入后&#xff0c;都爆出新的类找不到。而编译…

正弦实时数据库(SinRTDB)的使用(4)-快照查询

前文已经将松果实时数据库的安装、创建点表、创建测点、接入OPC DA的数据进行了介绍&#xff0c;没有了解的可以先看如下博客&#xff1a; 正弦实时数据库(SinRTDB)的安装 正弦实时数据库(SinRTDB)的使用(1)-使用数据发生器写入数据 正弦实时数据库(SinRTDB)的使用(2)-接入O…

【吊打面试官系列】Redis篇 -怎么测试 Redis 的连通性?

大家好&#xff0c;我是锋哥。今天分享关于 【怎么测试 Redis 的连通性&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 怎么测试 Redis 的连通性&#xff1f; 使用 ping 命令。 要测试Redis的连通性&#xff0c;可以使用redis-cli命令行工具或编写代码。以下是…

Docker 哲学 - Dockerfile 指令

Dockerfile 的 entrypoint 和 cmd 书写方式一样吗&#xff0c;分别用一个node项目的 demo来举例 Dockerfile 的 entrypoint 、cmd 有什么区别&#xff0c;分别举例他们同时出现的场景和 单独出现的场景 entrypoint 和 cmd 命令&#xff1a; 同时出现&#xff1a; 1、cmd 作为 e…

格式化危机!教你轻松恢复数据!

一、遭遇格式化&#xff0c;数据恢复并非难事 当存储设备遭遇格式化后&#xff0c;许多人可能会陷入恐慌&#xff0c;担心重要数据一去不复返。但实际上&#xff0c;数据恢复并非如想象中那般困难。格式化操作主要清除了文件系统的索引信息&#xff0c;而实际的数据往往还残留…

[STM32] Keil 创建 HAL 库的工程模板

Keil 创建 HAL 库的工程模板 跟着100ASK_STM32F103_MINI用户手册V1.1.pdf的第7章步骤进行Keil工程的创建。 文章目录 1 创建相关文件夹2 创建“main.c/h”和“stm32f1xx_clk.c/h”3 复制CMSIS和HAL库4 创建新的Keil工程5 添加组文件夹和工程文件6 配置Keil设置 1 创建相关文件…