网络编程 --------- 2、socket网络编程接口
1、什么是socket 套接字
socke套接字是一个编程的接口 (网络编程的接口)、是一种特殊的文件描述符 (read/write),不局限于TCP/IP 。socket是独立于具体协议的网络编程接口这个接口是位于 应用层和传输层之间 。
类型:
(1)流式套接字 SOCK_STREAM
面向字节流,针对于传输层协议为TCP的应用
(2)数据报套接字 SOCK_DGRAM
面向数据报,针对于传输层协议为UDP的应用
(3)原始套接字 SOCK_RAW
程序之间对ip层进行访问,跳过了传输层
2、基于TCP套接字的编程流程
Server ----- 服务器
socket ----- 创建套接字
bind (服务器的ip和端口) ------ 绑定服务器ip与端口
listen ---- 监听
accept ----- 接受连接请求
read/write ------- 读写
close ------ 关闭
Client ------- 客户端
socket
设置服务器的ip和端口
connect ------ 发出连接请求
write/read
close
3、socket套接字的接口函数
1)创建一个套接字 socket
NAME
socket - create an endpoint for communication
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
功能:创建一个套接字
参数:
domain:协议族
socket不局限于TCP/IP,它还可以指定其他的通信协议
AF_UNIX, AF_LOCAL Local communication unix(7)
AF_INET IPv4 Internet protocols ip(7)
AF_INET6 IPv6 Internet protocols
...
type:指定要创建的套接字类型
SOCK_STREAM 流式套接字 ---> TCP
SOCK_DGRAM 数据报套接字 ---> UDP
SOCK_RAW 原始套接字
...
protocol:协议,指定具体的应用层的协议
一般为 0 (不知名的私有协议)
返回值:
成功,返回一个套接字描述符 (>0)
失败,返回-1,同时errno被设置
例子: // 创建一个TCP流式套接字int sock_fd = socket( AF_INET, SOCK_STREAM, 0 ); if( sock_fd == -1 ){perror("socket error ");return -1;}printf("sock_fd = %d\n", sock_fd );
2) bind 绑定服务器的ip和端口
NAME
bind - bind a name to a socket
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:把一个地址绑定到套接字上
参数:
sockfd:指定要绑定的套接字描述符
addr:指向包含地址信息的 struct sockaddr 结构体的指针
addrlen:指定要绑定的地址结构体的长度,单位:字节
返回值:
成功,返回0
失败,返回-1,同时errno被设置
(2.1)网络地址结构体 (ip+端口)
socket接口可以用于 以太网(ipv4),也可以用于ipv6,....
不同的协议族,它们的地址是不一样的通用的地址结构体 所有的socket函数接口的 地址参数的类型都是 struct sockaddr {}
struct sockaddr
{
sa_family_t sa_family; //协议族
char sa_data[14]; //指定网络协议地址
}
==========================Internet协议地址结构体 ( man 7 ip 进行查看)struct sockaddr_in {sa_family_t sin_family; /* 协议族 in_port_t sin_port; /* 端口号 (网络字节序)struct in_addr sin_addr; /* ip地址};/* Internet address. */struct in_addr {uint32_t s_addr; /* ip地址(整数形式) };
(2.2)网络字节序
不同类型CPU的主机中,内存存储多字节整数序列 有两种方式:
大端模式
低地址存放数据的高位,高地址存放数据的低位 (和阅读习惯一致)
小端模式
低地址存放数据的低位,高地址存放数据的高位 (和阅读习惯相反)
网络字节序: 采用的是 大端模式
网络传输的数据必须按照网络字节序
注意:
大部分的主机上,当应用程序将多字节整数传递给socket之前,需要转换成网络字节序,当应用程序从socket上获取多字节整数时,需要转换成主机字节序 。
ps. 网络字节序的转换函数:
h host 主机字节序
n network 网络字节序
l long 32bits
s short 16bits
NAME
htonl, htons, ntohl, ntohs - convert values between host and network byte order
SYNOPSIS
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
功能:把一个32bits的整数的主机字节序 转换成 网络字节序
参数:
hostlong:指定要转换的32bits整数
返回值:
返回转换之后的结果
uint16_t htons(uint16_t hostshort);
功能:把一个16bits的整数的主机字节序 转换成 网络字节序
uint32_t ntohl(uint32_t netlong);
功能:把一个32bits的整数的网络字节序 转换成 主机字节序
uint16_t ntohs(uint16_t netshort);
功能:把一个16bits的整数的网络字节序 转换成 主机字节序
(2.3)ipv4地址之间的转换函数
NAME
inet_aton, inet_addr, inet_network, inet_ntoa - Internet address manipulation routines
SYNOPSIS
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
功能:把 ip地址(点分十进制字符串) 转换成 struct in_addr结构体类型
参数:
cp:指定要转换的字符串
inp:指向 struct in_addr 结构体的指针
返回值:
成功,返回1
失败,返回0,同时设置errno
in_addr_t inet_addr(const char *cp);
功能:把 ip地址(点分十进制字符串) 转换成 32bits整数 (网络字节序)
in_addr_t inet_network(const char *cp);
功能:把 ip地址(点分十进制字符串) 转换成 32bits整数 (主机字节序)
因此还需要使用 htonl() 进行转换
char *inet_ntoa(struct in_addr in);
功能:把 struct in_addr 结构体类型 转换成 ip地址(点分十进制字符串)
例子: //设置服务器的ip和端口struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; //协议族 server_addr.sin_port = htons( 6666 ); //端口号 ( 网络字节序 )inet_aton( "172.4.0.244", &server_addr.sin_addr ); //ip地址 //server_addr.sin_addr.s_addr = htonl( inet_network( "172.4.0.244" ) );//server_addr.sin_addr.s_addr = inet_addr( "172.4.0.244" );//server_addr.sin_addr.s_addr = htonl( INADDR_ANY ); // INADDR_ANY 是一个宏,表示任何地址 0.0.0.0 // 一个监听地址,表示服务器愿意接收来自任何客户端的连接请求 //绑定 int re = bind( sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr) );if( re == -1 ){perror("bind error ");return -1;}printf("bind success\n");
3) listen 监听
NAME
listen - listen for connections on a socket
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
功能:监听套接字上的连接请求
参数:
sockfd:指定要监听的套接字描述符
backlog:指定最大连接请求的数量
返回值:
成功,返回0
失败,返回-1,同时errno被设置
4) accept 接收连接请求
NAME
accept - accept a connection on a socket
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:等待一个新的连接,用户接受一个来自客户端的连接请求
参数:
sockfd:指定要接收连接的套接字描述符
addr:指向 struct sockaddr 结构体的指针,用于返回客户端的地址信息(ip+端口)
addrlen:指向 socklen_t 类型的指针,用于指定 addr 结构体的长度
在调用时,addrlen保存addr指向空间的最大的长度
在函数返回时,addrlen保存实际返回的地址长度
返回值:
成功,返回一个套接字描述符 (后续与客户端发生通信,都是使用这个套接字描述符 )
失败,返回-1,同时errno被设置
struct sockaddr_in client_addr; //保存客户端的ip+端口 socklen_t len = sizeof( client_addr );//接受连接int client_sock = accept( sock_fd, (struct sockaddr *)&client_addr, &len );if( client_sock == -1 ){perror("accept error ");return -1;}printf("client ip = %s\n", inet_ntoa( client_addr.sin_addr ) );
5)通信 发送/接收数据
(5.1)发送数据
write / send / sento
这三个函数,TCP都可以用,但是UDP只能用sendto
NAME
send, sendto - send a message on a socket
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
功能:发送数据到套接字上
参数:
sockfd:指定要发送数据的套接字描述符
buf:指针,指向的空间用来保存要发送的数据
len:指定要发送的数据的长度,单位:字节
flags:指定发送标志
0 阻塞模式
MSG_DONTWAIT 非阻塞模式
dest_addr:地址结构体指针,指定接收方的地址,UDP一定要指定,TCP可以不指定
addrlen:接收方地址结构体的长度,单位:字节
返回值:
成功,返回实际发送的字节数
失败,返回-1,同时errno被设置
(5.2)接收数据
read / recv / recvfrom
这三个函数,TCP都可以用,但是UDP只能用recvfrom
NAME
recv, recvfrom - receive a message from a socket
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
功能:从套接字上接收数据
参数:
sockfd:指定要接收数据的套接字描述符
buf:指针,指向的空间用来保存接收到的数据
len:指定接收的数据的最大长度,单位:字节
flags:指定接收标志
0 阻塞模式
MSG_DONTWAIT 非阻塞模式
src_addr:地址结构体指针,用于保存发送方的地址,UDP一定要指定,TCP可以不指定
addrlen:地址结构体的长度,单位:字节
返回值:
成功,返回实际接收的字节数
失败,返回-1,同时errno被设置
6)关闭套接字
close / shutdown
NAME
shutdown - shut down part of a full-duplex connection
SYNOPSIS
#include <sys/socket.h>
int shutdown(int sockfd, int how);
功能:关闭指定的套接字
参数:
sockfd:指定要关闭的套接字描述符
how:指定关闭的方式
SHUT_RD 关闭读方向
SHUT_WR 关闭写方向
SHUT_RDWR 关闭读写方向 <===> close( sockfd )
返回值:
成功,返回0
失败,返回-1,同时errno被设置
7)connect 连接服务器
NAME
connect - initiate a connection on a socket
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:连接服务器
参数:
sockfd:指定客户端的套接字描述符
addr:地址结构体指针,指定要连接的那个服务器的地址(ip+端口)
addrlen:地址结构体的长度,单位:字节
返回值:
成功,返回0
失败,返回-1,同时errno被设置
总结示例: 利用TCP 写一个网络应用程序的服务器,用来接收数据 客户端 用来发送数据 tcp_server.c int main( int argc, char * argv[] ) {//1.创建套接字 socket int server_sock = socket( AF_INET, SOCK_STREAM, 0 );if( server_sock == -1 ){perror("socket server error ");return -1;}printf("server_sock = %d\n", server_sock );//2.绑定服务器的ip和端口 bind (服务器的ip和端口)struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; //协议族 server_addr.sin_port = htons( atoi(argv[2]) ); //端口号 ( 网络字节序 )inet_aton( argv[1] , &server_addr.sin_addr ); //ip地址 int re = bind( server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr) );if( re == -1 ){perror("bind server error ");close( server_sock );return -1;}printf("bind success! \n"); //3.监听 listen re = listen( server_sock, 5 );if( re == -1 ){perror("listen server error ");close( server_sock );return -1;}printf("listen success! \n"); //4.接受连接请求 accept struct sockaddr_in client_addr; //保存客户端的ip+端口 socklen_t len = sizeof( client_addr );int client_sock = accept( server_sock, (struct sockaddr *)&client_addr, &len );if( client_sock == -1 ){perror("accept server error ");close( server_sock );return -1;}printf("accept success! client_sock = %d\n", client_sock );printf("client ip = %s\n", inet_ntoa( client_addr.sin_addr ) );//5.通信 recv/sendwhile(1){//接收数据 char buf[128] = {0};re = recv( client_sock, buf, sizeof(buf), 0 );if( re > 0 ){printf("recv = %s\n", buf );}else {perror("recv server error ");break;}//人为定义退出条件if( buf[0] == '#' ){break;}} //6.关闭套接字 closeclose( server_sock );}tcp_client.c int main( int argc, char * argv[] ){//1.创建套接字 socket int client_sock = socket( AF_INET, SOCK_STREAM, 0 );if( client_sock == -1 ){ perror("socket client error ");return -1;}printf("client_sock = %d\n", client_sock );//2.设置服务器的ip和端口,连接服务器 connect struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; //协议族 server_addr.sin_port = htons( atoi(argv[2]) ); //端口号 ( 网络字节序 )inet_aton( argv[1] , &server_addr.sin_addr ); //ip地址 int re = connect( client_sock, (struct sockaddr *)&server_addr, sizeof(server_addr) );if( re == -1 ){perror("connect client error ");close( client_sock );return -1;}//3.通信 send/recv while(1){//发送数据 char buf[128] = {0};printf("input data: ");fgets( buf, sizeof(buf), stdin );re = send( client_sock, buf, strlen(buf), 0 );if( re == -1 ){perror("send client error ");break;}//人为定义退出条件if( buf[0] == '#' ){break;}}//4.关闭套接字 closeclose( client_sock );}相关文章:
网络编程 --------- 2、socket网络编程接口
1、什么是socket 套接字 socke套接字是一个编程的接口 (网络编程的接口)、是一种特殊的文件描述符 (read/write),不局限于TCP/IP 。socket是独立于具体协议的网络编程接口这个接口是位于 应用层和传输层之间 。 类型: (1)流式套接字 SOCK_ST…...
C# Deconstruct详解
总目录 前言 该文来源于探索弃元的使用,由弃元了解到元组,由元组又了解到解构方法Deconstruct。 另外本文中 解构和析构一个意思,不要在意! 一、Deconstruct是什么? 1. 关于元组 如果我们想了解Deconstruct 的使用&…...
Java 面试常见问题之——为什么重写equals时必须重写hashCode方法
Java 面试常见问题之——为什么重写equals时必须重写hashCode方法 当重写 equals 方法时,通常也应该重写 hashCode 方法,原因主要有以下几点: 一致性原则:根据 Java 的约定,如果两个对象通过 equals 方法比较返回 tr…...
后端给的树形结构 递归 改造成阶联选择器所需要的lable、value结构
赋值:this.newTreeData this.renameFields(this.treeData) 递归方法:renameFields (tree) {return tree.map(node > {// 创建一个新对象来存放修改后的字段名const newNode {value: node.id,label: node.title,// 如果有子节点,则递归处理…...
文献阅读:基于拓扑结构模型构建ICI收益诊断模型
介绍 Custom scoring based on ecological topology of gut microbiota associated with cancer immunotherapy outcome是来自法国Gustave Roussy Cancer Campus的Laurence Zitvogel实验室最近发表在cell的关于使用肠道微生物拓扑结构预测免疫治疗疗效的文章。 该研究提供基于…...
Python文献调研(四)QtDesigner的布局
一、新建项目: 1.打开pycharm,新建一个Python项目 (1)右键项目列表区,找到我们之前配置好的外部工具,点击Pyside6 QtDesigner 打开Qt Designer后会是这个界面: (2)此时…...
CentOS Linux release 7.9.2009 中sudo命令未找到
先在 Windows 环境中下载 sudo 的安装包 下载安装包:https://www.sudo.ws/releases/stable/ 然后把安装包拷贝的 Centos 中,cd 进入安装包所在的目录执行下面的命令: 格式:rpm -Uhv xxxxx.rpm rpm -Uhv sudo-logsrvd-1.9.15-6.…...
生产计划问题的不同最优化工具软件求解
一、优化求解软件简介 众所周知,常用的优化工具软件有Lingo、Mathcad和MATLAB。 1. LINGO是Linear Interactive and General Optimizer的缩写,即“交互式的线性和通用优化求解器”,由美国LINDO系统公司(Lindo System Inc.&…...
Java关键字及保留字总结
文章目录 Java关键字及保留字总结(按首字母字母顺序所排列)1.abstract2.boolean3.break4.byte5.case6.catch7.char8.class9.continue10.default11.do12.double13.else14.enum15.extends16.final17.finally18.float19.for20.if21.implements22.import23.i…...
【PGCCC】PostgreSQL 14 小版本分析,有那个版本不建议使用#PG中级
以下是对 PostgreSQL 14 各个小版本的详细分析,包括每个版本的主要变化、修复的 bug 和潜在的问题: PostgreSQL 14.0 发布日期:2021 年 9 月 30 日 主要变化: 增加了并行查询的改进,提升了性能。增强了 JSON 数据类…...
B树在数据库中的应用:理论与实践
B树在数据库中的应用:理论与实践 B树(B-tree)是一种自平衡的树数据结构,广泛应用于数据库系统中,特别是用于实现索引和文件系统中的关键字查找。B树的设计目标是保持数据有序并允许高效的查找、插入和删除操作。本文将…...
网络编程 -------- 3、TCP_UDP_UNIX
1、基于TCP的套接字编程流程 Server.c socket bind (服务器的ip端口) listen accept recv / send close Client.c socket connect (服务器的ip端口) …...
口袋奇兵:游戏辅助教程!陆军搭配阵容推荐,平民必备!
《口袋奇兵》是一款策略类手游,玩家需要在游戏中组建和指挥自己的军队,进行各种战斗和任务。为了在游戏中取得更好的成绩,合理搭配英雄和使用辅助工具是非常重要的。本攻略将为大家介绍一种强力的陆军搭配阵容,以及如何利用VMOS云…...
Spring Boot 集成参数效验 Validator
为什么需要参数效验? 在业务开发中,为了防止非法参数对业务造成影响,所以需要对用户输入的正确性、数据完整性、安全性、业务规则的执行做效验,靠代码对接口参数做if判断的话就太繁琐了,代码冗余且可读性差(主要是不够优雅)。 Validator效验框架遵循了JSR-303验证规范…...
63、ELK安装和部署
一、ELK日志系统 1.1、ELK平台的定义 ELK平台是一套完整的日志集中处理解决方案,将ElasticSearch、Logstash和Kiabana 三个开源工具配合使用,完成更强大的用户对日志的查询、排序、统计需求 E:elasticsearch ES分布式索引型非关系数据库,存…...
【Dash】简单的直方图
一、Visualizing Data The Plotly graphing library has more than 50 chart types to choose from. In this example, we will make use of the histogram chart. # Import packages from dash import Dash, html, dash_table, dcc import pandas as pd import plotly.expre…...
【CTF-Crypto】格密码基础(例题较多,非常适合入门!)
格密码相关 文章目录 格密码相关格密码基本概念(属于后量子密码)基础的格运算(行列式运算)SVP(shortest Vector Problem)最短向量问题CVP(Closet Vector Problem)最近向量问题 做题要…...
Java对象流
对象流 对象输入流 java.io.ObjectInputStream使用对象流可以进行对象反序列化 构造器 ObjectInputStream(InputStream in) 将当前创建的对象输入流链接在指定的输入流上 方法 Object readObject() 进行对象反序列化并返回。该方法会从当前对象输入流链接的流中读取若干…...
问界M7是不是换壳东风ix7? 这下有答案了
文 | AUTO芯 作者 | 谦行 终于真相大白了 黑子们出来挨打啊 问界M7是换壳的东风ix7? 你们没想到,余大嘴会亲自出来正面回应吧 瞧瞧黑子当时乐的 问界你可以啊!靠改名字造车呢? 还有更过分的,说M7是东风小康ix7…...
mybatis多条件in查询拓展
背景 最近碰上有个业务,查询的sql如下: select * from table where (sku_id,batch_no) in ((#{skuId},#{batchNo}),...); 本来也没什么,很简单常见的一种sql。问题是我们使用的是mybatis-plus,然后写的时候又没有考虑到后面的查…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...
