Linux下异步socket客户端

news2025/9/14 0:54:15

文章目录

  • socket 客户端
    • 1. 创建socket
      • socket()函数
      • 返回值
    • 2. 设置socket的属性
    • connect函数
      • sockaddr_in结构体
      • inet_pton函数
    • 3. fcntl设置非阻塞
    • 4. recv函数

socket 客户端

在这里插入图片描述

1. 创建socket

socket()函数

#include <sys/socket.h>
int socket(int domain, int type, int protocol)

// 实例: IPv4 与字节流的默认的协议,一般为 TCP
int sockfd=socket(AF_INET,SOCK_STREAM,0);
  • domain:一个地址描述。支持AF_INET格式,也就是说ARPA Internet地址格式。

    • AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址
    • AF_INET6 与上面类似,不过是来用IPv6的地址
    • AF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用
  • type:指定socket类型。新套接口的类型描述类型,如:

    • TCP(SOCK_STREAM)UDP(SOCK_DGRAM)

    • 常用的socket类型还有SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。

    • SOCK_STREAM 提供有序的、可靠的、双向的和基于连接的字节流,使用带外数据传送机制,为Internet地址族使用TCP

    • SOCK_DGRAM 支持无连接的、不可靠的和使用固定大小(通常很小)缓冲区的数据报服务,为Internet地址族使用UDP

  • protocol:就是指定协议。套接口所用的协议。如调用者不想指定,可用0。常用的协议有:

    • IPPROTO_TCP(TCP传输协议)
    • IPPROTO_UDP(UDP传输协议)
    • IPPROTO_STCP(STCP传输协议)
    • IPPROTO_TIPC(TIPC传输协议)

    SOCK_STREAM类型的套接口为全双向的字节流。对于流类套接口,在接收或发送数据前必需处于已连接状态。用connect()调用建立与另一套接口的连接,连接成功后,即可用send()和recv()传送数据。当会话结束后,调用closesocket()。带外数据根据规定用send()和recv()来接收。
    实现SOCK_STREAM类型套接口的通讯协议保证数据不会丢失也不会重复。如果终端协议有缓冲区空间,且数据不能在一定时间成功发送,则认为连接中断,其后续的调用也将以WSAETIMEOUT错误返回。
    SOCK_DGRAM类型套接口允许使用sendto()和recvfrom()从任意端口发送或接收数据报。如果这样一个套接口用connect()与一个指定端口连接,则可用send()和recv()与该端口进行数据报的发送与接收。

返回值

返回值:socket的编号,为-1表示失败,成功为一个大于0的数字。

socket返回的值是一个文件描述符SOCKET类型本身也是定义为int的,既然是文件描述符,那么在系统中都当作是文件来对待的,0,1,2分别表示标准输入、标准输出、标准错误。所以其他打开的文件描述符都会大于2, 错误时就返回 -1. 这里INVALID_SOCKET 也被定义为 -1

2. 设置socket的属性

setsockopt函数原型:

int setsockopt( int socket, int level, int option_name,const void *option_value, size_t ,ption_len);

功能:设置一个套接字的选项(属性)
第一个参数socket是套接字描述符。
第二个参数level是被设置的选项的级别,如果想要在套接字级别上设置选项,就必须把level设置为 SOL_SOCKET。option_name指定准备设置的选项,option_name可以有哪些取值,这取决于level,在套接字级别上(SOL_SOCKET),option_name可以有以下取值:

  • SO_RCVTIMEO,设置接收超时时间,该选项最终将接收超时时间赋给sock->sk->sk_rcvtimeo。
  • SO_SNDTIMEO,设置发送超时时间,该选项最终将发送超时时间赋给sock->sk->sk_sndtimeo。
int nNetTimeout=5000;//5秒
//发送时限
setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char*)&nNetTimeout,sizeof(int));
//接收时限
setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char*)&nNetTimeout,sizeof(int)); 
  • SO_REUSEADDR,打开或关闭地址复用功能。
    此参数经常用于当socket正在关闭,处于TIME_WAIT的状态,而此时你又想继续重用该socket,你可以私用此参数,否则你在调用bind接口的时候会出现bind failed: Address already in use
BOOL bReuseaddr=TRUE;
setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); 

connect函数

功能:将socket客户端连接到服务端的某个IP地址或端口号即可用connect函数

//函数原型
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

//实例
struct sockaddr_in servaddr;
memset(&servaddr, '\0', sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(server_port);  // 标注服务器的端口
inet_pton(AF_INET, server_ip, &servaddr.sin_addr); //通过IP地址连接服务器

int con_tab= connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
  • sockdf:socket文件描述符

  • addr:传入参数,指定服务器端地址信息,含IP地址和端口号

  • addrlen:传入参数,传入sizeof(addr)大小

  • 返回值:成功返回0,失败返回-1,设置errno

  • connect 函数将激发 TCP 的三次握手过程,而且仅在连接建立成功或出错时才返回。其中出错返回可能有以下几种情况:

    • 三次握手无法建立,客户端发出的 SYN 包没有任何响应,于是返回 TIMEOUT 错误。这种情况比较常见的原因是对应的服务端 IP 写错

    • 客户端收到了 RST(复位)回答,这时候客户端会立即返回 CONNECTION REFUSED 错误。这种情况比较常见于客户端发送连接请求时的请求端口写错,因为 RST 是 TCP 在发生错误时发送的一种 TCP 分节。产生 RST 的三个条件是:目的地为某端口的 SYN 到达,然而该端口上没有正在监听的服务器(如前所述);TCP 想取消一个已有连接;TCP 接收到一个根本不存在的连接上的分节。

    • 客户发出的 SYN 包在网络上引起了"destination unreachable",即目的不可达的错误。这种情况比较常见的原因是客户端和服务器端路由不通

sockaddr_in结构体

sockaddr_in 是一个 C 语言中的结构体,用于存储 IPv4 套接字地址。它包含了以下成员变量:
sockaddr_in所在在头文件#include<netinet/in.h>或#include <arpa/inet.h>

struct sockaddr_in
{
	sa_family_t sin_family;   //地址族
	uint16_t sin_port;     //端口号
	struct in_addr sin_addr;  //32位IP地址
	char sin_zero;      //预留未使用
};
sin_family:地址族,通常设置为 AF_INET
sin_port:端口号,使用网络字节序
sin_addr:IP 地址,使用 in_addr 结构体存储
sin_zero:填充字段,保证 sockaddr_in 结构体与 sockaddr 结构体大小相同 它通常用于设置套接字地址或者接收套接字地址。

sockaddr_in和sockaddr的区别:
使用sockaddr_in设置端口、IP地址以及地址属性等参数,而不是直接使用sockaddr结构体,因为这个结构体是操作系统内核调用的,对于程序员来说不应该是透明的。所以一般的做法是我们设置好sockaddr_in结构体,然后将其显示转换为sockaddr。

inet_pton函数

头文件:#include<arpa/inet.h>
inet_pton 和 inet_ntop 这 2 个函数能够处理 ipv4 和 ipv6
inet_pton() 转换网络主机地址ip(如192.168.1.10)为二进制数值,并存储在struct in_addr结构中

#include<arpa/inet.h>
struct sockaddr_in servaddr;
inet_pton(AF_INET, 10.168.248.245, &servaddr.sin_addr); 

3. fcntl设置非阻塞

fcntl - 对一个打开的文件描述符执行一系列控制操作。
fcntl() 对打开的文件描述符fd执行下面操作之一。操作由cmd决定

int func()
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    int flag = fcntl(fd,F_GETFL,0);//获取文件fd当前的状态
    //int flag = fcntl(fd,F_GETFL);//不用第3个参数也可以
    if(flag<0)
    {
        perror("fcntl F_GETFL fail"); 
        close(fd); 
        return -1; 
    }
    if (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0)//设置为非阻塞态
     {  
        perror("fcntl F_SETFL fail"); 
        close(fd);
        return -1; 
    }
}
-----------------------------------------
#include <fcntl.h>
int sockfd
int flags;
flags= fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

4. recv函数

  • 功能:接收服务店或订阅的IP/端口号发过来的数据
int recv( SOCKET s, char *buf, int len, int flags);

参数一:指定接收端套接字描述符;
参数二:指向一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
参数三:指明buf的长度;
参数四:一般置为0;

  • 返回值:异步与同步的返回值没有区别
    • 成功:>0,返回值大于0,返回值为读取到的字节数。
    • 返回值=0,表示另一端关闭了socket
    • 返回值= -1 错误,需要获取错误码errno
int read_tab;
unsigned char data[10000];
read_tab= recv(sockfd, data, 10000,0);

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

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

相关文章

四、线程安全,synchronized,volatile(JMM)【4/12 5/12 6/12】【多线程】

4. 多线程带来的的风险-线程安全 (重点) 4.1 观察线程不安全 static class Counter {public int count 0;void increase() {count;} } public static void main(String[] args) throws InterruptedException {final Counter counter new Counter();Thread t1 new Thread(()…

数据结构——排序(4)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年4月12日 内容&#xff1a;数据结构排序内容讲解 目录 前言&#xff1a; 1.快速排序中的递归&#xff1a; 2.小区间优化&#xff1a; 3.递归改非递归&#xff1a; 4.归并排序&#xff1a; 5.归并排序的非递归形式&…

Revit中如何绘制倾斜的屋顶及一键成板?

Revit中如何绘制倾斜的屋顶&#xff1f;如下图所示&#xff0c;像这种坡屋顶有两种方法进行绘制。 第一种&#xff1a;定义坡度。 1、点击建筑选项卡中的屋顶按钮。选择使用矩形工具。 2、在选项栏中&#xff0c;偏离值修改为500&#xff0c;把屋顶迹线绘制出来。 3、取消这三…

软件测试今天你被内卷了吗?

认识一个人&#xff0c;大专学历非计算机专业的&#xff0c;是前几年环境好的时候入的行&#xff0c;那时候软件测试的要求真的很低&#xff0c;他那时好像是报了个班&#xff0c;然后入门的&#xff0c;但学的都是些基础&#xff0c;当时的他想的也简单&#xff0c;反正也能拿…

【面试】限流算法有哪些?

文章目录前言1.固定窗口限流算法1.2 固定窗口限流的伪代码实现1.2 固定窗口算法的优缺点2.漏桶算法3.令牌桶算法4. 滑动窗口限流算法4.1 什么是滑动窗口限流算法4.2 滑动窗口限流算法的伪代码实现4.3 滑动窗口限流算法的优缺点漏桶算法 VS 令牌桶算法总结参考 & 鸣谢前言 …

docker项目实施

鲲鹏916架构openEuler-arm64成功安装docker并跑通tomcat容器_闭关苦炼内功的技术博客_51CTO博客鲲鹏916架构openEuler-arm64成功安装docker并跑通tomcat容器&#xff0c;本文是基于之前这篇文章鲲鹏920架构arm64版本centos7安装docker下面开始先来看下系统版本卸载旧版本旧版本…

刘二大人《Pytorch深度学习实践》第八讲加载数据集

文章目录Epoch、Batch-Size、IterationsDataset、DataLoader课上代码torchvision中数据集的加载Epoch、Batch-Size、Iterations 1、所有的训练集进行了一次前向和反向传播&#xff0c;叫做一个Epoch 2、在深度学习训练中&#xff0c;要给整个数据集分成多份&#xff0c;即mini-…

【密码学】ElGamal加密算法原理 以及 例题讲解

目录前言1. 原理2. 例题2.1 例题一2.2 例题二前言 具体的性质&#xff1a; 非对称加密算法应用于一些技术标准中&#xff0c;如数字签名标准&#xff08;DSS&#xff09;、S/MIME 电子邮件标准算法定义在任何循环群 G 上&#xff0c;安全性取决于 G 上的离散对数难题 1. 原理…

元宇宙地产暴跌,林俊杰亏麻了

文/章鱼哥出品/陀螺财经随着元宇宙的兴起&#xff0c;元宇宙地产曾一度被寄予厚望&#xff0c;成为各大投资者追捧的对象。然而&#xff0c;最近的一次元宇宙地产价值暴跌再次提醒我们&#xff0c;高收益背后可能伴随着高风险。根据元宇宙分析平台WeMeta的数据显示&#xff0c;…

400以内的蓝牙耳机哪款好?400以内蓝牙耳机排行榜

谈起TWS&#xff0c;无论是传统的音频厂商还是手机厂商&#xff0c;都是其不可或缺的重要产品线&#xff0c;现在很多许多蓝牙耳机都不是千篇一律得形状&#xff0c;市场也鲜有商家在外观上下功夫&#xff0c;下面分享几款400元以内&#xff0c;内外兼具的耳机品牌。 一、南卡…

Spring boot+Vue3博客平台:修改密码与找回密码的设计与实现

修改密码与找回密码功能的设计与实现涉及到前后端的配合。本文将详细介绍如何通过设计思路、技术实现和代码示例实现这两个功能。 一、修改密码功能 设计思路 在设计修改密码功能时&#xff0c;需要注意以下几点&#xff1a; 用户输入的当前密码需要正确新密码需要满足一定的…

查询优化器:选择最优的查询路径

当我们通过解析器理解了SQL语句要干什么之后&#xff0c;接着会找查询优化器&#xff08;Optimizer&#xff09;来选择一个最优的查询路径。 可能有同学这里就不太理解什么是最优的查询路径了&#xff0c;这个看起来确实很抽象&#xff0c;当然&#xff0c;这个查询优化器的工…

总结819

学习目标&#xff1a; 4月&#xff08;复习完高数18讲内容&#xff0c;背诵21篇短文&#xff0c;熟词僻义300词基础词&#xff09; 第二周&#xff1a; 学习内容&#xff1a; 暴力英语&#xff1a;早上背诵《think different》记150词&#xff0c;默写了两篇文章&#xff0c…

BUUCTF-warmup_csaw_2016

1.checksec/file 64位的linux文件 2.ida 找到主函数 发现致命函数 get() 因为get可以无限输入 看看有没有什么函数我们可以返回的 双击进入sub_40060d 直接发现这个函数是取flag的 所以我们开始看这个函数的地址 所以函数地址是 0x40060d 我们看看get什么时候开始的 发现g…

Stable Diffusion复现——基于 Amazon SageMaker 搭建文本生成图像模型

众所周知&#xff0c;Stable Diffusion扩散模型的训练和推理非常消耗显卡资源&#xff0c;我之前也是因为资源原因一直没有复现成功。而最近我在网上搜索发现&#xff0c;亚马逊云科技最近推出了一个【云上探索实验室】刚好有复现Stable Diffusion的活动&#xff0c;其使用亚马…

超详细从入门到精通,pytest自动化测试框架实战-fixture高级进阶(十)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 1、fixture的autous…

jQuery+AJAX技术(简单的用户注册功能)

目录1、jQuery是什么&#xff1f;2、AJAX是什么&#xff1f;3、jQuery与AJAX的关系&#xff1f;使用jQuery实现AJAX示例&#xff1a;4、jQueryAJAX技术实现用户注册验证功能。1、jQuery是什么&#xff1f; jQuery 是一个快速&#xff0c;小型且功能丰富的JavaScript库。它使 诸…

gradle编译项目报错Execution failed for task ‘:bootJar‘,‘:mainClass‘,‘:compileJava‘.

目录1.问题2.问题查找3.更多1.问题 idea导入Gradle管理的SpeingBoot多模块项目&#xff0c;依赖下载不下来&#xff0c;执行编译报错 报错信息&#xff1a; 2.问题查找 首先怀疑是不是idea的版本与gradle版本冲突&#xff0c;我用的是idea2022.3.3&#xff0c;gradle是7.5.…

做一个内心强大的人

想想类似如下这种心灵鸡汤&#xff0c;本不太愿意在这个平台发布&#xff0c;但是偶尔喝点又何尝不可&#xff01; 语录摘抄/分享&#xff1a; 1、你开始炫耀自己&#xff0c;往往都是灾难的开始&#xff0c;就像老子在《道德经》里写到: 光而不耀&#xff0c;静水流深。 2、…

汽车电子相关术语介绍

一、相关术语介绍 1、汽车OTA 全称“Over-The-Air technology ”&#xff0c;即空中下载技术&#xff0c;通过移动通信的接口实现对软件进行远程管理&#xff0c;传统的做法到4S店通过整车OBD对相应的ECU进行软件升级。OTA技术最早2000年出现在日本&#xff0c;目前通过OTA方式…