<转>Socket编程——基础介绍

本文深入探讨了Unix网络编程中的Socket基础知识,包括IPv4地址结构、通用地址结构及新的通用地址结构。此外,还详细介绍了字节序、字节操纵函数、字符串处理函数等内容,并提供了实用的编程技巧。

最近系统的看了下unix网络编程的一些内容,对socket的理解有了进一步的加深,在看APUE的时候,那会儿看socket上面介绍的比较少,只是模糊的懂了如何去写一个简单的TCP服务端和客户端,对其中一些注意的点,以及实现的原理没有过多的去研究。这是我自己总结的socket编程的第一篇,基本就是介绍一些基础性的东西。

这个只是在IPV4上的一些socket编程,对于IPV6暂不涉及。下面对unix网络编程卷一第三版简称为unpV13e

地址结构

提到地址结构我们一般使用的是最基本的地址结构。IPV4的地址结构为struct sockaddr_in 里面包含了一些字段。如sin_family, sin_addr, sin_port.对于sin_addr这是一个结构体类型的。声明是struct in_addr.struct sockaddr_in是定义在<netinet/in.h>中的。而对于结构体中所 涉及到的变量的定义一般包含在<sys/types.h><sys/socket.h>. 所以一般在编程的时候需要注意将这些头文件引用。

上述详细的讨论可以参看UnpV13e的p56-p57。里面的讨论比较详尽。

接着我们还有一类地址结构,称作通用地址结构。这是地址结构的引入是为了对各种socket的地址结构做一个统一的,通用地址的定义是struct sockaddr 舍去了后缀。这个地址结构的使用我们一般是用在类型强转上面。例如bind函数第二个参数需要强转为struct sockaddr 遵循Richard的思想,将struct sockaddr精简一下,使用define将其定义为SA. 如此便省去敲击的次数。

最后还有一类更加通用的地址结构,称作新的通用地址结构. 它比之前的地址结构更具通用性,能够存储任意大小的结构体。struct sockaddr_storage这个结构一部分是对用户透明的。所以使用的时候我们一般不需要担心空间不够。

字节序

不同的机器上,使用的字节序一般是不同的,一般称作大端和小端。我们为什么要讨论这个问题呢?因为作为网络编程,双方之间的通信要一致。比如我这边是使用的小端,而对方机器是大端,那么解析后的结果就是错乱的,因此我们需要做的就是将其统一起来。需要一个能够将本地转为网络字节,再从网络字节转为本地,这之间的细节包括网络字节转本地的时候需要对机器进行大小端的判断。这样就避免了错乱。我们自己如何来判断一个机器的大小端呢?

我们使用的是联合这个数据类型来实现的。具体的实现参看我的Gits,一般linux上使用的是小端字节序。

讨论了字节序后我们需要知道的是如何将本地和网络字节序进行互换,一般提供了一些接口,我们一一来简单的讨论下。

TCP中一般是16位的端口号和32位的IPV4地址。而我们在实现本地转网络的时候不需要去考虑本地是大端还是小端了,只需要考虑需要转的内容长度了。因为从如下的四个函数可以看出htons,htonl,ntohs,ntohl 这边的n代表network,h代表host, l代表long,s代表short。我们把l视为32位的,将s视为16位的。这样在转换ip和port的时候就很方便了。但是需要注意的就是我们在使用这些函数的时候需要注意的就是我们的参数是整型的,这一点需要注意到。

字节操纵函数

对一个结构体进行初始化,或是数组初始话的时候我们要做的就是使用一些字节操纵函数来实现。一般我们会想到使用memset这个函数,同样在linux中有另外一组不错的函数,是BSD所提供的,称作bzero bcmp bcopy 以字节来实现相关的操作,而不是以c语言中string的这个概念中所做的那样。

使用bzero在网络编程中是又好处的。因为参数少,直接将目标初始化成0. 而memset多一个参数。还有一点就是memset无法处理字节重叠的这个问题。而bzero是可以解决的。这一块使用bzero可以省去一些麻烦。这个函数是包含在<strings.h>这个头文件中的。而memset是包含在<string.h>中的。

字符串处理的函数

一般我们的输入都是基于字符串这个格式的,使用的比较多,所以如果提供一个直接将字符串格式的地址或是端口转换成网络字节序的函数的话,那么我们就会变得更加的方便。

这边也有两组不一样的函数,一般我们倾向使用后面一组。 好了先说说第一组的函数。

  • inet_aton ====> 将点分十进制的内容转换成网络字节序,参数是两个,一个是strptr,另一个是地址addrptr。详情参看手册页。
  • inet_addr ====> 几乎淘汰,有一些弊端
  • inet_ntoa ====> 将网络字节序的转换为本地的字符串格式。 参数只有一个。

这组函数用起来还是可以的。不过更流行的使用是使用下面的这两个。

  • inet_pton ====> 将本地的字符串的描述转为网络字节序,参数有三个。
  • inet_ntop ====> 将网络字节序的转为本地的字符串形式。参数有四个。

不过为了防止错误,在<netinet/in.h>中有一个好的定义,为INET_ADDRSTRLEN 大小定义为16,这就保证了我们的大小不会溢出。

上面的两组函数都包含在<arpa/inet.h>这个头文件中。

但是下面的那两个函数有一个不太好的就是我们要确定sock的类型,而不是直接传入一个地址结构,所以Richard给出了这样的一个封装函数,处理起来应该就是比较轻松一些。

char *sock_ntop(const sockaddr *sa, socklen_t salen)
{
    char  portstr[8];
    static char str[128];  //unix domain is largest

    switch(sa->sin_family)
    {
        case AF_INET:
        {
            struct sockaddr_in *sin = (struct sockaddr_in *)sa;
            if(inet_ntop(AF_INET,&sin->sin_addr,str,sizeof(str)) == NULL)
                return NULL;
            if(ntohs(sin->sin_port) != 0)
            {
                snprintf(portstr,sizeof(portstr),":%d",ntohs(sin->sin_port));
                strcat(str,portstr);
            }
        return str;
        }
    }
}

另外还有其他几个函数,实现都可以在源代码中找到。因为这些函数比较好的一个点就是我们调用的时候省去了很多的细节。

socket的一部分内容基本上是介绍完了。在字节流套接字上,read和write是不同于文件的I/O的。所以还有一套不错的函数

  • readn
  • written
  • readline

这三个函数会在下一篇中给出,下一篇将这些函数实现。并且又另一个版本的叫RIO。虽然如出一辙,但是还有一些更加不错的函数提供出来。这对 网络编程中I/O提供的一个好的解决。

转载于:https://www.cnblogs.com/sexybear/p/4502019.html

多源数据接入 支持校园各业务系统数据接入:包括教务系统(学生成绩、课程信息)、学工系统(奖惩记录、资助信息)、后勤系统(宿舍分配、能耗数据)、图书馆系统(借阅记录、馆藏信息)、一卡通系统(消费数据、门禁记录)等。 接入方式:提供数据库直连(MySQL、SQL Server)、文件导入(CSV、Excel、JSON)、API 接口调用等多种方式,支持实时同步与定时批量同步。 数据标准化与治理 建立校园数据标准体系:统一数据格式(如日期格式、学号编码规则)、定义核心数据元(如 “学生” 包含学号、姓名、专业等必选字段)、规范代码集(如性别代码 “1 - 男,2 - 女”)。 数据清洗:自动检测并处理缺失值、重复值、异常值(如成绩 > 100 分),通过规则引擎实现数据校验(如 “学生年龄需在 16-30 岁之间”)。 元数据管理:记录数据来源、格式、更新频率、负责人等信息,生成数据血缘图谱,追踪数据从产生到应用的全生命周期。 二、数据共享与交换核心功能 分布式数据存储 基于 Hadoop HDFS 实现海量数据存储:结构化数据(成绩、消费记录)存入 HBase,非结构化数据(文档、图片、视频)直接存储于 HDFS,日志类数据通过 Flume 采集至 HDFS。 支持数据分片与副本机制,确保数据高可用(默认 3 副本存储),满足校园 PB 级数据存储需求。 数据交换引擎 构建点对点数据交换通道:各部门系统可通过交换引擎向平台上传数据或申请获取授权数据,支持同步 / 异步交换模式。 交换流程管理:定义数据交换规则(如 “学工系统每日向平台同步新增学生信息”),记录交换日志(成功 / 失败状态、数据量),失败时自动重试。 数据脱敏:对敏感数据(如身份证号、银行卡号)在交换过程中进行脱敏处理(如显示 “110********5678”),兼顾共享与隐私保护。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值