Linux--Socket套接字编程

Socket编程

Socket编程是一种在网络中不同计算机之间实现数据交换的编程方式。它允许程序创建网络连接,并通过这些连接来发送和接收数据。Socket编程是网络编程的基础,广泛应用于客户端-服务器(C/S)架构中。

要实现双方通信,就需要对应的地址,那如何找到对方的网络地址呢

IP地址和端口号

  • IP地址用于标识网络中的每一台设备
  • 端口号用于标识设备上的特定应用程序或服务(进程)
  • 端口号是一个 2 字节 16 位的整数;
  • 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来
    处理;
  • 一个端口号只能被一个进程占用
  • 端口号是传输层协议的内容
  • 0 - 1023: 知名端口号, HTTP, FTP, SSH 等这些广为使用的应用层协议, 他们的
    端口号都是固定的.
  • 1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作
    系统从这个范围分配的.

在这里插入图片描述
所以在网络通信中,可以通过IP地址锁定对应的主机,再通过端口号锁定对应主机上的应用程序或服务;
IP地址+端口号也成唯一标识的网络地址
Socket也就是将IP和port套在一起,完成网络间的通信;

进程ID和端口号

  • 进程ID是操作系统分配给每个正在运行的进程的唯一标识符。通过PID,操作系统可以跟踪和管理每个进程。
  • 端口号是一个逻辑概念,用于区分同一台计算机上不同应用程序或服务所使用的网络通信端口。每个端口号都对应着一个特定的服务或应用程序的实例。
  • 区别:进程ID用于操作系统内部管理和区分不同的进程,而端口号则用于网络通信中区分不同的应用程序或服务
  • 一个进程可以绑定多个端口号; 但是一个端口号不能被多个进程绑定

Socket的文件描述符

套接字(Socket)是一种在计算机网络中进行数据交换的端点。在UNIX和类UNIX系统中(如Linux和macOS),套接字被实现为文件描述符,这使得套接字可以像文件一样被打开、读写和关闭。文件描述符是一个非负整数,它是一个索引值,指向内核中每个进程打开文件的记录表。对于套接字而言,这个“文件”实际上是一个网络通信的端点

网络字节序

网络字节序,也称为大端字节序(Big-Endian),是指在网络通信协议中规定的字节序
它规定整数的高位字节必须先传输到网络上,即高位字节在前,低位字节在后。
主机字节序是指特定主机或处理器所采用的字节序。它取决于主机的硬件架构,可能是大端序或小端序(Little-Endian)。

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

#include <arpa/inet.h>
uint32_t htonl(uint32 t hostlong);
uint16_t htons(uintl6 t hostshort);
uint32_t ntohl(uint32tnetlong);
uint16_t ntohs(uintl6 ttnetshort);

Socket编程常见API

Socket是一个网络编程接口,是TCP/IP网络的API,它定义了一种方式,使应用程序可以通过网络与其他应用程序进行通信

socket()

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

socket函数是用于创建一个新的套接字的系统调用。套接字(Socket)是网络通信的基本单元,它提供了一种在应用程序之间(可能位于同一台机器或不同的机器上)进行通信的方式;

参数说明:

  • domain:指定协议族。常见的协议族有AF_INET(IPv4)、AF_INET6(IPv6)、AF_UNIX(本地套接字,用于同一机器上的进程间通信)等。
  • type:指定套接字的类型。常见的套接字类型有SOCK_STREAM(流套接字,提供可靠的、面向连接的通信,如TCP)、SOCK_DGRAM(数据报套接字,提供不可靠的、无连接的通信,如UDP)、SOCK_RAW(原始套接字,允许应用程序直接操作网络层协议)等。
  • protocol:指定协议。在大多数情况下,该参数可以设置为0,以选择协议族中默认的协议。

返回值:

  • 如果成功,socket函数返回一个非负整数,即新创建的套接字的文件描述符
  • 如果失败,返回-1,并设置全局变量errno以指示错误。

bind()

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

bind函数通常与网络编程相关,特别是在使用套接字(sockets)进行通信时,
bind函数用于将套接字与特定的本地地址和端口号绑定,从而确定套接字在网络上的标识

参数说明:

  • sockfd:套接字描述符,通常是通过socket函数创建的。
  • addr:指向struct sockaddr结构体的指针,该结构体中包含了要绑定的地址和端口信息。通常,对于IPv4地址,会使用struct sockaddr_in,而对于IPv6地址,则使用struct sockaddr_in6。这些结构体都需要强制类型转换为struct sockaddr*来传递给bind函数。
  • addrlen:addr结构体的大小。

返回值:
如果成功,bind函数返回0。
如果失败,返回-1,并设置全局变量errno以指示错误。

sockaddr_in结构体

struct in_addr
{uint32_t s_addr; /* IPv4 地址 */
};
struct sockaddr_in 
{shortsin_family;/*地址家族,AF_INET */unsigned shortsin_port;/*端口号,网络字节序*/struct in_addr sin_addr;/* IPv4 地址*/char sin_zero[8]/*未使用的字节,用零填充以保持结构大小与sockaddr相同3;
};

sockaddr_in是用于IPv4地址的套接字地址结构。它包含在sys/socket.h头文件中,并且是sockaddr结构的特定于IPv4的版本。当你需要在网络编程中处理IPv4地址时,你会经常与这个结构打交道。

成员变量:

  • sin_family:这是一个地址家族标识符,对于IPv4 来说,它通常被设置为AF_INET
  • sin_port:这是一个 16 位的端口号,它使用网络字节序(大端字节序)。在将端口号赋值给 sin_port 之前,你需要使用 htons() 函数(host to networkshort)来将主机字节序转换为网络字节序
  • sin_addr:这是一个 in_addr 结构,包含一个 32 位的IPv4 地址。在赋值之前,你可能需要将点分十进制表示法(如"192.168.1.1")转换为 32 位整数。这通常通过 inet _pton() 函数(presentation to network)来完成。
  • sin_zero:这是一个填充字段,用于确保sockaddr_in 结构的大小与通用的 sockaddr 结构相同。在实际使用中,这个字段通常被忽略。

recvfrom()

使用套接字(sockets)进行UDP通信时,这个函数用于从指定的套接字接收数据,并返回发送数据的地址
与TCP使用的 recv() 函数不同,recvfrom() 特别适用于无连接的UDP协议,因为它需要知道数据是从哪个地址发送来的。

#include <sys/socket.h>  ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,  struct sockaddr *src_addr, socklen_t *addrlen);

参数说明:

  • sockfd:套接字文件描述符,标识了一个打开的套接字。
  • buf:指向一个缓冲区的指针,用于存放接收到的数据。
  • len:指定了buf的大小,即可以接收的最大字节数。
  • flags:通常设置为0,但在某些特殊情况下可以用来控制函数的行为(如MSG_DONTWAIT标志,用于非阻塞套接字)。
  • src_addr:一个指向sockaddr结构的指针,该结构在调用后会被填充为发送数据的源地址。如果调用者不关心源地址,这个参数可以设置为NULL。
  • addrlen:是一个指向socklen_t的指针,在调用前应该包含src_addr指向的sockaddr结构的大小,在调用后,这个值会被更新为实际使用的结构大小。

返回值

  • 成功时,recvfrom() 返回接收到的字节数。
  • 如果连接被对方正常关闭,则返回0。
  • 如果发生错误,则返回-1,并设置相应的errno以指示错误类型

sendto()

用于UDP协议,允许开发者将数据从指定的套接字发送到对方主机,同时指定目的地址

#include <sys/types.h>  
#include <sys/socket.h>  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即可。但可以改变flags来改变sendto()发送的形式。
  • dest_addr:一个指向目的地址结构体的指针,包括目的IP地址和端口号等信息。
  • addrlen:表示目的地址结构体的长度。

返回值

  • 成功时,sendto() 返回实际发送的字节数。
  • 如果发生错误,则返回-1,并设置相应的errno以指示错误类型。

recv()

recv() 函数是网络编程中用于接收数据的函数,它主要用于TCP协议;
与recvfrom()不同,recv()不需要指定数据的来源地址,因为TCP是面向连接的协议,每个套接字(socket)都直接关联到一个特定的连接,所以接收的数据自然就是来自该连接的另一端

#include <sys/types.h>  
#include <sys/socket.h>  ssize_t recv(int sockfd, void *buf, size_t len, int flags);

参数说明

  • sockfd:套接字文件描述符,标识了一个打开的套接字。
  • buf:指向一个缓冲区的指针,用于存放接收到的数据。
  • len:指定了buf的大小,即可以接收的最大字节数。
  • flags:指定接收数据的方式,通常设置为0即可。但可以改变flags来改变recv()的行为,例如使用MSG_DONTWAIT标志进行非阻塞接收。

返回值

  • 成功时,recv() 返回接收到的字节数。
  • 如果连接被对方正常关闭,并且已经接收到了对方发送的FIN包,则返回0。
  • 如果发生错误,则返回-1,并设置相应的errno以指示错误类型。

send()

send() 函数是网络编程中用于发送数据的函数,它主要用于TCP协议。
与sendto()不同,send()不需要指定目的地址,因为TCP是面向连接的协议,每个套接字(socket)都直接关联到一个特定的连接,所以发送的数据自然就是发送到该连接的另一端

#include <sys/types.h>  
#include <sys/socket.h>  ssize_t send(int sockfd, const void *buf, size_t len, int flags);

参数说明

  • sockfd:套接字文件描述符,标识了一个打开的套接字。
  • buf:指向要发送数据的缓冲区的指针。
  • len:要发送的数据的字节数。
  • flags:指定发送数据的方式,通常设置为0即可。但可以改变flags来改变send()的行为,例如使用MSG_DONTWAIT标志进行非阻塞发送。

返回值

  • 成功时,send() 返回实际发送的字节数。这可能与请求发送的字节数相同,也可能不同(特别是在非阻塞模式下)。
  • 如果发生错误,则返回-1,并设置相应的errno以指示错误类型。

listen()

listen() 函数是在网络编程将套接字(socket)设置为监听状态,等待客户端的连接请求。常用于TCP协议。

#include <sys/socket.h>  int listen(int sockfd, int backlog);

参数说明

  • sockfd:套接字文件描述符,这是之前通过 socket() 函数创建的套接字,并且已经通过 bind() 函数绑定了特定的IP地址和端口号。
  • backlog:这个参数指定了操作系统可以挂起(即等待处理)的连接请求的最大数量。当超过这个数量时,新的连接请求可能会被拒绝。需要注意的是,这个值并不直接对应于队列中的最大连接数,而是操作系统用来处理并发连接请求的一个参数。

返回值

  • 监听成功时返回0
  • 监听失败时返回-1

函数作用

  • 设置监听状态:listen() 函数将 sockfd 指定的套接字设置为监听状态,使其能够接收来自客户端的连接请求。
  • 维护请求队列:操作系统会为处于监听状态的套接字维护两个队列:
    未完成连接队列(SYN_RCVD):这个队列用于存放那些已经接收到客户端的SYN包,但尚未完成三次握手过程的连接请求。
  • 已完成连接队列(ESTABLISHED):当三次握手过程完成后,连接请求会被移动到这个队列中,等待服务器端的 accept() 函数来接受。
  • 控制并发连接:通过 backlog 参数,listen() 函数帮助服务器控制可以同时处理的并发连接数量,从而避免系统资源的过度消耗。

accept()

accept() 函数: 接受一个客户端的连接请求,并返回一个新的套接字(socket)描述符,用于与客户端进行后续的通信。常用于TCP协议。

#include <sys/types.h>  
#include <sys/socket.h>  int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数说明

  • sockfd:这是一个套接字描述符,用于指定服务器端的监听套接字。这个套接字是之前通过- socket()函数创建的,并且已经通过bind()函数绑定了特定的IP地址和端口号,还通过listen()函数设置为监听状态。
  • addr:这是一个指向sockaddr结构的指针,用于存储连接请求的客户端的地址信息。如果调用者不关心客户端的地址信息,可以将此参数设置为NULL。但通常,为了后续与客户端的通信,我们需要知道客户端的地址信息。
  • addrlen:这是一个指向socklen_t变量的指针,该变量在调用前应该被设置为addr所指向的sockaddr结构的大小。在调用accept()后,该变量会被更新为实际存储在addr中的地址信息的大小。

返回值

  • 成功时,accept()函数返回一个非负的整数,即新创建的套接字描述符。
  • 失败时,返回-1,并设置errno以指示错误原因。

函数作用

  • 接受连接请求:当服务器端的监听套接字收到一个客户端的连接请求时,accept()函数会被调用以接受这个请求。如果监听套接字当前没有连接请求,accept()函数会根据套接字的阻塞/非阻塞属性来决定是立即返回错误还是等待直到有连接请求到来
  • 创建新套接字:一旦accept()函数接受了一个连接请求,它就会为这次连接创建一个新的套接字描述符,并返回这个描述符给调用者。这个新的套接字描述符用于后续的通信操作,如发送和接收数据
  • 返回客户端信息(如果addr不为NULL):accept()函数还会将连接请求的客户端地址信息存储在addr所指向的sockaddr结构中,并通过addrlen参数返回实际存储的字节数。这样,服务器就可以知道是哪个客户端发起的连接请求。

connect()

connect() 函数用于客户端程序,以建立与服务器之间的连接。常用于TCP协议。

#include <sys/types.h>  
#include <sys/socket.h>  int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数说明

  • sockfd:这是一个套接字描述符,用于指定要发起连接的客户端套接字。这个套接字是之前通过socket()函数创建的。
  • addr:这是一个指向sockaddr结构的指针,包含了目标服务器的地址信息,包括IP地址和端口号。在实际编程中,由于sockaddr是一个通用的地址结构,通常会使用其特定类型(如sockaddr_in对于IPv4)来方便地设置地址和端口。
  • addrlen:这个参数指定了addr所指向的地址结构的大小,通常是通过sizeof()运算符来获取的,如sizeof(struct sockaddr_in)。

返回值

  • 如果连接成功,函数返回0;
  • 如果连接失败,则返回-1,并设置全局变量errno以指示错误原因。

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

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

相关文章

spark shell

1.进行shell命令行 spark-shell 2.创建RDD 2.1 读取文件创建RDD 2.1.1读取linux文件系统的文件创建RDD --需要保证每一个worker中都有该文件 val data1 sc.textFile("file:/opt/file/word.txt") 2.1.2读取hdfs文件系统上的文件创建RDD val data2sc.textFile("…

使用小波分析实现文字种类自动识别

文章目录 数据简介开始实验小波分解得出结果结果分析误差分析 数据简介 各找一篇中文&#xff0c;日文&#xff0c;韩文&#xff0c;英文&#xff0c;俄文较长的学术论文。将论文转化为JPG格式。拆分每张JPG生成更多小的JPG。最终获得很多5个不同语言的JPG并且自带标签。数据链…

Volatility:分析MS10-061攻击

1、概述 # 1&#xff09;什么是 Volatility Volatility是开源的Windows&#xff0c;Linux&#xff0c;MaC&#xff0c;Android的内存取证分析工具。基于Python开发而成&#xff0c;可以分析内存中的各种数据。Volatility支持对32位或64位Wnidows、Linux、Mac、Android操作系统…

Spring MVC -- 响应

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 今天你敲代码了吗 文章目录 3.响应3.1 返回静态页面3.2 返回HTML代码片段3.3 返回JSON3.4 设置状态码3.5 设置Header设置Content-Type设置其他Header 3.响应 3.1 返回静态页面 静态html页面一般放在static目录底…

连接Redis异常:JedisMovedDataException

redis.clients.jedis.exceptions.JedisMovedDataException: MOVED 5798 192.168.187.138:6379 在使用JAVA API连接redis的时候&#xff0c;出现了异常&#xff1a; 问题的原因 JAVA API实现是redis集群实现方式&#xff0c;而在配置文中就配置的是单结点的方式。 Moved表示使…

【BUG】已解决:error: subprocess-exited-with-error

已解决&#xff1a;error: subprocess-exited-with-error 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发者社区主…

【计算机方向】SCI三区宝刊!国人发文超级友好,录用容易,不能错过!

期刊解析 01 期刊信息 出版商&#xff1a;Academic Press Inc. ISSN&#xff1a;0743-7315 E-ISSN &#xff1a;1096-0848 期刊官方网站:并行与分布式计算杂志 |ScienceDirect.com by Elsevier 期刊投稿网址&#xff1a;https://www.editorialmanager.com/JPDC …

系统设计面试问题:设计​WhatsApp

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 ​ 在这个系统设计面试场景中&#xff0c;我们被要求设计一个类似于 WhatsApp 的消息应用程序。 虽然真正的面试可能会关注应用程序的一个或多个功能&#xff0c;…

2048小游戏,h5,纯前端

部分代码 //scorevar scoreSprite game.add.sprite(10, 10);var scoreGraphics game.add.graphics(0, 0);scoreGraphics.lineStyle(5, 0xA1C5C5);scoreGraphics.beginFill(0x308C8C);scoreGraphics.drawRoundedRect(0, 0, 70, 50, 10);scoreGraphics.endFill();scoreSprite.a…

PyTorch 深度学习实践-循环神经网络(高级篇)

视频指路 参考博客笔记 参考笔记二 文章目录 上课笔记总代码练习 上课笔记 个人能力有限&#xff0c;重看几遍吧&#xff0c;第一遍基本看不懂 名字的每个字母都是一个特征x1,x2,x3…&#xff0c;一个名字是一个序列 rnn用GRU 用ASCII表作为词典&#xff0c;长度为128&#x…

业务系统核心模块资料访问性能优化实战

随着业务系统的云化转型不断推进&#xff0c;业务量呈现显著增长&#xff0c;对业务系统的性能和资源管理提出了更高要求。在这样的背景下&#xff0c;实现系统资源使用与性能指标的均衡成为保障生产系统高效稳定运行的核心任务。 在性能优化的范畴内&#xff0c;核心业务系统对…

苏州金龙海格汽车入选2024中国汽车行业可持续发展实践案例

2024年7月11日-13日&#xff0c;由中国汽车工业协会主办的第14届中国汽车论坛在上海嘉定举办。本届论坛隆重发布了“2024中国汽车行业可持续发展实践案例”&#xff0c;苏州金龙因在坚持绿色可持续发展方面做出的努力和贡献获评2024中国汽车行业可持续发展实践案例“绿色发展”…

【P2P_BMA_P2MP_NBMA】

基本概念介绍 1. BMA&#xff08;Broadcast&#xff09; 广播型多路访问技术&#xff0c;在一个MA&#xff08;多路访问&#xff0c;在一个网段内的节点数量不限制。&#xff09;网络中同时存在广播机制。 特点&#xff1a; 允许将数据包广播到网络上的所有主机。路由器之间…

【AI大模型Agent探索】深入探索实践 Qwen-Agent 的 Function Calling

系列篇章&#x1f4a5; No.文章1【Qwen部署实战】探索Qwen-7B-Chat&#xff1a;阿里云大型语言模型的对话实践2【Qwen2部署实战】Qwen2初体验&#xff1a;用Transformers打造智能聊天机器人3【Qwen2部署实战】探索Qwen2-7B&#xff1a;通过FastApi框架实现API的部署与调用4【Q…

PyTorch 深度学习实践-卷积神经网络基础篇

视频指路 参考博客笔记 参考笔记二 文章目录 上课笔记代码实现作业实现 上课笔记 如果一个网络全都是由线性层串联起来&#xff08;torch.nn.Linear(xx, yy)&#xff09;&#xff0c;就叫他全连接的网络(左边节点到右边节点任意两个都存在权重) 先看一下吴恩达或者李宏毅老师…

QT通用配置文件库(QPreferences)

QT通用配置文件库(QPreferences) QPreferences项目是基于nlohmann/json的qt可视化配置文件库&#xff0c;将配置保存成json格式&#xff0c;并提供UI查看与修改&#xff0c;可通过cmake可快速添加进项目。默认支持基本类型、stl常用容器、基本类型与stl容器组成的结构体&#…

【Git标签管理】理解标签 | 创建标签 | 查看标签 | 删除标签 | 推送标签

目录 1.理解标签 2.创建标签 3.查看标签 4.删除本地仓库的标签 5.推送标签 6.删除远程仓库的标签 1.理解标签 Git提供一个打标签的功能tag&#xff0c;对某一次事务/提交的表示&#xff08;作用/意义&#xff09;。标签 tag &#xff0c;可以简单的理解为是对某次 comm…

Java(二十二)---队列

文章目录 前言1.队列(Queue)的概念2.Queue的使用3.队列的模拟实现4.循环队列5.双端队列6.面试题[1. 用队列实现栈](https://leetcode.cn/problems/implement-stack-using-queues/description/)[2. 用栈实现队列](https://leetcode.cn/problems/implement-queue-using-stacks/de…

人工智能导论-机器学习

机器学习概述 概述 本章主要介绍的机器学习的概念、发展历程、发展趋势、相关应用&#xff0c;着重拓展机监督学习和无监督学习的相关知识。 重点&#xff1a;机器学习的定义和应用&#xff1b; 难点&#xff1a;机器学习算法及分类。 机器学习 - 重要性 MachineLeaning出…

<数据集>钢板缺陷检测数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;1986张 标注数量(xml文件个数)&#xff1a;1986 标注数量(txt文件个数)&#xff1a;1986 标注类别数&#xff1a;7 标注类别名称&#xff1a;[crescent gap, silk spot, water spot, weld line, oil spot, punchin…