当前位置: 首页 > news >正文

【Linux】Linux下使用套接字进行网络编程

🔥博客主页: 我要成为C++领域大神
🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】
❤️感谢大家点赞👍收藏⭐评论✍️

本博客致力于知识分享,与更多的人进行学习交流

用于网络应用开发,使用系统提供的一套API函数接口,称为套接字函数

所有的I/O设备都被抽象为文件,一切皆文件,Everything is a File,磁盘、网络数据、终端,甚至进程间通信工具管道pipe等都被当做文件对待。

套接字文件描述符包含有IP地址和PORT端口号。

socket创建套接字

函数原型:int sockfd=socket(AF_INET,SOCKET_STREAM(流式or报式),int protocol(默认流式协议TCP))

成功返回sock_fd,失败返回-1,并设置errno

bind绑定IP和端口

函数原型:bind(sock_fd,struct sockaddr *addr)

struct sockaddr *addr是早期的网络通信结构体,为了向前兼容,仍然保留。

struct sockaddr_in addr网络信息结构体

addr.sin_family=AF_INET
addr.sin_port=大端(8080)
addr.sin_addr.s_addr=大端(ip)

大小端转换常用函数

htons()小端转大端端口

htonl()小端转大端IP

ntohs()大端转小端端口

ntohl()大端转小端IP

inet_pton(AF_INET,char *ip,void *addr)

inet_ntop(AF_INET,void *addr,char *ip,16)


绑定可以对socket设置自定义的IP和端口号,其次当绑定某端口的进程退出,可以临时禁用端口号,禁用时长为2MSL。

成功返回0,失败返回-1

listen网络事件监听(TCP)

函数原型:listen(int sockfd,int backlog)

backlog:监听序列数

成功返回0,错误返回-1,并设置errno,用于错误处理

connet请求TCP连接函数(主动端)

函数原型:connect(int mysockfd,struct sockaddr * dest,socklen_t addrlen)

客户端调用该函数向服务器发起TCP连接请求

成功返回0,错误返回-1,并设置errno,用于错误处理

Accept等待TCP连接请求,完成连接(被动端)

Accept为阻塞等待连接,每次只能连接一个客户端,如果要多次连接,要执行多次该函数

函数原型:

int client_fd=accpet(int server_fd,sockaddr * clientAddr(output),socklen_t *Addrlen(intput|output))

arg[1] 包含自身网络信息的socket

arg[2] 连接成功,传出保存客户端的网络信息(IP,port)

arg[3] 传入可以接收的网络信息大小,传出实际大小

成功返回请求端的socketfd,错误返回-1,并设置errno,用于错误处理

CS架构中,服务器socket只有一个,客户端socket有多个(server_fd用于连接,client_fd用于与客户端交互数据)

recv读取数据

在Linux下,read也可以读取socket数据(TCP),因为在Linux下,套接字以文件描述符的形式记录。

函数原型:ssize_t recv(int sockfd,void *buf,size_t size,int flag)

成功返回读取的数据量,失败返回-1

可以通过将flag设置为MSG_DONTWAIT实现非阻塞读取数据

send发送数据

在Linux下,write也可以发送socket数据(TCP),因为在Linux下,套接字以文件描述符的形式记录。

函数原型:ssize_t send(int sockfd,void *buf,size_t len,int flag)

面试题:

在编写一个服务端-客户端模型时,客户端异常退出,服务端也异常退出。

原因

当客户端异常退出时,客户端关闭了它的读端文件描述符。此时,如果服务端尝试向管道或套接字写数据,会触发 SIGPIPE 信号,默认行为是终止进程,因此服务端也会异常退出。

解决方案

可以在 send() 函数中使用 MSG_NOSIGNAL 标志位,来忽略 SIGPIPE 信号,从而避免服务端异常退出

send(int sockfd, buffer, len, MSG_NOSIGNAL);

使用 MSG_NOSIGNAL 标志位,写操作在对端关闭连接的情况下不会触发 SIGPIPE 信号,而是会返回 EPIPE 错误,程序可以根据这个错误码进行处理而不是直接终止。

在公网上利用TCP协议实现网络数据传输

由于服务端和客户端不在同一个局域网下,所以需要通过互联网进行通信,虚拟机要配置网络连接。

服务端:

服务端是运行在公网上的阿里云服务器。

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>#define _SERVER_IP "xxx.xxx.xxx.xxx"
#define _PORT 8080
#define _BACKLOG 128
#define _SHUTDOWN 1
#define _TRUE 1
#define _FALSE 0
#define _IPSIZE 16
#define _RECVLEN 1500int main()
{struct sockaddr_in serverAddr,clientAddr;int server_fd;int client_fd;char Result[_RECVLEN];char client_ip[_IPSIZE];socklen_t Addrlen;serverAddr.sin_family=AF_INET;serverAddr.sin_port=htons(_PORT);serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);server_fd=socket(AF_INET,SOCK_STREAM,0);bind(server_fd,(struct sockaddr*)&serverAddr,sizeof(serverAddr));listen(server_fd,_BACKLOG);printf("Test TCP Server Version 1.1.0 is Running...\n");while(_SHUTDOWN){Addrlen=sizeof(clientAddr);if((client_fd=accept(server_fd,(struct sockaddr*)&clientAddr,&Addrlen))>0){bzero(Result,sizeof(Result));bzero(client_ip,sizeof(client_ip));inet_ntop(AF_INET,&clientAddr.sin_addr.s_addr,client_ip,_IPSIZE);printf("Connection From :IP[%s],PORT[%d]\n",client_ip,ntohs(clientAddr.sin_port));sprintf(Result,"Hi [%s] Welcome to my TCP test server!service version 1.1.0...",client_ip);send(client_fd,Result,strlen(Result),0);close(client_fd);}else{perror("accpet failed");close(server_fd);exit(0);}}close(server_fd);return 0;
}

客户端:

客户端是运行在本地上的虚拟机镜像

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>//客户端源码编写,连接服务器成功,服务器反馈信息#define _IP "xxx.xxx.xxx.xxx"
#define _PORT 8080
int main()
{struct sockaddr_in ServerAddr;bzero(&ServerAddr,sizeof(ServerAddr));ServerAddr.sin_family=AF_INET;ServerAddr.sin_port=htons(_PORT);inet_pton(AF_INET,_IP,&ServerAddr.sin_addr.s_addr);int Myfd=socket(AF_INET,SOCK_STREAM,0);//看需求决定是否要绑定char Response[1024];//存放服务端反馈信息ssize_t recvlen;bzero(Response,sizeof(Response));if((connect(Myfd,(struct sockaddr *)&ServerAddr,sizeof(ServerAddr)))==0){if((recvlen=recv(Myfd,Response,sizeof(Response),0))>0){printf("%s\n",Response);}}else{printf("Connect failed\n");close(Myfd);exit(0);}close(Myfd);printf("Client is Over\n");return 0;
}

运行结果:

函数二次包裹

在我们编写代码时,通常需要根据函数的返回值来判断函数调用情况,这个过程需要大量的if else语句,减少了代码阅读的简洁性。所以为了方便我们阅读,需要对函数进行二次包裹。

什么是二次包裹?

在自定义的头文件中重新声明一个函数,函数名与接口函数不同,返回值、参数均与接口函数相同。在相应的源文件中定义我们的函数,将逻辑判断的过程放在函数中。这样在调用函数时就省去大量的if else判断

#ifndef __MySock_H__
#define __MySock_H__
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>int SOCKET(int domain,int type,int protocol);
int BIND(int sockfd,struct sockaddr* addr,socklen_t addrlen);
ssize_t RECV(int sockfd,void *buf,size_t len,int flags);
ssize_t SEND(int sockfd,void *buf,size_t len,int flags);
int CONNECT(int sockfd,struct sockaddr *addr,socklen_t addrlen);
int ACCEPT(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
int LISTEN(int sockfd,int backlog);#endif
#include "MySock.h"
int SOCKET(int domain,int type,int protocol)
{int reval=socket(domain,type,protocol);    if(reval==-1){perror("socket call failed");   exit(0);}return reval;
}
int BIND(int sockfd,struct sockaddr* addr,socklen_t addrlen)
{int reval=bind(sockfd,addr,addrlen);if(reval==-1){perror("bind call failed");exit(0);}return reval;
}
ssize_t RECV(int sockfd,void *buf,size_t len,int flags)
{ssize_t reval;reval=recv(sockfd,buf,len,flags);if(reval==0)perror("recv call failed");return reval;
}
ssize_t SEND(int sockfd,void *buf,size_t len,int flags)
{ssize_t reval;reval=send(sockfd,buf,len,flags);if(reval==-1)perror("send call failed");return reval;
}
int CONNECT(int sockfd,struct sockaddr *addr,socklen_t addrlen)
{int reval=connect(sockfd,addr,addrlen);if(reval==-1){perror("connect call failed");exit(0);}return reval;
}int ACCEPT(int sockfd,struct sockaddr* addr,socklen_t *addrlen)
{int reval=accept(sockfd,addr,addrlen);if(reval==-1){perror("accept call failed");exit(0);}return reval;
}
int LISTEN(int sockfd,int backlog)
{int reval=listen(sockfd,backlog);if(reval==-1){perror("listen call failed");exit(0);}return reval;
}

使用包裹后的函数对我们TCP通信的客户端进行改写:

代码看起来简洁多了

#include "MySock.h"//客户端源码编写,连接服务器成功,服务器反馈信息#define _IP "xxx.xxx.xxx.xxx"
#define _PORT 8080
int main()
{struct sockaddr_in ServerAddr;bzero(&ServerAddr,sizeof(ServerAddr));ServerAddr.sin_family=AF_INET;ServerAddr.sin_port=htons(_PORT);inet_pton(AF_INET,_IP,&ServerAddr.sin_addr.s_addr);int Myfd=SOCKET(AF_INET,SOCK_STREAM,0);//看需求决定是否要绑定char Response[1024];//存放服务端反馈信息ssize_t recvlen;bzero(Response,sizeof(Response));if((CONNECT(Myfd,(struct sockaddr *)&ServerAddr,sizeof(ServerAddr)))==0){if((recvlen=recv(Myfd,Response,sizeof(Response),0))>0){printf("%s\n",Response);}}close(Myfd);printf("Client is Over\n");return 0;
}

相关文章:

【Linux】Linux下使用套接字进行网络编程

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 ​ 用于网络应用开…...

强化学习-Q-learning、SARSA和PPO等算法

强化学习 强化学习是一种机器学习方法&#xff0c;它关注智能体如何通过与环境的交互来最大化期望的累积奖励。在这个过程中&#xff0c;智能体不断尝试不同的行为策略&#xff0c;并根据结果调整策略&#xff0c;以提高长期的性能。以下是几种常见的强化学习算法&#xff1a;…...

HarmonyOS SDK助力鸿蒙原生应用“易感知、易理解、易操作”

6月21-23日&#xff0c;华为开发者大会&#xff08;HDC 2024&#xff09;盛大开幕。6月23日上午&#xff0c;《HarmonyOS开放能力&#xff0c;使能应用原生易用体验》分论坛成功举办&#xff0c;大会邀请了多位华为技术专家深度解读如何通过根技术、开放能力、场景化控件等亮点…...

Java基础入门day72

day72 mybatis mybatis的实现方式 三种实现方式&#xff1a; 纯xml方式&#xff0c;namespace随便写&#xff0c;id随便写&#xff0c;只要保证整个项目namespaceid唯一即可 xml接口的方式&#xff0c;namespace必须是接口的全路径&#xff0c;id必须是接口的方法名&#xf…...

文本编辑命令和正则表达式

一、 编辑文本的命令 正则表达式匹配的是文本内容&#xff0c;Linux的文本三剑客&#xff0c;都是针对文本内容。 文本三剑客 grep&#xff1a;过滤文本内容 sed&#xff1a;针对文本内容进行增删改查 &#xff08;本文不相关&#xff09; awk&#xff1a;按行取列 &#x…...

云手机群控功能讲解

接触云手机之前&#xff0c;很多企业或者个人卖家都对群控有浓厚的兴趣&#xff0c;云手机群控具体是什么呢&#xff1f;云手机群控&#xff0c;顾名思义&#xff0c;是指能够同时对多台云手机进行集中控制和管理的功能。打破了传统单台手机操作的限制&#xff0c;实现了规模化…...

gdb用法

创建文件 // main.cpp文件 // 稳态误差 void pid_test_wentaiwucha() {float p 1.5;int t 1; // t 1s;int target 5; // 5m/sfloat output 0;float radis 3; // 稳态误差std::cout << "output: " << std::endl;fo…...

聊一聊UDF/UDTF/UDAF是什么,开发要点及如何使用?

背景介绍 UDF来源于Hive&#xff0c;Hive可以允许用户编写自己定义的函数UDF&#xff0c;然后在查询中进行使用。星环Inceptor中的UDF开发规范与Hive相同&#xff0c;目前有3种UDF&#xff1a; A. UDF--以单个数据行为参数&#xff0c;输出单个数据行&#xff1b; UDF&#…...

配置Nginx二级域名

一、环境 &#xff08;一&#xff09;配置 1.服务器 linux CentOS 2.反向代理 Nginx 3.开放端口 云服务器开放端口80和443 二、域名备案 &#xff08;一&#xff09;腾讯云 1.腾讯云域名备案流程 备注&#xff1a;一级域名备案后&#xff0c;二级域名可以不用再备案&a…...

LeetCode——判断回文数

给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 例如&#xff0c;121 是回文&#xff0c;而 …...

shell:使用结构化语句(for、while循环)

1. for命令 下面是bash shell中for命令的基本格式。 for var in list docommands done每次for命令遍历值列表&#xff0c;它都会将列表中的下个值赋给$test变量。$test变量可以像for 命令语句中的其他脚本变量一样使用。在最后一次迭代后&#xff0c;$test变量的值会在shell脚…...

数据结构_绪论

1.数据结构的研究内容 研究数据的特性和数据之间的关系 用计算机解决一个问题的步骤 1.具体问题抽象成数学模型 实质: 分析问题--->提取操作对象--->找出操作对象之间的关系(数据结构)--->用数学语言描述 操作对象对象之间的关系 2.设计算法 3.编程,调试,运行 …...

AI自动生成角色和情节连续的漫画,中山大学联想提出AutoStudio,可以多轮交互式连续生成并保持主题一致性。

中山大学和联想研究院提出AutoStudio: 是一种无需训练的多代理框架&#xff0c;用于多轮交互式图像生成&#xff0c;能够在生成多样化图像的同时保持主体一致性。 AutoStudio 采用三个基于 LLM 的智能体来解释人类意图并为 SD 模型生成适当的布局指导。此外&#xff0c;还引入…...

【经典面试题】RabbitMQ如何防止重复消费?

RabbitMQ的消息消费是有确认机制的&#xff0c;正常情况下&#xff0c;消费者在消费消息成功后&#xff0c;会发送一个确认消息&#xff0c;消息队列接收到之后&#xff0c;就会将该消息从消息队列中删除&#xff0c;下次也就不会再投递了。 但是如果存在网络延迟的问题&#…...

如何自己录制教学视频?零基础也能上手

随着在线教育的蓬勃发展&#xff0c;录制教学视频成为了教师和教育工作者们不可或缺的一项技能。无论是为了远程教学、课程分享还是知识普及&#xff0c;教学视频的录制都变得愈发重要。可是如何自己录制教学视频呢&#xff1f;本文将介绍两种录制教学视频的方法&#xff0c;这…...

【android】用 ExpandableListView 来实现 TreeView树形菜单视图

使用 ExpandableListView 来实现 TreeView 创建一个 ExpandableListAdapter 来为其提供数据。以下演示了如何使用 ExpandableListView 来展示树形结构的数据&#xff1a; 首先&#xff0c;在布局文件中添加 ExpandableListView&#xff1a; <ExpandableListViewandroid:i…...

策略模式与函数式编程应用

策略模式 | 单一职责原则&#xff08;Single Responsibility Principle, SRP&#xff09;&#xff1a;islenone和islentwo分别根据特定条件返回电话号码 函数式编程&#xff1a; ‘’ if pd.isna(self.note1) else len(re.findall(r’\d, self.note1)) 重复代码&#xff1a; 当…...

docker原理记录C-N-A

docker原理 容器技术的兴起源于 PaaS 技术的普及 Docker 项目通过“容器镜像”&#xff0c;解决了应用打包这个根本性难题容器本身没有价值&#xff0c;有价值的是“容器编排”Cgroups 和 Namespace Cgroups 技术是用来制造约束的主要手段&#xff0c;而Namespace 技术则是用…...

【LeetCode】每日一题:二叉树的层次遍历

给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 解题思路 水题 AC代码 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightN…...

单体架构改造为微服务架构之痛点解析

1.微服务职责划分之痛 1.1 痛点描述 微服务的难点在于无法对一些特定职责进行清晰划分&#xff0c;比如某个特定职责应该归属于服务A还是服务B? 1.2 为服务划分原则的痛点 1.2.1 根据存放主要数据的服务所在进行划分 比如一个能根据商品ID找出商品信息的接口&#xff0c;把…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...