09.计算机网络——套接字编程

news2024/11/27 14:52:22

文章目录

  • 网络字节序
  • socket编程
    • socket 常见API
    • sockaddr结构
  • UDP编程
    • 创建socket
    • 绑定socket
    • sendto发送数据
    • recvform接收数据
    • 关闭socket
  • TCP编程
    • 创建socket
    • 绑定socket
    • listen监听套接字
    • accept服务端接收连接套接字
    • connect客户端连接套接字
    • send发送数据
    • recv接收数据
    • 关闭socket
  • 工具
    • netstat
    • telnet
    • 地址转换函数
  • socket编程注意细节
  • 代码案例


网络字节序

​ 内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网络数据流同样有大端小端之分。
​ TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据。为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oWm0b8Ym-1689856659297)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720171128069.png)]

  • h表示host,n表示network,l表示32位长整数,s表示16位短整数。

  • htonl表示将32位的长整数从主机字节序转换为网络字节序。

  • ntohl表示将32位的长整数从网络字节序转换为主机字节序。


socket编程

​ socket套接字通常指的是封装了ip和port的结构体,其是网络编程中的一种通信机制,支持TCP/IP的网络通信的基本操作单元,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。


socket 常见API

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);

// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);

// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);

// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,socklen_t* address_len);

// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockaddr结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jm27OicV-1689856659297)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720182915989.png)]

套接字分类:

  1. 域间套接字 —— 本地通信
  2. 原始套接字 —— 允许绕过传输层,直接跟底层打交道,主要用来写一些工具。
  3. 网络套接字 —— 网络通信

​ 理论上是三种应用场景,对应的应该是三套接口,但是Linux设计套接字的时候不想设计过多的接口,所以Linux将所有的接口进行了统一,只使用sockaddr结构体来描述这三种场景。 但是真正在基于IPv4编程时, 使用的数据结构是sockaddr_in; 这个结构里主要有三部分信息: 地址类型, 端口号, IP地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e69gOlTy-1689856659298)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720183050113.png)]


UDP编程

创建socket

#include <sys/types.h>
#include <sys/socket.h>
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
//参数
domain:指定网络层的协议
    AF_INT: 使用ipv4版本的ip协议
    AF_INT6:使用ipv6版本的ip协议
    AF_UNIX:本地通信
type: 指定套接字的类型
    SOCK_DGRAM :使用UDP数据报套接字
	SOCK_STREAM:使用TCP字节流套接字
protocol:指定使用的协议
      0:使用套接字类型对应的默认协议

绑定socket

int bind(int socket, const struct sockaddr* address,socklen_t address_len);*
//参数
sockfd:		socket函数返回的套接字描述符
addr:		地址信息结构体成员,struct sockaddr 是一个通用地址信息结构
address_len:地址信息结构的长度

sendto发送数据

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-阻塞发送
dest_addr:	 目标主机的地址信息结构体
addrlen:	目标主机地址信息结构体的长度
//返回值
成功返回发送的字节数量,失败返回-1

recvform接收数据

ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags,struct sockaddr* src_addr, socklen_t* addrlen);
//参数
sockfd:		套接字描述符
buf:		将数据接收到buf当中
len:		buf的最大接收能力
flags:		0-阻塞接收
src_addr:	数据来源的主机地址信息结构体  
addrlen:	输入输出型参数
//返回值
成功则返回实际接收到的字符数,失败返回-1,错误原因会存于errno中

关闭socket

close(int sockfd);
//sockfd:		套接字描述符

TCP编程

创建socket

#include <sys/types.h>
#include <sys/socket.h>
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
//参数
domain:指定网络层的协议
    AF_INT: 使用ipv4版本的ip协议
    AF_INT6:使用ipv6版本的ip协议
    AF_UNIX:本地通信
type: 指定套接字的类型
    SOCK_DGRAM :使用UDP数据报套接字
	SOCK_STREAM:使用TCP字节流套接字
protocol:指定使用的协议
      0:使用套接字类型对应的默认协议
//返回值:
socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,程序可以像读写文件一样用read/write在网络上收发数据;调用出错则返回-1

绑定socket

int bind(int socket, const struct sockaddr* address,socklen_t address_len);*
//参数
sockfd:		socket函数返回的套接字描述符
addr:		地址信息结构体成员,struct sockaddr 是一个通用地址信息结构
address_len:地址信息结构的长度

listen监听套接字

//listen()声明sockfd处于监听状态
int listen(int sockfd, int backlog);
//参数
sockfd:	套接字描述符
backlog:已完成连接队列的大小
//返回值:
  成功:0
  失败:-1

当客户端和服务端进行三次握手的时候会存在两种状态:连接还未建立和连接已建立,此时操作系统内核中就会存在两个队列:未完成连接队列和已完成连接队列。当完成三次握手后会由未完成连接队列放到已完成连接队列,而backlog就是已完成连接队列的大小,backlog影响了服务端并发接收连接的能力。

accept服务端接收连接套接字

//从已经完成连接队列中获取已经完成三次握手的连接,没有连接时,调用accept会阻塞等待。
int accept(int sockfd, struct sockaddr* addr, socklen_t * addrlen);
//参数
sockfd:套接字描述符(listen_sockfd)
addr:输出型参数,保存客户端地址信息结构(客户端IP,客户端的端口)
addrlen:输入输出参数,传入缓冲区的大小,传出客户端地址信息结构的长度
//返回值
  成功:返回新连接的套接字描述符
  失败:返回-1

三次握手的时候是对listen_sockfd进行操作,当调用accept()会在Tcp服务端内部创建一个新的套接字new_sockfd,三次握手之后的数据收发都是多new_sockfd进行操作。


connect客户端连接套接字

//客户端需要调用connect()连接服务器
int connect(int sockfd, const struct sockaddr * addr,socklen_t addrlen);
//参数
sockfd:套接字描述符(listen_sockfd)
addr:服务端地址信息结构(服务端IP,服务端的端口)
addrlen:服务端地址信息结构的长度
//返回值
  成功:返回0
  小于0,连接失败

send发送数据

ssize_t send(int sockfd, const void * buf, size_t len, int flags);

//参数
sockfd:套接字描述符(new_sockfd)
buf:待要发送的数据
len:发送数据的长度
flags:
  0:阻塞发送
  MSG_OOB:发送带外数据,在紧急情况下所产生的数据,会越过前面进行排队的数据优先进行发送。
    
//返回值
  大于0:返回发送的字节数量
  -1:发送失败

recv接收数据

ssize_t recv(int sockfd, void * buf, size_t len, int flags);

//参数
sockfd:套接字描述符(new_sockfd)
buf:将接收的数据放到buf
len:buf的最大接收能力
flags:0:阻塞发送;如果客户端没有发送数据,调用recv会阻塞
    
//返回值
  大于0:正常接收了多少字节数据
  等于0:对端将连接关闭了
  小于0:接受失败

关闭socket

close(int sockfd);
//sockfd:		套接字描述符

工具

netstat

netstat -anp | grep [端口号]
  • 查看端口的使用情况

telnet

  • 进入cmd,使用telnet模仿TCP三次握手建立连接,在cmd窗口输入 “tenlet + 公网IP + 端口号” 即可模拟测试

地址转换函数

sockaddr_in中的成员struct in_addr sin_addr表示32位 的IP 地址,但是我们通常用点分十进制的字符串表示IP 地址,以下函数可以在字符串表示 和in_addr表示之间转换

字符串转in_addr的函数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oo44FIpo-1689856659298)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720195247336.png)]

in_addr转字符串的函数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MIr8eH4R-1689856659298)(C:\Users\11794\AppData\Roaming\Typora\typora-user-images\image-20230720195258821.png)]

inet_ntoa函数把这个返回结果放到了静态存储区,这个时候不需要我们手动进行释放。

socket编程注意细节

  • 客户端没有必要调用bind()固定一个端口号,否则如果在同一台机器上启动多个客户端,就会出现端口号被占用导致不能正确建立连接。
  • 服务器也不是必须调用bind(),但如果服务器不调用bind(), 内核会自动给服务器分配监听端口, 每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦。
  • 多进程的客户端代码和单进程是一样的,父进程负责accept,子进程负责数据的接收和发送,若子进程一直不退出,则父进程一直在等待,永远无法接收新连接,可以使用自定义信号处理方式将SIGCHLD信号重新定义,当子进程退出发出SIGCHLD信号时,父进程则对子进程的资源进行回收。
  • 建立好了tcp连接之后,我们就可以把得到的fd当作文件描述符来使用,也可以使用read和 write函数进行读写

代码案例

UDP案例

UDP · 程序员Jared/Linux - 码云 - 开源中国 (gitee.com)

TCP案例

TCP · 程序员Jared/Linux - 码云 - 开源中国 (gitee.com)

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

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

相关文章

算法训练营第四十六天||● 139.单词拆分 ● 关于多重背包,你该了解这些! ● 背包问题总结篇!

● 139.单词拆分 这道题和完全背包一样&#xff0c;求排列数相当于 字符串相当于背包&#xff0c;字串相当于物品 注意find方法的使用 find&#xff08;s.begin(),s.end(),"zichuan") 还有s.substr的使用s.substr(起始位置&#xff0c;截取长度&#xff09; clas…

Stable Diffusion服务环境搭建(远程服务版)

Stable Diffusion服务环境搭建&#xff08;远程服务版&#xff09; Stable Diffusion是什么 Stable diffusion是一个基于Latent Diffusion Models&#xff08;潜在扩散模型&#xff0c;LDMs&#xff09;的文图生成&#xff08;text-to-image&#xff09;模型。具体来说&#…

ES6基础知识一:说说var、let、const之间的区别

一、var 在ES5中&#xff0c;顶层对象的属性和全局变量是等价的&#xff0c;用var声明的变量既是全局变量&#xff0c;也是顶层变量 注意&#xff1a;顶层对象&#xff0c;在浏览器环境指的是window对象&#xff0c;在 Node 指的是global对象 var a 10; console.log(window.…

VUE3---->基础入门

目录 vue 基础入门 1、解读核心关键词&#xff1a;框架 2、vue 的版本 3、vue 的调试工具 vue 基础入门 vite 的基本使用 1. 创建 vite 的项目 2. 梳理项目的结构 3. vite 项目的运行流程 组件的基本使用 1. 组件的注册 2. 组件之间的样式冲突问题 3. 组件的 props …

穿透内网群晖NAS实现远程访问【无公网IP】

穿透内网群晖NAS实现远程访问【无公网IP】 现代科技日新月异&#xff0c;我们身边的电子设备也在不断更新&#xff0c;日积月累之下&#xff0c;被淘汰的电子设备越来越多&#xff0c;难道就让这些性能不算差的电子设备从此闲置么&#xff0c;这明显不符合我们物尽其用的原则&a…

记录安装stable diffusion webui时,出现的gfpgan安装卡住的问题

参考链接&#xff1a;(145条消息) 使用stable diffusion webui时&#xff0c;安装gfpgan失败的解决方案&#xff08;windows下的操作&#xff09;_新时代原始人的博客-CSDN博客

[書籍]思考的框架

圖片來源:博客來書店 《思考的框架》是一本極具啟發性和實用性的書籍&#xff0c;它以系統性和綜合性的方式引導讀者運用跨學科思維來解決問題和拓展思維視野。作者巧妙地整合了來自不同領域的思想家和學者的觀點&#xff0c;從心理學到經濟學&#xff0c;從哲學到科學等&#…

docker安装jdk

文章目录 1.安装镜像2.查看已安装的镜像4.运行容器5.进入JDK 容器6.查看JDK版本 1.安装镜像 找到所要安装的镜像版本&#xff0c;复制命令 输入命令&#xff0c;下载openjdk8镜像 命令作用docker pull openjdk:8拉取版本号为8的镜像 2.查看已安装的镜像 命令作用docker ima…

指针大厂笔试真题讲解(c语言篇)

大家好&#xff0c;我是c语言boom家宝&#xff0c;今天为大家带来的是c语言指针内容在大厂笔试中的真题讲解&#xff0c;希望能让初学者对指针有更深入的理解。 ps&#xff1a;如有侵权&#xff0c;请私信联系&#xff0c;立刻删除。 真题一&#xff1a; 答案&#xff1a;2 &…

SpringCloud分布式项目下feign的使用

新建一个feign的微服务&#xff08;后面统称为A&#xff09;&#xff0c;其他项目要使用利用maven导入该服务模块的依赖就行了 导入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</…

【C++】STL——list的使用和介绍、list的构造函数及其使用、list迭代器及其使用

文章目录 1.list的介绍和使用2.list的构造函数&#xff08;1&#xff09;list (size_type n, const value_type& val value_type()) &#xff08;2&#xff09;list() 构造空的list&#xff08;3&#xff09;list (const list& x) 拷贝构造函数&#xff08;4&#xff…

Spring Boot创建与运行

Spring Boot创建与运行 ​ 经过之前 Spring 文章的铺垫&#xff0c;终于来到了基于 Spring &#xff0c;并且也是 Spring 最火的框架之一 Spring Boot &#xff0c;在企业或者个人项目中&#xff0c;基本都是使用 Spring Boot &#xff0c;所以 Spring Boot 在 Spring 的学习阶…

Spring Boot 源码学习之@EnableAutoConfiguration注解

EnableAutoConfiguration 注解 引言主要内容1. EnableAutoConfiguration 功能解析1.1 常见的自动配置示例1.2 源码介绍 2. Import 注解介绍3. AutoConfigurationPackage 注解介绍 总结 引言 在 Huazie 的上篇博文中&#xff0c;我们详细了解了关于 SpringBootApplication 注解…

【论文阅读 03】机器学习算法在颈动脉斑块影像学分类中的研究进展

读完之后就是&#xff0c;总结 机器学习&#xff08;SVM、小波&#xff09;和深度学习&#xff08;CNN&#xff09;在 颈动脉斑块影像学中的 分类效果。只讨论了超声、磁共振两种成像 Chin J Clin Neurosci 临床神经科学杂志 复旦大学 颈动脉斑块( carotid plaques) 是一种…

JavaScript基础篇(31-40题)

此文章&#xff0c;来源于印客学院的资料【第一部分&#xff1a;基础篇(105题)】&#xff0c;也有一些从网上查找的补充。 这里只是分享&#xff0c;便于学习。 诸君可以根据自己实际情况&#xff0c;自行衡量&#xff0c;看看哪里需要加强。 概述如下&#xff1a; javascri…

使用Docker在局域网安装GitLab

使用 Docker 安装 GitLab 1. 安装GitLab 最近想在本地创建一个GitLab仓库&#xff0c;简单记录一下&#xff1a; 简单设置一个GitLab信息的存储目录 export GITLAB_HOME/etc/docker/gitlab/ && mkdir &GITLAB_HOMEdocker中启动 sudo docker run --detach \# 以…

C++:类和对象(上)---初步认识类和this指针

文章目录 面向过程和面向对象类的引入类的定义类定义的方式 类的访问限定符类的实例化类对象模型类对象的大小 this指针 面向过程和面向对象 C语言是一门面向过程的语言关注的是过程&#xff0c;确认一个问题求解的步骤&#xff0c;再一步一步对它进行解决 C是一门基于面向对…

【学会动态规划】最小路径和(9)

目录 动态规划怎么学&#xff1f; 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后&#xff1a; 动态规划怎么学&#xff1f; 学习一个算法没有捷径&#xff0c;更何况是学习动态规划&#xff0c; 跟我…

Kotlin 协程基础入门:Channel(通道)

简介 Kotlin 中的 Channel&#xff08;通道&#xff09;是一种协程间通信的机制&#xff0c;用于在协程之间传递数据。它提供了一种有序、线程安全的方式&#xff0c;让生产者和消费者之间进行异步数据传输。 Channel 这个管道的其中一端&#xff0c;是发送方&#xff1b;管道…

OpenCV实现照片换底色处理

目录 1.导言 2.引言 3.代码分析 4.优化改进 5.总结 1.导言 在图像处理领域&#xff0c;OpenCV是一款强大而广泛应用的开源库&#xff0c;能够提供丰富的图像处理和计算机视觉功能。本篇博客将介绍如何利用Qt 编辑器调用OpenCV库对照片进行换底色处理&#xff0c;实现更加…