c++ socket基于TCP

linux网络编程基础api

  1. socket 地址api:ip地址和端口对,成为 soccket 地址。

  2. socket 基础api: sys/socket.h 中,包括创建、命名、监听 socket ;接受连接、发起连接、读写数据、获取地址信息、检测带外标记、读取设置 socket 选项

  3. 网络信息api:主机名和ip地址之间的转换、服务名称和端口号之间的转换。 netdb.h 中。

socket通信过程

  1. server端
    创建socket()->绑定地址和端口bind()->监听连接listen()->接受连接accept()->发送数据send()->关闭socket close()
  2. client
    创建socket()->IP地址转换inet_pton()->连接到服务端connect()->接收数据read()->关闭socket close()
  • TCP:可靠传输,三次握手建立连接,传出去一定接受的到(如聊天软件);

  • UDP:不可靠传输,不需要建立连接,只管发送,实时性好(如视频会议);

  • 套接字:表示通信的端点。就像用电话通信,套接字相当于电话,IP地址相当于总机号码,而端口号则相当于分机号码。

TCP:

 UDP:

socket地址

  1. 协议族和地址
    +=========+=========+==============+
    |     协议族     |     地址族    |          描   述          |
    +=========+=========+==============+
    |  PF_UNIX   |  AF_UNIX   |UNIX本地域协议族|
    +=========+=========+==============+
    |  PF_INET    |   AF_INET   |  TCP/IPv4协议族  |
    +=========+=========+==============+
    |  PF_INET6  |  AF_INET6 |  TCP/IPv6协议族   |
    +=========+=========+==============+

  2. tcp/ip 协议族有 sockaddr_in  和 sockaddr_in6两个专用socket地址结构体,分别用于ipv4和ipv6

// TCP/IPv4协议族
struct sockaddr_in {sa_family_t sin_family; /* 地址族 */in_port_t sin_port;  /* Port number.*/struct in_addr sin_addr; /*Internet address.  */
};struct in_addr {in_addr_t s_addr;
};// TCP/IPv6协议族
struct sockaddr_in6 {sa_family_t sin6_family; /* 地址族 */in_port_t sin6_port;	 /* Transport layer port # */uint32_t sin6_flowinfo;	 /* IPv6 flow information  = 0*/struct in6_addr sin6_addr;	/* IPv6 address */uint32_t sin6_scope_id;	 /* IPv6 scope-id */
};struct in6_addr {unsigned charsa_addr[16]; /* IPv6要用网络字节序表示 */
};

ip转换函数

  1. 将点分十进制的 IPv4 地址转换为网络字节序整数表示的 IPv4 地址,是为了方便在网络通信中使用。整数形式的 IP 地址更容易存储、传输和比较。

  2. “192.168.1.1” 转换为010101···的值

# include <arpa/inet.h>in_addr_t inet_addr( const char* strptr);   //将点分十进制的ipv4转化为网络字节序整数表示的ipv4int inet_aton(const char * cp, struct in_addr* inp); //与上功能相同,但是转化结果存储与参数imp的地址结构中。返回1或0 表示成功或失败。char* inet_ntoa( struct in_addr in );   //将网络字节序整数转化为点分十进制ipv4,该函数内部用一个静态变量存储静态结果,因此是不可重入的。

创建socket

#include <sys/socket.h>
int socket(int domain, int type, int protocol);int server_fd = socket(AF_INET, SOCK_STREAM, 0);
  • domain:指定要使用的协议族,常用的有 AF_INET(IPv4 地址族)和 AF_INET6(IPv6 地址族)。

  • type:指定套接字的类型,常用的有 SOCK_STREAM(流套接字,用于 TCP)和 SOCK_DGRAM(数据报套接字,用于 UDP)。

  • protocol:指定要使用的协议,通常为 0,表示使用默认协议。

  • 返回值:成功创建返回 0,失败返回 -1。

函数作用:socket 函数用于创建一个套接字(socket),并返回一个文件描述符,该描述符可以用于后续的套接字操作,如绑定地址、监听连接、发送和接收数据等。

绑定地址和端口

    struct sockaddr_in address;address.sin_family = AF_INET;     // TCP/IPv4   AF_INET6:TCP/IPv6address.sin_addr.s_addr = INADDR_ANY; // 地址address.sin_port = htons(8080); // 端口号if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) == -1) {std::cerr << "Error: Failed to bind\n";return 1;}
  1. int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd:要绑定地址的套接字文件描述符。

  • addr:要绑定的地址信息,通常是一个 struct sockaddr 结构体指针,需要进行类型转换。

  • addrlen:地址信息的长度。

  • 返回值:成功绑定返回 0,失败返回 -1。

函数作用:bind 函数将一个套接字绑定到一个地址,使得该套接字可以在网络中被标识。对于服务器程序来说,通常在调用 bind 后还需要调用 listen 函数开始监听连接。对于客户端程序来说,通常不需要显式调用 bind 函数。

监听连接

    int listen(int sockfd, int backlog);if (listen(server_fd, 3) == -1) {std::cerr << "Error: Failed to listen\n";return 1;}
  • sockfd:套接字文件描述符,即要监听的套接字。
  • backlog:指定在拒绝新连接之前,操作系统可以挂起的最大连接数。
  • 返回值:成功返回 0,失败返回 -1。

函数作用:listen 函数将指定的套接字设置为监听状态,使其可以接受连接。backlog 参数指定操作系统可以挂起的最大连接数,超过这个数目的连接将被拒绝。通常在服务器端使用,用于开始接受客户端的连接请求。

接受连接

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);int addrlen = sizeof(address);int new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);if (new_socket == -1) {std::cerr << "Error: Failed to accept connection\n";return 1;}
  • sockfd:监听套接字的文件描述符,即调用 listen 函数后返回的套接字。

  • addr:指向 sockaddr 结构的指针,用于存储连接到的客户端的地址信息。

  • addrlensockaddr 结构的大小,在调用 accept 函数前,需将其初始化为 sizeof(struct sockaddr)

  • 返回值:返回一个新的套接字文件描述符,用于与客户端通信。如果出现错误,则返回 -1。

函数作用:accept 函数用于接受客户端的连接请求。当有客户端连接到服务器时,accept 函数会创建一个新的套接字,并返回该套接字的文件描述符,服务器可以使用该文件描述符与客户端进行通信。同时,addr 参数用于存储连接到的客户端的地址信息。

发送数据给客户端

    const char *message = "Hello from server";send(new_socket, message, strlen(message), 0);std::cout << "Message sent to client\n";
  • sockfd:要发送数据的套接字文件描述符。
  • buf:指向要发送数据的缓冲区。
  • len:要发送数据的长度。
  • flags:发送标志,通常设置为 0。
  • 返回值:成功时返回发送的字节数,失败时返回 -1。

函数作用:send 函数用于向指定套接字发送数据。它将缓冲区 buf 中的 len 字节数据发送到套接字 sockfd。函数的 flags 参数通常设置为 0,表示没有特殊标志

关闭socket

    close(new_socket);close(server_fd);

使用 close 函数关闭这个套接字,释放相关的资源。

  1. 释放系统资源:关闭套接字会释放操作系统为其分配的资源,包括文件描述符等。
  2. 避免资源泄漏:如果不关闭套接字,可能会导致资源泄漏,消耗系统资源并降低性能。
  3. 表示通信结束:关闭套接字可以告知对方通信结束,同时也能清理本地的通信状态。

在这段代码中,new_socket 是一个整数类型的变量,但它关联了一个与客户端通信的套接字文件描述符。在调用 accept 函数后,操作系统会创建一个新的套接字并返回其文件描述符,我们将这个文件描述符保存在 new_socket 中。因此,虽然 new_socket 是一个整数类型的变量,但它实际上是用来代表与客户端通信的套接字的文件描述符。

连接到服务端

    struct sockaddr_in serv_addr;serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(8080);if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {std::cerr << "Invalid address/ Address not supported\n";return 1;}if (connect(client_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {std::cerr << "Connection failed\n";return 1;}
  1. int inet_pton(int af, const char *src, void *dst);
  • af:指定地址族,常用的有 AF_INET(IPv4 地址族)和 AF_INET6(IPv6 地址族)。
  • src:要转换的点分十进制或十六进制字符串形式的 IP 地址。
  • dst:用于存储转换后的二进制形式 IP 地址的内存地址。
  • 返回值:如果转换成功,返回 1(对于 IPv4 地址)或 0(对于 IPv6 地址)。如果发生错误,返回 -1。

函数作用:inet_pton 函数用于将点分十进制或十六进制字符串形式的 IP 地址转换为二进制形式的 IP 地址表示。在这个示例中,它将字符串形式的 IPv4 地址 "127.0.0.1" 转换为二进制形式,并将结果存储在 serv_addr.sin_addr 中。如果转换成功,则条件 inet_pton(...) <= 0 将为假,否则为真。

  1. int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd:套接字文件描述符,表示要连接的套接字。
  • addr:指向要连接的目标地址信息的 sockaddr 结构体指针。
  • addrlensockaddr 结构体的大小。
  • 返回值:成功返回 0,失败返回 -1。

函数作用:connect 函数用于向指定的目标地址发起连接请求。在客户端中,通常在创建套接字后调用 connect 函数,指定要连接的服务器的地址和端口号,以建立与服务器的连接。如果连接成功建立,则可以通过该套接字进行数据传输。

从服务端接收数据

    ssize_t read(int fd, void *buf, size_t count);read(client_fd, buffer, 1024);std::cout << "Message from server: " << buffer << std::endl;
  • fd:文件描述符,即要从中读取数据的文件或套接字。
  • buf:指向存储读取数据的缓冲区的指针。
  • count:要读取的最大字节数。
  • 返回值:返回实际读取的字节数。如果返回 0,表示已经读到文件末尾(对套接字则表示连接已关闭)。如果返回 -1,表示出现错误。

函数作用:read 函数用于从文件描述符 fd 指定的文件或套接字中读取数据,将读取的数据存储到 buf 指向的缓冲区中。它会尽可能读取 count 指定的字节数,但可能会因为文件末尾或其他原因而读取少于 count 字节的数据。

代码

server.cpp

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>int main() {// 创建socketint server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd == -1) {std::cerr << "Error: Failed to create socket\n";return 1;}// 绑定地址和端口struct sockaddr_in address;int addrlen = sizeof(address);address.sin_family = inet_addr("100.10.10.1");//AF_INET;     // TCP/IPv4   AF_INET6:TCP/IPv6address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(8080);if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) == -1) {std::cerr << "Error: Failed to bind\n";return 1;}// 监听连接if (listen(server_fd, 3) == -1) {std::cerr << "Error: Failed to listen\n";return 1;}// 接受连接int new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);if (new_socket == -1) {std::cerr << "Error: Failed to accept connection\n";return 1;}// 发送数据给客户端const char *message = "Hello from server";send(new_socket, message, strlen(message), 0);std::cout << "Message sent to client\n";// 关闭socketclose(new_socket);close(server_fd);return 0;
}

client.cpp

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {// 创建socketint client_fd = socket(AF_INET, SOCK_STREAM, 0);if (client_fd == -1) {std::cerr << "Error: Failed to create socket\n";return 1;}// 连接到服务端struct sockaddr_in serv_addr;serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(8080);if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { //IP地址转换std::cerr << "Invalid address/ Address not supported\n";return 1;}if (connect(client_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {std::cerr << "Connection failed\n";return 1;}// 从服务端接收数据char buffer[1024] = {0};read(client_fd, buffer, 1024);std::cout << "Message from server: " << buffer << std::endl;// 关闭socketclose(client_fd);return 0;
}

上面内容比较简单基础,这篇socket网络通信包含TCP和UDP,以供参考 

【C++】基础:网络编程介绍与TCP&UDP示例_c++网络编程-CSDN博客

抛弃别人的目光才是自由的开始!

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

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

相关文章

unity ui 同屏

一共有三个摄像机&#xff0c;上屏&#xff0c;下屏 和 类似照相机的ccamera 类似照相机的ccamera的设置&#xff1a; 下屏摄像机设置&#xff1a; 下屏交互的Canvas设置&#xff1a; 新建一个canvas&#xff0c;下面放上rawimage&#xff1a; 如果下屏不想显示的内容&#xf…

创建和管理数据库

1. 一条数据的存储过程 存储数据是处理数据的第一步.只有正确的把数据存储起来&#xff0c;我们才能进行有效的处理和分析.否则&#xff0c;只能是一团乱麻.在MySQL中&#xff0c;一个完整的数据存储过程一共有四步 : 创建数据库&#xff0c;确认字段&#xff0c;创建数据表&a…

【练习3】

1.将二叉搜索树转为排序的双向链表 (好久没看数据结构&#xff0c;忘完了&#xff0c;学习大佬的代码&#xff09; class Solution { public:Node* prenullptr,*headnullptr; //pre为每次遍历时的前一个节点&#xff0c;head记录头节点Node* treeToDoublyList(Node* root) {if…

漏扫神器Invicti V2024.4.0专业版

前言 Invicti Professional是Invicti Security公司推出的一个产品&#xff0c;它是一种高级的网络安全扫描工具。Invicti Professional旨在帮助组织发现和修复其网络系统中的潜在安全漏洞和弱点。它提供了全面的漏洞扫描功能&#xff0c;包括Web应用程序和网络基础设施的漏洞扫…

xhs 旋转滑块流程分析

声明 本文章中所有内容仅供学习交流&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 前言 本文首发于公众号…

近似消息传递算法(AMP)单测量模型(SMV)

1、算法解决问题 很多人致力于解决SLM模型的求逆问题&#xff0c;即知道观测值和测量矩阵&#xff08;字典之类的&#xff09;&#xff0c;要求未知变量的值。SLM又叫做标准线性模型&#xff0c;后续又在此基础上进行升级变为广义线性模型。即SLM是yAxe&#xff0c;这里是线性…

STM32单片机实战开发笔记-独立看门狗IWDG

嵌入式单片机开发实战例程合集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/11av8rV45dtHO0EHf8e_Q0Q?pwd28ab 提取码&#xff1a;28ab IWDG模块测试 1、功能描述 STM32F10X内置两个看门狗&#xff0c;提供了更高的安全性&#xff0c;时间的精确下性和使用的灵活性…

【JAVA基础之时间API】自定义时间格式

&#x1f525;作者主页&#xff1a;小林同学的学习笔录 &#x1f525;mysql专栏&#xff1a;小林同学的专栏 目录 1.Date类 1.1 概述 1.2 构造方法 1.3 常用方法 2.SimpleDateFormat类 2.1 概述 2.2 构造方法 2.3 格式规则 2.4 常用方法 3.Calendar类 3.1 概述…

SparkSQL优化

SparkSQL优化 优化说明 缓存数据到内存 Spark SQL可以通过调用spark.sqlContext.cacheTable("tableName") 或者dataFrame.cache()&#xff0c;将表用一种柱状格式&#xff08; an inmemory columnar format&#xff09;缓存至内存中。然后Spark SQL在执行查询任务…

PotPlayer v1.7.22218 全格式影音播放器,无广绿色版!

软件介绍 PotPlayer是一款多功能且免费的媒体播放软件&#xff0c;兼容多种音频和视频格式。提供了丰富的功能性以及个性化设置&#xff0c;以迎合不同用户的需求。友好的用户界面&#xff0c;允许用户自定义皮肤和快捷键&#xff0c;提升了操作的便利性。 此外&#xff0c;Po…

DenseCLIP环境配置

直接看raoyongming/DenseCLIP: [CVPR 2022] DenseCLIP: Language-Guided Dense Prediction with Context-Aware Prompting (github.com) 但这里的环境配置可能和现在不太适配&#xff0c;自己配了好久没弄好 后面尝试了另外的版本的&#xff08;但这个版本少了一些内容&#…

力扣打卡第二天

206. 反转链表 class Solution { public:ListNode* reverseList(ListNode* head) {// //迭代法// ListNode *pre nullptr;// ListNode *curr head;// while(curr){// ListNode *next curr -> next;// curr -> next pre;// pre curr;// curr next;/…

【吃透Java手写】1- Spring(上)-启动-扫描-依赖注入-初始化-后置处理器

【吃透Java手写】Spring&#xff08;上&#xff09;启动-扫描-依赖注入-初始化-后置处理器 1 准备工作1.1 创建自己的Spring容器类1.2 创建自己的配置类 ComponentScan1.3 ComponentScan1.3.1 Retention1.3.2 Target 1.4 用户类UserService Component1.5 Component1.6 测试类 2…

我独自升级崛起怎么下载 游戏下载教程分享

《我独自升级&#xff1a;崛起》这款游戏核心聚焦于激烈的战斗与角色的持续成长。新加入的玩家首要任务是熟悉基础攻击模式&#xff0c;随后深入探索技能组合策略与连贯招式的艺术&#xff0c;同时掌握防守与躲避技巧&#xff0c;这些都是战斗中不可或缺的关键。随着战斗的持续…

重写muduo之Thread、EventLoopThread、EventLoopThreadPool

目录 1、概述 2、Thread 2.1 Thread.h 3、EventLoopThread 3.1 EventLoopThread.h 3.2 EventLoopThread.cc 4、 EventLoopThreadPool 4.1 EventLoopThreadPool.h 4.2 EventLoopThreadPool.cc 1、概述 管理事件循环线程的调度的 打包了一个EventLoop和线程&#xff0c;…

项目经理【过程】原则

系列文章目录 【引论一】项目管理的意义 【引论二】项目管理的逻辑 【环境】概述 【环境】原则 【环境】任务 【环境】绩效 【人】概述 【人】原则 【人】任务 【人】绩效 【过程】概念 【过程】原则 一、质量管理水平、质量管理的发展 1.1 质量管理水平 1.2 质量管理的发展 …

NAS选购全方位解析,性价比才是硬道理 | 2024年618威联通NAS选购攻略

NAS选购全方位解析&#xff0c;性价比才是硬道理 | 2024年618威联通NAS选购攻略 哈喽小伙伴们好&#xff0c;我是Stark-C~&#xff0c;临近618&#xff0c;今天和大家谈谈NAS的选购问题。 关注我的小伙伴都知道&#xff0c;经过我手头折腾的NAS设备非常多&#xff0c;除了群晖…

如果出现一个工具,可以让前端开发彻底不用再手写UI,这个工具意义大吗?干货!

求这样的一个工具&#xff0c;可以让后端开发、嵌入式开发、产品经理、UI设计师都能用&#xff0c;注意&#xff0c;不是在一个简单的静态页生成&#xff0c;也不是类似飞冰那种 generator &#xff0c;而是真正让设计师和开发者在各自的那侧达成自治&#xff0c;可以做到吗&am…

;【排列【

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

C++进阶之路:深入理解编程范式,从面向过程到面向对象(类与对象_上篇)

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…