Linux下Socket编程
1. Socket简介
- Socket是什么?
- Socket是一种进程间通信的机制,通过它应用程序可以通过网络进行数据传输。Socket提供了一种跨平台的接口,使得同样的代码可以在不同的操作系统上运行。
- Socket类型
- 流式套接字(SOCK_STREAM): 基于TCP协议,提供可靠的双向字节流通信。
- 数据报套接字(SOCK_DGRAM): 基于UDP协议,提供不可靠的、无连接的通信。
- 原始套接字(SOCK_RAW): 允许直接访问底层协议,主要用于协议开发或网络分析工具。
2. Socket编程流程
-
创建Socket
int socket(int domain, int type, int protocol);- domain: 协议族,常用的有
AF_INET(IPv4) 和AF_INET6(IPv6)。 - type: 套接字类型,如
SOCK_STREAM和SOCK_DGRAM。 - protocol: 通常设为
0,表示由系统自动选择合适的协议。
- domain: 协议族,常用的有
-
绑定Socket
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);- 将Socket与指定的IP地址和端口绑定。
-
监听连接
int listen(int sockfd, int backlog);- 服务器端Socket进入监听模式,
backlog指定队列中允许的最大未处理连接数。
- 服务器端Socket进入监听模式,
-
接受连接
int accept(int sockfd, struct sockaddr *addr,socklen_t *addrlen);- 接受客户端的连接请求,创建一个新的Socket用于与客户端通信。
-
连接到服务器
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);- 客户端Socket使用此函数连接到服务器。
-
发送和接收数据
- 发送数据:
ssize_t send(int sockfd, const void *buf, size_t len,int flags); - 接收数据:
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
- 发送数据:
-
关闭Socket
int close(int sockfd);
3. 常用API详解
-
socket()
- 功能: 创建一个新的Socket。
- 参数:
domain: 地址族,常用的如AF_INET表示IPv4地址。type: Socket类型,SOCK_STREAM或SOCK_DGRAM。protocol: 协议编号,通常为0,由系统选择默认协议。
- 返回值: 返回新的文件描述符,失败返回
-1。
-
bind()
- 功能: 将Socket绑定到特定的IP地址和端口。
- 参数:
sockfd: 由socket()创建的文件描述符。addr: 结构体指针,包含要绑定的地址信息。addrlen:addr的长度。
-
listen()
- 功能: 在Socket上监听连接请求。
- 参数:
sockfd: 由socket()创建的文件描述符。backlog: 未处理连接的最大数量。
-
accept()
- 功能: 接受连接请求,创建用于通信的新Socket。
- 参数:
sockfd: 监听套接字。addr: 客户端的地址信息结构体。addrlen:addr的长度。
-
connect()
- 功能: 客户端使用此函数连接到服务器。
- 参数:
sockfd: 由socket()创建的文件描述符。addr: 服务器的地址信息。addrlen:addr的长度。
- 返回值: 成功返回
0,失败返回-1。
-
send() 和 recv()
send()用于向对方发送数据,recv()用于接收数据。- 参数:
sockfd: 通信的套接字。buf: 数据缓冲区。len: 缓冲区的大小。flags: 标志位,一般为0。
4. 错误处理
在Socket编程中,经常会遇到错误。通常的做法是检查函数的返回值,若为 -1 则出错,并通过 errno 查看具体的错误原因。以下是一些常见的错误:
EADDRINUSE: 地址已被使用。EADDRNOTAVAIL: 无效的地址。ECONNREFUSED: 连接被拒绝。ETIMEDOUT: 连接超时。
5. 高级特性
- 非阻塞I/O: 使用
fcntl()设置Socket为非阻塞模式。 - 多路复用: 使用
select()或poll()等函数同时监听多个Socket。
6. 示例代码
服务器端
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int clientFd;
int serverFd;
void hand(int s){if(2 == s){//7 断开连接close(clientFd);close(serverFd);printf("bye bye 了勾八!\n");exit(1);}
}int main(){signal(2,hand);//1 创建socketserverFd = socket(AF_INET,SOCK_STREAM,0);if(-1 == serverFd) printf("创建socket失败:%m!\n"),exit(-1);printf("创建socket成功!\n");//2 协议地址簇struct sockaddr_in addr={0};addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr("127.0.0.1");//ip地址 注意字符串转网络字节序addr.sin_port = htons(8888);//端口号 用1W左右的 //3 绑定int r = bind(serverFd,(struct sockaddr*)&addr,sizeof addr); if(-1 == r) printf("绑定失败:%m!\n"),close(serverFd),exit(-1);printf("绑定成功!\n");//4 监听r = listen(serverFd,100);//最大容量为100if(-1 == r) printf("监听失败:%m!\n"),close(serverFd),exit(-1);printf("监听成功!\n");//5 接受客户端连接struct sockaddr_in cAddr = {0};//用来接收客户端的协议地址簇int len = sizeof cAddr;clientFd = accept(serverFd,(struct sockaddr*)&cAddr,&len);if(-1 == clientFd) printf("服务器崩溃:%m\n"),close(serverFd),exit(-1);printf("接受客户端连接成功:%d %s %u\n",clientFd,inet_ntoa(cAddr.sin_addr),cAddr.sin_port);//6 通信char buff[1024];int n=0;char temp[1024];while(1){r = recv(clientFd,buff,1023,0);if(r > 0) {buff[r] = '\0';//添加字符串结束符号 '\0'printf("%d:%s\n",r,buff);sprintf(temp,"%d-%s",n++,buff);send(clientFd,temp,strlen(temp),0);}}
}
客户端
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int fd;
void hand(int s){if(2 == s){//5 断开连接close(fd);printf("bye bye !\n");exit(1);}
}int main(){signal(2,hand);//1 创建socketfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == fd) printf("创建socket失败:%m!\n"),exit(-1);printf("创建socket成功!\n");//2 协议地址簇struct sockaddr_in addr={0};addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr("127.0.0.1");//ip地址 注意字符串转网络字节序addr.sin_port = htons(8888);//端口号 用1W左右的 大小端转换//3 连接服务器int r = connect(fd,(struct sockaddr*)&addr,sizeof addr);if(-1 == r) printf("连接服务器失败:%m!\n"),exit(-1);printf("连接服务器成功!\n");//4 通信char buff[1024];char temp[1024];while(1){printf("请输入要发送给服务器的数据:");scanf("%s",buff);r = send(fd,buff,strlen(buff),0);printf("发送%d字节数据到服务器!\n",r);r = recv(fd,temp,1023,0);if(r>0){temp[r] = '\0';printf("服务器回复:%s\n",temp);}}
}
7. 结论
Socket编程是网络通信的基础,通过了解各种Socket API的使用,可以实现复杂的网络应用程序。在实际编程中,掌握错误处理和高级特性如非阻塞I/O和多路复用是非常重要的。
相关文章:
Linux下Socket编程
1. Socket简介 Socket是什么? Socket是一种进程间通信的机制,通过它应用程序可以通过网络进行数据传输。Socket提供了一种跨平台的接口,使得同样的代码可以在不同的操作系统上运行。Socket类型 流式套接字(SOCK_STREAM࿰…...
Scrapy 爬虫的大模型支持
使用 Scrapy 时,你可以轻松使用大型语言模型 (LLM) 来自动化或增强你的 Web 解析。 有多种使用 LLM 来帮助进行 Web 抓取的方法。在本指南中,我们将在每个页面上调用一个 LLM,从中抽取我们定义的一组属性,而无需编写任何选择器或…...
数据仓库简介(一)
数据仓库概述 1. 什么是数据仓库? 数据仓库(Data Warehouse,简称 DW)是由 Bill Inmon 于 1990 年提出的一种用于数据分析和挖掘的系统。它的主要目标是通过分析和挖掘数据,为不同层级的决策提供支持,构成…...
Kafka和RabbitMQ区别
RabbitMQ的消息延迟是微秒级,Kafka是毫秒级(1毫秒1000微秒) 延迟消息是指生产者发送消息发送消息后,不能立刻被消费者消费,需要等待指定的时间后才可以被消费。 Kafka的单机呑吐量是十万级,RabbitMQ是万级…...
go-zero学习
go-zero官网: https://go-zero.dev/docs/tasks 好文: https://blog.csdn.net/m0_63629756/article/details/136599547 视频: https://www.bilibili.com/video/BV18JxUeyECg 微服务基础 根目录下,一个文件夹就是一个微服务。如果微…...
python如何查询函数
1、通用的帮助函数help() 使用help()函数来查看函数的帮助信息。 如: import requests help(requests) 会有类似如下输出: 2、查询函数信息 ★查看模块下的所有函数: dir(module_name) #module_name是要查询的函数名 如: i…...
计算机视觉与深度学习 | 从激光雷达数据中提取地面点和非地面点(附matlab代码)
===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 激光雷达数据 使用velodyneFileReader函数从P...
vulnhub-wakanda 1靶机
vulnhub:wakanda: 1 ~ VulnHub 导入靶机,放在kali同网段,扫描 靶机在192.168.81.5,扫描端口 四个端口,详细扫描一下 似乎没什么值得注意的,先看网站 就这一个页面,点按钮也没反应,扫…...
Bilibili视频如何保存到本地
Bilibili(哔哩哔哩)作为中国领先的视频分享平台之一,汇聚了大量的优质内容,从搞笑动画、综艺节目到专业教程,应有尽有。许多用户时常会遇到这样的需求:希望将视频保存到本地,方便离线观看或者保存珍藏。由于版权保护等…...
C++之多线程
前言 多线程和多进程是并发编程的两个核心概念,它们在现代计算中都非常重要,尤其是在需要处理大量数据、提高程序性能和响应能力的场景中。 多线程的重要性: 资源利用率:多线程可以在单个进程中同时执行多个任务,这可以更有效地利用CPU资源,特别是在多核处理器上。 性…...
《C++音频降噪秘籍:让声音纯净如初》
在音频处理领域,降噪是一项至关重要的任务。无论是录制音乐、语音通话还是音频后期制作,都需要有效地去除背景噪声,以获得清晰、纯净的音频效果。在 C中实现高效的音频降噪处理,可以为音频应用带来更高的质量和更好的用户体验。本…...
C(十)for循环 --- 黑神话情景
前言: "踏过三界宝刹,阅过四洲繁华。笑过五蕴痴缠,舍过六根牵挂。怕什么欲念不休,怕什么浪迹天涯。步履不停,便是得救之法。" 国际惯例,开篇先喝碗鸡汤。 今天,杰哥写的 for 循环相…...
记录一次docker报错无法访问文件夹,权限错误问题
记录一次docker报错无法访问文件夹,权限错误问题 1. 背景 使用docker安装photoview,为其分配了一个cache目录,用户其缓存数据。在运行过程中,扫描文件后显示如下错误 could not make album image cache directory: mkdir /app/c…...
react crash course 2024(8) useEffect
引入 import { useEffect } from react; useEffect – React 中文文档useEffect 是一个 React Hook,它允许你 将组件与外部系统同步。 有些组件需要与网络、某些浏览器 API 或第三方库保持连接,当它们显示在页面上时。这些系统不受 React 控制࿰…...
GEE开发之Modis_NDWI数据分析和获取
GEE开发之Modis_NDWI数据分析和获取 0 数据介绍NDWI介绍MOD09GA介绍 1 NDWI天数据下载2 NDWI月数据下载3 NDWI年数据下载 前言:本文主要介绍Modis下的NDWI数据集的获取。归一化差异水指数 (NDWI) 对植被冠层液态水含量的变化很敏感。它来自近红外波段和第二个红外波…...
netty之NettyClient半包粘包处理、编码解码处理、收发数据方式
前言 Netty开发中,客户端与服务端需要保持同样的;半包粘包处理,编码解码处理、收发数据方式,这样才能保证数据通信正常。在前面NettyServer的章节中我们也同样处理了;半包粘包、编码解码等,为此在本章节我们…...
Linux:文件描述符介绍
文章目录速览 1、虚拟地址空间(1)What(什么是虚拟地址空间)(2)Why(为什么需要虚拟地址空间) 2、文件描述符(1)What(什么是文件描述符)(2)文件描述符表 1、虚拟地址空间 (1)What(什么是虚拟地址…...
stm32f103调试,程序与定时器同步设置
在调试定时器相关代码时,注意到定时器的中断位总是置1,怀疑代码有问题,经过增大定时器的中断时间,发现定时器与代码调试并不同步,这一点对于调试涉及定时器的代码是非常不利的,这里给出keil调试stm32使定时…...
《Python编程:从入门到实践》数据可视化
一、项目 数据可视化学习 二、库依赖 matplotlib,pygal, 三、生成数据 1.绘制简单的折线图 import matplotlib.pyplot as pltsquares [1, 4, 9, 16, 25] plt.plot(squares) plt.show() 模块pyplot包含很多用于生成图表的函数。 (1&am…...
github/git密钥配置与使用
零、前言 因为要在ubuntu上做点东西,发现git clone 的时候必须输账户密码,后来发现密码是token,但是token一大串太烦了,忙了一天发现可以通过配置 公钥 来 替代 http 的 部署方式。 一、生成 ssh 密钥对 我们先测试下能不能 连接…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...
