【计算机网络】什么是socket编程?以及相关接口详解

news2024/9/24 23:33:32

在这里插入图片描述

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 :阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶🔹C++🔹Liunx
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍

在这里插入图片描述

一、 什么是socket套接字

我们使用一张图片很形象的可以看出socket所处的位置。

在这里插入图片描述
从用户层面来看:

从上图看出,Socket处于应用层传输层的中间软件抽象层,它是一组接口。并且前面我们也学过,运输层和网络层其实属于操作系统内层面,我们只给用户提供使用的接口即可,不可能让用户能直接访问到内核部分。
在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

从操作系统层面来看:
linux下一切皆文件!!!所以本质来说Socket即是一种特殊的文件,一些socket函数【bind()、listen()等等】,就是对这个文件进行的操作(读/写IO、打开、关闭)

二、Socket函数接口详解

// 创建 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);

上面的参数中带有 struct sockaddr*结构体,这是个什么呢?

首先我们要知道socket的英文为插座,而我们的ip+端口号可以决定是哪一台主机上的哪一个进程,相当于一个插头,谁插入这个socket插槽,谁就可以与之通信。

套接字的分类及struct sockaddr*

1.网络套接字

2.原始套接字

3.unix域间套接字

这个struct sockaddr*结构体是一个父类一般还有两个衍生的子类,他们一个sockaddr_in(inet,网络通信)主要用于网络间的通信同时也支持本地,另一个sockaddr_un(域间套接字)只能在本地通信。而原始套接字可以跨过传输层(TCP/IP协议)访问底层的数据

网络套接字
struct sockaddr_in {
    short int sin_family;  // 地址族,一般为AF_INET(IPv4)和AF_INET6(IPv6)
    unsigned short int sin_port; // 端口号,网络字节序
    struct in_addr sin_addr; // IP地址
    unsigned char sin_zero[8];// 用于填充,使sizeof(sockaddr_in)等于16
};


原始套接字
struct sockaddr {
    sa_family_t sa_family; 		/* address family, AF_xxx */
    char sa_data[14];//sa_data是一个字节数组,用于存储地址和端口号信息的具体内容,具体内容的长度和格式依赖于协议族的不同。
};

unix域间套接字
struct sockaddr_un {
    sa_family_t sun_family;       /* AF_UNIX */
    char sun_path[108];    /* 带有路径的文件名 */
};//通过同一个文件的路径来让进程看到同一份资源

其中还有一个结构体是struct in_addr,这个函数内部如下:


struct in_addr {
  uint32_t    s_addr;   /* address in network byte order */
};

简单来说原始套接字使用了一个sa_data数组将IP和端口号存储在了一起,很多网络编程函数诞生早于IPv4协议,那时候都使用的是sockaddr结构体。但是sockaddr的缺陷是:sa_data把目标地址和端口信息混在一起了。IPv4为了解决这个问题,于是便设计了sockaddr_in专门用于网络通信结构体,把port和ip分开来存储。

sockaddr_in 是用于 IPv4 地址的特定地址结构体。它扩展了 sockaddr,并提供了 IPv4 地址(通过 sin_addr 字段存储)和端口号(通过 sin_port 字段存储)的字段。sockaddr_in 使用的是网络字节序(大端字节序)来存储这些值。如果不知道网络字节序请搜索一下。

在这里插入图片描述

1.socket

格式:

int socket(int domain, int type, int protocol);

参数:

  • domain:指定套接字的协议族,如AF_INET(IPv4)或AF_INET6(IPv6)。
    type:指定套接字的类型。
       SOCK_STREAM(面向连接的流套接字)
      SOCK_DGRAM(无连接的数据报套接字)。
    protocol:指定使用的传输协议,通常可以设置为0以自动选择合适的协议。

返回值:返回一个int型的数字来表示套接字

作用创建一个套接字,将domain、type和protocol参数传递给socket()函数以指定套接字的特性,并返回一个int型套接字描述符,用于后续的操作。

2.bind

格式:

int bind(int socket, const struct sockaddr *addr,socklen_t addrlen);

参数:

  • sockfd:要绑定的套接字描述符,也就是socket函数的返回值
  • addr:是一个指向 sockaddr 结构的指针,该结构包含了要绑定的IP地址和端口号。
  • addrlen:指定addr结构体的大小。

返回值

  • bind函数的返回值用于指示操作是否成功:
    如果 bind 函数成功执行,它将返回 0。
    如果 bind 函数执行失败,它将返回 -1,并设置全局变量 errno 以指示错误的具体原因。

作用:bind函数用于将一个套接字(socket)与特定的IP地址和端口号绑定

3.listen

格式:

int listen(int socket, int backlog)

参数:

  • socket:要设置为监听状态的套接字描述符。
  • backlog:指定等待连接队列的最大长度,用于限制同时可以等待处理的连接请求的数目

返回值

  • 成功时:当listen函数成功地将套接字置于监听状态时,它返回0。这表示服务器已经准备好接受客户端的连接请求。
  • 失败时:如果listen函数执行失败,它将返回-1,并设置全局变量errno以指示错误的具体原因。此时,可以通过检查errno的值来确定错误类型,并据此采取相应的错误处理措施。

错误码:

EADDRINUSE:表示地址已被使用,即尝试监听的端口已被其他进程占用。
EINVAL:表示无效的参数,可能是因为套接字未绑定地址,或者该套接字已被连接(对于某些类型的套接字,如SOCK_DGRAM,监听操作可能不被允许)。
ENOTSOCK:表示文件描述符不是一个套接字。
WSAENETDOWN(Windows特有):表示网络子系统失效。
WSAEINPROGRESS(Windows特有):表示一个阻塞的套接字调用正在运行中。
WSAEMFILE(Windows特有):表示无可用文件描述符。
WSAENOBUFS(Windows特有):表示无可用缓冲区空间。

作用: 将套接字设置为监听状态,开始接受客户端的连接请求。通过指定backlog参数,可以控制连接队列的长度。

4.accept

格式:

int accept(int socket, struct sockaddr* address,
socklen_t* address_len)

参数:

  • sockfd:监听 套接字描述符。
  • addr:用于存储客户端的地址信息的结构体指针,可以是struct sockaddr、struct sockaddr_in或struct sockaddr_in6等类型的指针。
  • addrlen:指向一个整数变量,用于传递addr结构体的大小,并在接受连接后更新为实际的地址长度。

返回值

  • 成功时的返回值
    当accept函数成功接受一个客户端的连接请求时,它会返回一个非负值。这个非负值就是新创建的socket文件描述符或对象的标识符,用于后续的通信操作。

  • 失败时的返回值
    如果accept函数在尝试接受连接请求时遇到错误(例如,监听socket已经被关闭),它将返回-1,并设置全局变量errno以指示错误的具体原因。此时,可以通过检查errno的值来确定错误类型,并据此采取相应的错误处理措施。

作用: 等待并接受客户端的连接请求,并返回一个新的套接字描述符,该描述符用于与客户端进行通信。同时,可以获取客户端的地址信息

5.connet

格式:


int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

参数:

  • sockfd:要进行连接的套接字描述符。
  • addr:要连接的目标地址的结构体指针,该结构包含了要绑定的IP地址和端口号。
  • addrlen:指定addr结构体的大小。

返回值

  • 成功时的返回值
    当connect函数成功地将客户端套接字与服务器套接字连接起来时,它返回0。这表示连接已经成功建立,客户端可以继续通过该套接字发送和接收数据。
  • 失败时的返回值
    如果connect函数在尝试建立连接时遇到错误(如网络不可达、服务器未运行、服务器拒绝连接等),它将返回-1,并设置全局变量errno以指示错误的具体原因。此时,可以通过检查errno的值来确定错误类型,并据此采取相应的错误处理措施。

错误码

ECONNREFUSED:表示连接被远程计算机拒绝。这通常意味着没有服务在目标端口上监听,或者服务器程序拒绝连接请求。
ENETUNREACH:表示网络不可达。这可能是因为网络线路故障、路由表配置错误或远程主机不可达等原因。
ETIMEDOUT:表示连接超时。这可能是因为远程主机没有响应连接请求,或者连接请求在传输过程中被延迟或丢失。
EINPROGRESS(在非阻塞模式下):表示连接操作正在进行中。在非阻塞模式下,connect函数可能无法立即完成连接操作,此时将返回-1,并将errno设置为EINPROGRESS。在这种情况下,需要调用其他函数(如select、poll或epoll)来检查连接是否成功建立。

作用: 与另一个套接字建立连接,通常用于客户端连接服务器。通过指定目标地址和端口号,使套接字能够与目标进行通信。

6.读写操作

以下函数均可读取Socket数据

   ssize_t read(int fd, void *buf, size_t count);
   ssize_t write(int fd, const void *buf, size_t count);

   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);

   ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                  const struct sockaddr *dest_addr, socklen_t addrlen);
   ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                    struct sockaddr *src_addr, socklen_t *addrlen);

   ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
   ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

主要来说说recvfrom和sendto函数

在这里插入图片描述

recvfrom参数中的addr的意义就是获取发送发放的信息,便于之后使用sento发送时使用。

7.close()函数

在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好比操作完打开的文件要调用fclose关闭打开的文件。

8.字节序转换接口

#include<arpa/inet.h>

uint32_t    htonl(uint32_t hostlong);    //32位整数从主机字节序转换为网络字节序
uint16_t    htons(uint16_t hostshort);   //16位整数从主机字节序转换为网络字节序
uint32_t    ntohl(uint32_t netlong):     //32位整数从网络字节序转换为主机字节序
uint16_t    ntohs(uint16_t netshort);    //16位整数从网络字节序转换为主机字节序

9.IP地址格式转换函数

//点分十进制的IP地址字符串转换成in_addr_t类型
in_addr_t inet_addr(const char *cp)
//将结构struct in_addr中的二进制IP地址转换为一个点分十进制
char *inet_ntoa(struct in_addr in)

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

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

相关文章

letcode 分类练习 x个数之和问题 15. 三数之和 18. 四数之和 454. 四数相加 II 383. 赎金信

letcode 分类练习 x个数之和问题 15. 三数之和 18. 四数之和 454. 四数相加 II 383. 赎金信 三数之和四数之和454. 四数相加 II383. 赎金信 三数之和 三数之和&#xff0c;双指针模版代码&#xff0c;注意去重逻辑&#xff0c;还有只需要去重第一和第二重循环&#xff0c;第三…

从Python翻译Go代码谈起:AI辅助编程的现状与展望

最近&#xff0c;一位同学使用GPT-4o将一个约300行的Python程序转换成Golang&#xff0c;正确率达到了90%。这引发了一个有趣的讨论&#xff1a;如果是整个项目规模的代码转换&#xff0c;准确率会如何&#xff1f;作为被的对象&#xff0c;我决定深入探讨这个话题&#xff0c;…

高等数学精解【6】

文章目录 直线与二元一次方程直线方程斜率两点式方程截距式方程将不同形式的直线方程转换为截距方程直线的一般方程直线一般方程的系数有一个或两个为零的直线 参考文献 直线与二元一次方程 直线方程 斜率 直线对于 x 轴的倾角&#xff0c;平行于 x 轴&#xff0c;倾角为 0 &…

从一个服务预热不生效问题谈微服务无损上线

作者&#xff1a;凡问、启淮 前言 本文基于阿里云技术服务团队和产研团队&#xff0c;在解决易易互联使用 MSE&#xff08;微服务引擎&#xff09;产品无损上线功能所遇到问题的过程总结而成。本文将从问题和解决方法谈起&#xff0c;再介绍相关原理&#xff0c;后进一步拓展…

jupyter下载

https://blog.csdn.net/qq_48372575/article/details/125630622 我下面是CPU运行的&#xff0c;GPU链接在上面 Anaconda下载 https://docs.anaconda.com/miniconda/miniconda-other-installer-links/ 参考链接&#xff1a; https://blog.csdn.net/qq_48372575/article/detai…

计算机编码 - 笔记

1 ASCII码 - 0- 127 2 ASCII码扩展字符集 - 128- 255

反转字符串(LeetCode)

题目 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 的额外空间解决这一问题。 解题 def reverse_string(s):left 0right len(s) - 1while left …

SDF Marching Cubes Ray-marching Teahouse

SDF & Marching Cubes & Ray-marching SDF SDF(Signed Distance Field)有向距离场。SDF是由到&#xff08;多边形模型&#xff09;物体表面最近距离的采样网格。作为惯例&#xff0c;使用负值来表示物体内部&#xff0c;使用正值表示物体外部。 Marching Cubes marc…

CUDA编程05 - GPU内存架构和数据局部性

一&#xff1a;概述 到目前为止&#xff0c;我们已经学会了如何编写 CUDA 核函数&#xff0c;以及如何设置和分配大量线程来执行核函数。我们还了解了当前 GPU 硬件的计算架构&#xff0c;以及线程在硬件上调度执行过程。在本章中&#xff0c;我们将重点关注 GPU 的片上(on-chi…

golang实现Digest认证鉴权接口

什么是Digest认证鉴权接口? Digest认证鉴权接口是一种基于摘要算法的身份验证方法,用于确保API请求的安全性。在实际应用中,常常使用HTTP协议的Digest认证鉴权接口来验证请求的合法性。下面是一种常见的Digest认证鉴权流程: 1. 客户端发送HTTP请求到服务器,请求接口资源…

【MCAL】TC397+EB-tresos之ADC配置实战 - (模数转换)

本篇文章首先从理论讲起&#xff0c;基于《MC-ISAR_TC3xx_UM_Adc.pdf》介绍了ADC模块的理论知识&#xff0c;然后详细介绍了在TC397平台使用EB-tresos对ADC驱动模块进行配置与调试的实战过程&#xff0c;帮助第一次接触这个模块的读者能够更快的上手来实现符合自己项目要求的开…

OSPF TE

OSPF TE&#xff08;OSPF Traffic Engineering&#xff0c;即OSPF流量工程&#xff09;是为了支持MPLS流量工程&#xff08;MPLS TE&#xff09;&#xff0c;支持建立和维护TE的标签交换路径LSP&#xff08;Label Switch Path&#xff09;而在OSPF协议基础上扩展的新特性。在MP…

Qt WebEngine基于WebEngineScript注入js脚本

在之前的文章中&#xff0c;我们介绍了Qt WebEngine注入js的用法&#xff0c;及runJavaScript()的用法&#xff0c;该方法主要是用在页面加载完成后&#xff0c;为了和网页做一些交互时使用。有时候需要监听网页加载完成的一些状态或信息&#xff0c;则需要网页加载前注入js来实…

【CodinGame】趣味算法(教学用) CLASH OF CODE -20240802

[toc] 正文 最大最小值 import math import sys# Auto-generated code below aims at helping you parse # the standard input according to the problem statement.a int(input()) b int(input()) c int(input()) d int(input())mylist [] mylist.append(a) mylist.app…

如何写好提示词?《Midjourney常用关键词大全》-附关键词文件

​ Midjourney如何写好提示词从而生成高质量图片&#xff1f; 并且随心所欲生成各种风格的图片&#xff1f; 这是一份关于Midjourney常用关键词的文件&#xff1a; 风格形式/摄影构图/灯光材质/渲染方式/常见设备/常见元素等不同类别&#xff0c; 关键词分门别类&#xff0…

从PyTorch官方的一篇教程说开去(6.2 - 张量 tensor 矩阵运算等)

您的进步和反馈是我写作最大的动力&#xff0c;小伙伴来个三连呗&#xff01;共勉~ 话不多说&#xff0c;书接上文&#xff0c;需要温习的小伙伴请移步 - 从PyTorch官方的一篇教程说开去&#xff08;6.1 - 张量 tensor 基本操作&#xff09;-CSDN博客 借图镇楼 - 1 - 矩阵乘…

【面经】 HR面试套路一览 | 10条面试要点总结

博客主页&#xff1a;Duck Bro 博客主页 关注博主&#xff0c;后期持续更新系列文章 如果有错误感谢请大家批评指出&#xff0c;及时修改 感谢大家点赞&#x1f44d;收藏⭐评论✍ 面经总结 目录 面经总结前言1. 期望薪资2. 关于加班的问题3. 平时是如何学习的&#xff08;学…

光电测径仪和激光测径仪的区别

光电测径仪和激光测径仪都是用于测量物体直径的精密仪器&#xff0c;它们在工作原理、测量范围、精度、适用场景等方面有所不同。光电测径仪通常使用CCD光电传感器来检测通过物体的光强度变化&#xff0c;而激光测径仪则使用激光作为测量信号&#xff0c;通过发射激光束并接收反…

IT服务质量管理攻略(至简)

质量管理、风险管理和信息安全管理是IT服务监督管理的重要内容&#xff0c;三者之间相对独立。IT服务质量管理是通过制订质量方针、质量目标和质量计划&#xff0c;实施质量控制、质量保证和质量改进活动&#xff0c;确保IT服务满足服务级别协议的要求&#xff0c;最终获得用户…

案例分享-国外UI设计界面赏析

国外UI设计倾向于简洁的布局和清晰的排版&#xff0c;减少视觉干扰&#xff0c;提升用户体验。通过合理的色彩搭配和图标设计&#xff0c;营造舒适愉悦的使用氛围。 设计师不拘泥于传统框架&#xff0c;勇于尝试新元素和理念&#xff0c;使界面独特有趣。同时&#xff0c;强调以…