深入理解Socket API与TCP协议:网络编程基础与字节序解析 永州可靠营销推广招聘信息
栏目:广告推广 发布时间:2026-01-15
[] [] 在 TCP/IP 协议里,“IP 地址加上 TCP 或者 UDP 端口号”能够唯一地标识网络通讯里的一个进程,“IP 地址与端口号相结合”就被称作

[]

[]

在 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>


# 展会网站推广软文怎么写  # 放在  # 天猫怎么做网站推广的  # 临沂网站建设优化  # 魔力盒网站建设素材视频  # 普通笔记可以营销推广吗  # 横沥网站关键词优化价格  # 盐田网站优化及营销方案  # 抚州谷歌seo公司  # 产品外贸营销推广方案  # 网站推广建设方案模板  # 哪种类型  # 合肥seo公司推荐哪家  # 推广内部券网站  # 建设网站结构最好的方法  # 湖北全网营销推广机构  # 福州抖音seo代理  # 网站建设有哪些推广方式  # 推广网站搭建成本  # 辽宁营销推广厂家  # 汕尾网站建站推广  # 巩义网站seo  # 转换为  # 深入理解Socket API与TCP协议  # 网络编程基础与字节序解析  # 的是  # 端口号  # 多字  # 是一个  # 都有  # 相关内容  # 将其  # 一地  # 深入理解Socket API与TCP协议:网络编程基础与字节序解析  # 之分  # 区中  # 它用  # 返回值  # 网络编程  # 网络地址  # 是在  # 也有  # 成了 


相关文章: 广东百度推广活动,助力企业智能营销新升级,营销型网站推广方案项目  广州百度推广费用记账,优化成本管理的关键策略,优酷土豆网站推广  掌握了这9个推广的qq沟通技巧,轻松提高转化率!  惊掉下巴!趣头条严查广告联盟代理商,*广告也敢放!  广告联盟怎么接单赚钱?单子、cpc单子、单子哪个更赚钱?  福建百度推广咨询工具哪个好用?,石景山网站建设全网推广  福建百度推广账户不支持无效赔付,这对企业意味着什么?,超市如何引流与推广营销  app线下推广之校园app地推活动应该如何进行?  广东百度推广欺诈事件解析,企业如何规避陷阱?,丰台母婴种草营销推广招聘  网站加入广告联盟营销的4大优点以及成功赚钱的2大要素!  广州百度推广代运营,助力企业数字营销新突破,定陶网站建设培训  为什么网站的原创文章收录了但是无排名?主要是这几个原因!  广州百度推广的费用标准解析,衡阳网站建设路火锅  加入百度广告联盟有哪些好处?申请条件有哪些?  广告推广赚钱是什么意思?怎么做?  广告联盟上的网赚形式有哪些优势?  网赚广告联盟是什么?广告联盟怎么赚钱?  app推广如何实现快速变现赚钱?  没本钱怎么在手机一天赚500?“趣闲赚”分享推广做任务赚钱玩法介绍  可以单人做任务来赚钱的项目有哪些?有哪些靠谱的平台推荐?  广州百度推广图片的关键意义与实用指南,衡水网站建设搭建  2020年适合上班族的三个副业赚钱项目,基本无门槛,快速赚钱!  福建百度推广没接到电话会怎么样?,顺庆区网络推广网站优化  广州百度推广产品深度分析,精准营销时代的必备利器,招聘网站建设需求分析  广州百度推广到底还要不要做?,南昌网站建设路酒店  网赚游戏真的很赚钱吗?揭秘网赚游戏背后的真实秘密!  广州百度推广的多种形式及收费方式详解,如何运用网站推广软装  福建百度推广没有咨询量怎么办?实用建议提升转化率,加盟推广那个网站好  广州百度推广开户渠道有哪些类型的总结分析,营销推广员工  想要让目标用户知道你的产品,这七种免费的网站推广方法必须掌握!  想要网站通过广告联盟赚钱必须要明白这三者之间的关系!  广州百度推广产品哪种渠道好排行榜,奶酪营销推广方案  广告联盟源码下载平台有哪些,免费版的源码在哪可以下载?  广州百度推广任务的高效策略与执行方法,廊坊好的网站优化推广  广州百度推广关键词怎么设置好推荐,天津软文推广营销哪家好  广州百度推广搭建的关键步骤与策略解析,重庆涪陵网站建设哪家好  广州百度推广为什么接不到电话了?,温州营销推广怎么投放  四个不耽误上班的网上兼职赚钱副业分享  福建百度推广为什么接不到电话了?深入剖析原因与解决办法,智慧营销系统推广简历  在推广项目的时候使用短链有什么好处?  广州百度推广,个人如何开户操作指南,惠州网站推广运营中心  如何利用闲鱼引流推广赚钱?做好了日赚几百不是问题!  网赚的优势有哪些?好羡慕这些日入上千的大神!  app推广之在APP Store上该怎么推广?  百度广告联盟怎么加入​?申请条件有哪些?  广州百度推广开户返点是什么意思?,诸城网站推广价格多少钱  app长期运营推广的5个全网覆盖、精细化运营思路!  广州百度推广代运营服务靠谱么?,网贷平台营销推广  广东百度推广跟踪,助力精准市场营销,长春网站建设包括哪些公司  没本钱怎么在手机一天赚500?这3个简单无门槛的方法轻松实现! 


相关栏目: 【 广告资讯37196 】 【 广告推广143353 】 【 广告优化89630