当前位置: 首页 > news >正文

Linux Socket 编程(TCP:socket, bind, listen, accept,connect, write, read;UDP:sendto, recvfrom)

文章目录

  • 1、预备知识
    • 1.1 网络字节序
    • 1.2 `客户端`/`服务器`模型
  • 2、编程接口 BSD Socket
    • 2.1 Socket是什么
    • 2.2 基本的 Socket 编程接口
      • 2.2.1 Socket API 概览
      • (1)socket():创建 socket
      • (2)bind():(服务器) 绑定 socket,绑定地址和端口
      • (3)listen():(服务器) 监听 socket ,设置 Socket 为监听模式
      • (4)accept():(服务器) 接受(客户端)连接
      • (5)connect():(客户端) 连接服务器
  • 3、面向连接的 Socket:C/S模型-TCP
    • 数据传输的过程:
    • 3.1 server
    • 3.2 client
  • 4、面向无连接的 Socket:C/S模型-UDP
    • 4.1 server
    • 4.2 client


参考博客:https://www.jianshu.com/p/ca0bbd8700ce

Socket 这个词可以表示很多概念:

概念类别描述
1在TCP/IP协议中,【IP地址+TCP或UDP端口号】唯一标识网络通讯中的一个进程,IP地址+端口号就称为 Socket
2在TCP协议中,建立连接的两个进程各自有一个 Socket 来标识,那么这两个Socket 组成的socket pair就唯一标识一个连接。
Socket 本身有 插座 的意思,因此用来描述网络连接的一对一关系。
3TCP/IP协议最早在BSD UNIX上实现,为TCP/IP协议设计的应用层编程接口 称为Socket API

1、预备知识

1.1 网络字节序

在几乎所有的计算机上,多字节的对象,都被表示为连续的字节序列。

数据的高字节保存在 内存的低地址,称为大端模式(大端序);
数据的高字节保存在 内存的高地址,称为小端模式(小端序)。

0x12345678 这样一个 32 位整数在内存中需要占用四个字节,这四个字节的地址会递增。
若随着地址增加,按照 0x12、0x34、0x56 和 0x78 这样的顺序存入内存,就称为大端序
反之,若随着地址增加,按照 0x78、0x56、0x34、0x12 的顺序存入内存,就称为小端序

大端序和小端序内存布局示意图:

在网络应用中,字节序是一个必须考虑的因素,因为不同机器类型可能采用不同标准的字节序,所以均须按照网络标准转化。

网络传输的标准叫做网络字节序,实际上是大端序
而我们常用的 X86都是小端序,ARM 的字节序实际上是可配置的,但是一般都配置为小端。

在网络编程中不应该假设自己程序运行的主机的字节序,应当使用htonl/htons/ntohs/ntohl之类的函数来在网络字节序主机字节序之间进行转换。

#include<arpa/inet.h>uint32_thtonl(uint32_thostlong);//host to net (long)uint16_thtons(uint16_thostshort);//host to net (short)uint32_tntohl(uint32_tnetlong);//net to host (long)uint16_tntohs(uint16_tnetshort);//net to host (short)

其中h代表host,就是本地主机的表示形式;n代表network,表示网络上传输的字节序;sl代表类型shortlong


1.2客户端/服务器模型

网络上进行通信的各端点,大部分都是遵循客户端/服务器模型的。

一般来说,服务器端具有以下特征:

序号特征
1被动通信
2始终等待来自客户端的请求
3自己参与通信的网络接口端口必须确定
4处理客户端请求后,将结果(响应)返回给客户端

客户端的特征如下:

序号特征
1主动通信
2需要发起请求
3自己参与通信的网络接口端口可以不确定
4发起请求后,需要等待服务器回应结果

服务器可以是有状态的,也可以是无状态的(Stateless),无状态的服务器不会保留两个请求之间的任何信息,而有状态的服务器会记住请求之间的信息。
实际上的服务器一般都能同时并发处理多个客户端的请求。

一个简单的客户机/服务器通信过程如图:


2、编程接口 BSD Socket

2.1 Socket是什么

TCP/IP协议 存在于OS中,网络服务通过 OS 提供,在OS中增加支持TCP/IP的系统调用——Berkeley套接字,如socketconnectsendrecv等。


网络传输概貌:

Socket 是应用层TCP/IP协议族通信的中间软件抽象层

Socket 起源于Unix,而Unix/Linux 基本哲学之一就是一切皆文件,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。
Socket 就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。

Socket是应用层TCP/IP协议族 通信的中间软件抽象层,它是一组接口。在设计模式中,Socket 其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在 Socket 接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

注意:其实 Socket 也没有层的概念,它只是一个facade设计模式的应用,让编程变的更简单。是一个软件抽象层。在网络编程中,大量用的都是通过Socket 实现的。


2.2 基本的 Socket 编程接口

现在的网络编程接口通常是 Socket。
BSD Socket 是事实上的网络应用编程接口标准(API),其它编程语言往往也使用和这套用 C 写成的 Socket 类似的接口。

用 Socket 能够实现网络上的不同主机之间同一主机不同对象之间的数据通信。所以,现在 Socket 已经是一类通用通信接口集合

2.2.1 Socket API 概览


服务器端 先创建socket(),然后与端口绑定bind(),对端口进行监听listen(),调用accept()阻塞,等待客户端连接。
在这时如果有个客户端初始化一个 socket(),然后连接服务器 connect(),如果连接成功,这时客户端与服务器端的连接就建立了。

客户端发送数据请求,服务器接收请求处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
这些接口的实现都是内核来完成。具体如何实现,可以看看 Linux内核。

序号函数原型描述
1intsocket(int domain,int type,int protocol)创建 Socket
2intbind(intsocket,const struct sockaddr*address,socklentaddress_len)绑定地址端口
3intlisten(int socket,int backlog)设置 Socket 为监听模式
4intaccept(int socket,struct sockaddr*restrict address,socklen_t*restrict address_len接受连接
5intconnect(int socket,const struct sockaddr*address,socklentaddress_len连接服务器

(1)socket():创建 socket

在进行 Socket 通信之前,一般调用 socke(2) 函数来创建一个 Socket 通信端点。
socket() 打开一个网络通讯端口,如果成功的话,就像 open() 一样返回一个文件描述符fd,应用程序可以像读写文件一样用read() / write()在网络上收发数据,如果 socket() 调用出错则返回-1。

对于IPv4,domain参数指定为 AF_INET。
对于TCP协议,type 参数指定为SOCK_STREAM,表示面向流的传输协议。
如果是UDP协议,则 type 参数指定为SOCK_DGRAM,表示面向数据报的传输协议。

socket(2)函数原型如下:

#include<sys/types.h>#include<sys/socket.h>intsocket(intdomain,inttype,intprotocol);
序号参数含义
1domain地址类型:
(1)AF_INET(IPv4)
(2)AF_INET6(IPv6)
2type协议类型:
(1)SOCK_STREAM(面向连接)
(2)SOCK_DGRAM(非连接)
3protocol默认填0

如果建立套接字成功,返回一个新的文件描述符fd,失败则返回-1,设置errno。这个函数可能发生的错误:

序号errno 值错误含义
1EPROTONOSUPPORT参数 domain 指定的类型不支持参数 type 或 protocol 指定的协议
2ENFILE核心内存不足,无法建立新的 socket 结构
3EMFILE进程文件表溢出,无法再建立新的套接字
4EACCESS权限不足,无法建立 type 或 protocol 指定的协议
5ENOBUFS、ENOMEM内存不足
6EINVAL参数不合法(invalid)

序号类型示例
1创建 TCP Socketsockfd=socket(AF_INET, SOCK_STREAM, 0);
2创建 UDP Socketsockfd=socket(AF_INET, SOCK_DGRAM, 0);

实际程序中,应该先检查返回值sockfd有效后,再使用。


(2)bind():(服务器) 绑定 socket,绑定地址和端口

创建了 Socket 后,可以调用 bind(2) 函数来将这个 Socket 绑定到特定的地址端口上来进行通信。函数原型如下:

#include<sys/types.h>/* See NOTES */#include<sys/socket.h>intbind(intsockfd,conststruct
http://www.jsqmd.com/news/796268/

相关文章:

  • 如何高效使用B站字幕下载工具:释放视频学习价值的完整指南
  • 奇点大会闭门报告首曝:AI原生联邦学习系统不是升级,而是重构——基于LLM驱动的元协调器(Meta-Orchestrator)架构图谱(含开源PoC链接)
  • 2026全国监控杆采购选型QA测评:从陕西市场看厂商实力与风险规避 - 深度智识库
  • 机器人实时控制中的VLA模型与延迟优化技术
  • Intel RealSense D435i 标定实战:从工具安装到VINS配置全流程解析
  • 从零到一:基于STM32F1与SPL库的lwIP-2.1.2裸机移植实战(ENC28J60驱动适配)
  • SoC自适应雷达信号处理架构在6G与智能驾驶中的应用
  • AI原生迁移学习落地攻坚手册(2026奇点大会闭门报告首次解禁)
  • 2026年江苏充电桩SaaS服务深度横评:社区生态物联解决方案与资金扶持完全指南 - 企业名录优选推荐
  • 终极Mac电源管理指南:如何用SleeperX彻底解决3大电源痛点
  • 广州外墙清洗行业企业盘点:精准选型指南,避开采购雷区 - 深度智识库
  • 1.7.2 掌握Scala函数 - Scala函数种类
  • .NET开发者集成OpenAI API实战指南:从基础调用到生产部署
  • 别再只用默认端口了!手把手教你用Hydra测试Windows 10 RDP弱口令(附字典生成技巧)
  • WinMD:跨平台存储架构的突破性实现与Windows访问Linux RAID解决方案深度解析
  • 不止 Paperxie!9 款 AI 毕业论文写作工具横评:从选题到终稿,谁才是真正的效率之王?
  • 江西省青蜂环保:丰城白蚁防治选哪家 - LYL仔仔
  • Gemini长上下文重塑RAG架构
  • Oracle数据库中的Java概述
  • FileZilla中文乱码终结指南:从字符集原理到一键修复
  • ICC II 布线优化实战:从 route_auto 到 route_opt 的全流程解析
  • 3个理由告诉你为什么Mem Reduct是Windows内存优化的最佳选择
  • 明日方舟智能基建管理工具完整使用指南
  • 终极指南:如何用FanControl轻松掌控Windows风扇散热优化
  • CES 2012启示录:移动互联、生态连接与硬件创新的产业转折点
  • 2026年人才盘点公司榜单分析:值得信赖的人才盘点企业/值得信赖的人才盘点老牌机构/比较不错的人才盘点老牌公司 - 品牌策略师
  • 年轻人的财务小智慧:如何把闲置消费额度变成灵活现金流 - 团团收购物卡回收
  • Honey Select 2 HF Patch:200+插件整合补丁,打造完美游戏体验
  • Excel取消隐藏列的底层原理与4种实战方法
  • CoverM深度解析:如何高效配置PacBio HiFi宏基因组数据覆盖率分析的完整指南