深入理解Socket API与TCP协议:网络编程基础与字节序解析 眉山推广保洁招聘网站
发布时间 - 2026-01-15 18:39:16 点击率:次[]

[]
在 TCP/IP 协议里,“IP 地址加上 TCP 或者 UDP 端口号”能够唯一地标识网络通讯里的一个进程,“IP 地址与端口号相结合”就被称作。
在 TCP 协议里,建立连接的两个进程各自都有一个标识。这两个进程组成的 pair 能够唯一地标识一个连接。“插座”本身就有其特定含义,所以被用来描述网络连接的一对一关系。
TCP/IP 协议最早是在 BSD UNIX 上得以实现的。为 TCP/IP 协议所设计的应用层编程接口被称作。
[]
二、网络字节序
我们已知,内存中的多字节数据对于内存地址存在大端和小端的区别。磁盘文件中的多字节数据对于文件中的偏移地址也有大端小端之分。网络数据流同样具备大端小端之分。那么,怎样去定义网络数据流的地址呢?发送主机一般会把发送缓冲区里的数据依据内存地址从低到高的次序进行发出。接收主机则把从网络上接收到的字节依次存放在接收缓冲区中,同样是按照内存地址从低到高的顺序来保存。所以,对于网络数据流的地址要这样规定:先发出的那些数据对应的是低地址,而后发出的数据对应的是高地址。
TCP/IP 协议规定,网络数据流的字节序应采用大端字节序,也就是说在这种字节序中,低地址对应的字节是高字节。四十五节的 UDP 段格式中,地址 0 到 1 为 16 位的源端口号。若此端口号是 1000(0x3e8),那么地址 0 是 0x03,地址 1 是 0xe8,即先发送 0x03,接着发送 0xe8。在发送主机的缓冲区中,这 16 位也应是低地址存 0x03,高地址存 0xe8。如果发送主机是小端字节序,那么这 16 位会被这样解释,而非 1000。所以,发送主机在把 1000 填到发送缓冲区之前,需要进行字节序的转换。同样地,若接收主机是小端字节序,当接到 16 位的源端口号时,也需要做字节序的转换。而如果主机是大端字节序,无论是发送还是接收,都不需要进行转换。同样地,对于 32 位的 IP 地址,需要考虑网络字节序以及主机字节序方面的问题。
为让网络程序具备可移植性,让相同的 C 代码在大端计算机和小端计算机上编译后都能正常运转,能够调用以下这些库函数来进行网络字节序与主机字节序的转换。
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="prettyprint"><code class=" hljs actionscript">#<span class="hljs-preprocessor"><span class="hljs-keyword">include</span> <a style='color:#0000CC;font-size:15px;' rpa/inet.h> 定义了一个名为 htonl 的函数,该函数的参数是一个 uint32_t 类型的 hostlong,函数的返回值也是 uint32_t 类型。</span> 这个函数名为 htons,它接收一个 16 位的主机短整型数值作为参数,然后进行相应的网络字节序转换操作,最终返回转换后的网络字节序的 16 位数值。 定义了一个名为 ntohl 的函数,该函数接收一个 uint32_t 类型的参数 netlong,并返回一个 uint32_t 类型的值。 定义一个函数 ntohs,它接收一个无符号 16 位整数类型的参数 netshort,函数返回值也为无符号 16 位整数类型。 h 表示host n 表示network l 表示<span class="hljs-number">32</span>位长整数 s 表示<span class="hljs-number">16</span>位短整数。 如果主机的字节序是小端的,那么这些函数会对参数进行相应的大小端转换之后再返回。如果主机的字节序是大端的,这些函数就不会进行转换,而是将参数原原本本地返回。</code></pre></p>三、IP地址转换函数
早期使用的是一下函数:
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="prettyprint"><code class=" hljs vala"><span class="hljs-preprocessor">#include <sys/socket.h></span> <span class="hljs-preprocessor">#include <netinet/in.h></span> <span class="hljs-preprocessor">#include <a style='color:#0000CC;font-size:15px;' rpa/inet.h></span> <span class="hljs-keyword">int</span> inet_aton(<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *cp, <span class="hljs-keyword">struct</span> in_addr *inp); in_addr_t inet_addr(<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *cp); <span class="hljs-keyword">char</span> *inet_ntoa(<span class="hljs-keyword">struct</span> in_addr in); 只能处理IPv4的ip地址 不可重入函数 注意参数是<span class="hljs-keyword">struct</span> in_addr</code></pre></p>现在多使用的是:
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="prettyprint"><code class=" hljs vala"><span class="hljs-preprocessor">#include <a style='color:#0000CC;font-size:15px;' rpa/inet.h></span> <span class="hljs-keyword">int</span> inet_pton(<span class="hljs-keyword">int</span> af, <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *src, <span class="hljs-keyword">void</span> *dst); <span class="hljs-comment">//将字符串转换为网络地址</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *inet_ntop(<span class="hljs-keyword">int</span> af, <span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *src, <span class="hljs-keyword">char</span> *dst, socklen_t size); <span class="hljs-comment">//将网络地址转换为字符串</span> 支持IPv4和IPv6 可重入函数</code></pre></p>其中,它不仅能够转换 IPv4 的相关内容,还能够转换 IPv6 的相关内容,正因如此,其函数接口为 void *。
四、数据结构
很多网络编程函数诞生于 IPv4 协议之前,当时使用的是结构体。为了实现向前兼容,现在这些函数退化成了(void *)的作用,即传递一个地址给函数。而这个函数具体是哪种类型,由地址族来确定。之后,函数内部会再将其强制类型转化为所需的地址类型。
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="prettyprint"><code class=" hljs cs"><span class="hljs-keyword">struct</span> sockaddr { sa_family_t sa_family; <span class="hljs-comment">地址族,其格式为 AF_xxx 。</span> <span class="hljs-keyword">char</span> sa_data[<span class="hljs-number">14</span>]; <span class="hljs-comment">协议地址为 14 字节。</span> }; <span class="hljs-keyword">struct</span> sockaddr_in { 内核的地址族类型为 sin_family;sin_family 是一个特定的地址族类型;该地址族类型被用于内核相关的操作中;它在网络编程等领域有重要作用。<span class="hljs-comment">/* Address family */</span> __be16 sin_port;<span class="hljs-comment">/* Port number 端口号*/</span> <span class="hljs-keyword">struct</span> in_addr sin_addr; <span class="hljs-comment">/* Internet address IP地址*/</span> <span class="hljs-comment">将其填充至 `struct sockaddr` 的大小。</span> unsigned <span class="hljs-keyword">char</span> __pad[__SOCK_SIZE__ - <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">short</span> <span class="hljs-keyword">int</span>) - <span class="hljs-keyword">sizeof</span>(unsigned <span class="hljs-keyword">short</span> <span class="hljs-keyword">int</span>) - <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">struct</span> in_addr)]; }; <span class="hljs-comment">/* Internet address. */</span> <span class="hljs-keyword">struct</span> in_addr { __be32 s_addr; <span class="hljs-comment">// 32位地址</span> }; <span class="hljs-keyword">struct</span> sockaddr_in6 { unsigned <span class="hljs-keyword">short</span> <span class="hljs-keyword">int</span> sin6_family;<span class="hljs-comment">/* AF_INET6 */</span> __be16 sin6_port; <span class="hljs-comment">关于运输层的端口号</span> __be32 sin6_flowinfo; <span class="hljs-comment">IPv6 流信息的控制属性。</span> <span class="hljs-keyword">struct</span> in6_addr sin6_addr; <span class="hljs-comment">/* IPv6 addressip地址128位*/</span> __u32 sin6_scope_id; <span class="hljs-comment">范围标识(在 RFC2553 中是新的)</span> }; <span class="hljs-keyword">struct</span> in6_addr { union { __u8u6_addr8[<span class="hljs-number">16</span>]; <span class="hljs-comment">// 可以使用16个8位的地址</span> __be16 u6_addr16[<span class="hljs-number">8</span>]; <span class="hljs-comment">// 8个16位地址</span> __be32 u6_addr32[<span class="hljs-number">4</span>]; <span class="hljs-comment">// 4个32位地址</span> } in6_u; <span class="hljs-preprocessor">#<span class="hljs-keyword">define</span> s6_addr in6_u.u6_addr8</span> <span class="hljs-preprocessor">#<span class="hljs-keyword">define</span> s6_addr16 in6_u.u6_addr16</span> <span class="hljs-preprocessor">#<span class="hljs-keyword">define</span> s6_addr32 in6_u.u6_addr32</span> }; <span class="hljs-preprocessor">#<span class="hljs-keyword">define</span> UNIX_PATH_MAX 108</span> <span class="hljs-keyword">struct</span> sockaddr_un { sun_family 属于 __kernel_sa_family_t 类型。<span class="hljs-comment">/* AF_UNIX */</span> <span class="hljs-keyword">char</span> sun_path[UNIX_PATH_MAX];<span class="hljs-comment">/* pathname */</span> };</code></pre></p>IPv4 的地址格式在 /in.h 中被定义,它用结构体来表示,其中包含 16 位端口号以及 32 位 IP 地址。IPv6 的地址格式也在 /in.h 中被定义,它用结构体来表示,此结构体包含 16 位端口号、128 位 IP 地址和一些控制字段。UNIX 的地址格式在 sys/un.h 中被定义,用 sock-结构体来表示。各种地址结构体的开头是相同的。其前 16 位表示整个结构体的长度,不过并非所有 UNIX 的实现都有长度字段,像 Linux 就没有。而后 16 位表示地址类型。IPv4 的地址类型定义为常数,IPv6 的地址类型定义为常数,Unix 的地址类型也定义为常数。这样,只要能够获取到某种结构体的首地址,并且无需知晓具体属于哪种类型的结构体,就能够依据地址类型字段来确定结构体中的内容。API 能够接受各种类型的结构体指针作为参数,像 bind 等函数就是如此。这些函数的参数需设计为 void 类型,这样就能接受各种类型的指针。然而,sock API 的实现早于 ANSI C 标准化,在那时候还不存在 void 类型,所以这些函数的参数都用 *类型来表示,在传递参数之前需要进行强制类型转换,例如:
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="prettyprint"><code class=" hljs cs"><span class="hljs-keyword">struct</span> sockaddr_in servaddr; <span class="hljs-comment">/* initialize servaddr */</span> bind(listen_fd, (<span class="hljs-keyword">struct</span> sockaddr *)&servaddr, <span class="hljs-keyword">sizeof</span>(servaddr));</code></pre></p>
# 深入理解Socket API与TCP协议:网络编程基础与字节序解析
# 深入理解Socket API与TCP协议
# 网络编程基础与字节序解析
# 的是
# 端口号
# 多字
# 是一个
# 都有
# 相关内容
# 将其
# 一地
# 转换为
# 之分
# 区中
# 它用
# 返回值
# 网络编程
# 网络地址
# 是在
# 也有
# 成了
# 哪种类型
# 放在
# 临沂网站建设实例
# 儋州湖南网站建设
# 上海网络网站建设公司
# 千亿网站建设
# 合肥网站推广怎么样
# 宁波研发网站建设推广
# 网站建设小海报图片
# 自然离不开营销的推广
# 雷神代刷推广网站靠谱吗
# 义乌市网站推广公司
# 许昌产品推广营销
# 东宁网站优化排名推广
# 宁波湖南网站优化推广
# 智能网站优化活动策划
# 营销的推广
# 广东网站推广定制哪家好
# 桐城seo优化哪好
# 信用卡营销推广文案
# 公司关键词排名怎么合作
# 深圳推广网站服务商
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
广州百度推广投资,企业发展的明智选择,河南推广大数据营销
潍坊SEO优化,从关键词布局到搜索引擎排名提升之路,网站一定要花钱找人优化
广州百度推广通在哪里?全面解析及实用指南,520 营销推广怎么做
福建百度推广运营顾问工作是什么?,南丰企业网站建设推广
SEO学堂:开启数字营销新时代,全面提升网站排名与流量,文山ai营销推广方案
探索未知,我的成长之旅与自媒体营销的融合,seo中标题写法
微信收款语音播报怎么设置?学会再也不用担心收不到钱啦
手机丢后微信钱包被刷走两万?几步操作就能锁死钱包
山西SEO大法哪家强介绍本地SEO服务佼佼者,seo.sem工作日常
广州百度推广年费,助力企业精准营销,南安卫浴网站推广
福建百度推广的费用高吗?多少钱?,网站建设创意方法
SEO兼职:如何通过SEO兼职实现收入增长与职业突破,濮阳网站建设官网
福建百度推广消费不出去怎么办?,营销和推广|视频|怎么做
青岛SEO,探索数字时代的城市营销秘籍,沈阳放心的网站优化推广
邯郸SEO技术服务,助力企业高效提升网络曝光度,成都数据优化招聘网站
介绍宁夏抖音SEO价格,性价比之选,助力企业品牌腾飞,上海seo设计
咸宁SEO推广哪家厉害?揭秘行业内的佼佼者,桔子seo如何查询权重
探索自媒体营销的奥秘,如何成为一名成功的SEO加盟代理,宣城营销推广哪家专业
自媒体营销新纪元,如何利用社交媒体打造个人品牌?,青岛抖音seo商家
娄底淘宝SEO优化,打造电商新篇章的关键策略,深圳布吉营销推广
广州百度推广费用记账,优化成本管理的关键策略,优酷土豆网站推广
祖庙抖音搜索SEO优化,打造你的品牌之光,seo优化托管方案
横岗SEO优化,打造企业网络品牌新高度,哪些是免费流量 淘宝seo
老科熬夜找12款*网站推荐,视频啦、电影淘淘等超好用
2月23日网商银行安全检验技术与系统入选国家级项目,有何亮点?
SEO新站优化指南:快速提升排名的必备技巧,海珠网站推广哪家有名
福建百度推广点击费用到底是多少?,潮州网站推广找哪里
郑州SEO矩阵公司,助力企业腾飞的关键策略,承德网站建设广告词优化
SEO努力:提升网站排名的关键策略,网站建设微企动力
SEO确实是企业增长的关键,这些技巧让你走在行业前沿,山东网站建设信息
锡山SEO推广,如何让你的品牌在数字海洋中脱颖而出?,东营机场建设招标网站
外贸独立站SEO,打造全球贸易的隐形翅膀,SEO优化松松
介绍巴南专业SEO优化,效果显著,助力企业腾飞,京东关键词排名低
广州SEO软件首选乐云SEO,专业赋能,助力企业高效招商,香港seo推广优化公司
武汉SEO公司代理,助力企业网络营销,提升品牌影响力,魏则西后seo前景
济南优化网站排名SEO攻略,助力企业腾飞之路,力盟seo优化公司
以用户体验为核心,打造SEO新境界,seo基础入门知识大全
广州百度推广条件详解,助力企业数字化营销,网络营销推广个人
如何通过百度推广优化广州地区配图效果,商丘网站建设技术公司
介绍SEO关键词优化软件S,助力企业网站排名的利器,泉州seo优化教程
SEO优化提升关键词外推,让您的网站在搜索引擎中脱颖而出,廊坊优化网站怎么样
SEO挣钱之道:如何通过SEO实现网络盈利,宁晋网站建设商家
普陀短|视频|SEO推广攻略,助力短|视频|内容脱颖而出,衡水网站排名优化多少钱
SEO排位:如何通过精准策略提升网站排名,获得流量与转化,林海网络推广营销
SEO指:如何通过精准优化提高网站流量和转化率,无锡论坛营销推广要多久
探索未知,自媒体营销的奥秘与策略,济宁营销线上推广
德阳SEO排名优化公司,让您的网站在竞争激烈的市场中脱颖而出,抖音短视频营销与推广
如何选择合适的SEO加盟品牌?,seo优化项目经验心得
全国SEO优化步骤,关键词布局的艺术与方法,网站积分seo优化
关键词挖掘在项目SEO中的应用与步骤,多页面seo

