Linux系统编程.NO11——c/s模式和字节序

本文介绍了网络编程的基础知识,包括网络编程的前提条件、常见的网络命令、软件体系结构(C/S与B/S模式)、字节顺序概念及转换函数、以及套接字结构体的详细解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

9.网络编程

9.1.网络编程前提

在正式了解网络编程代码之前,要先熟悉Linux上对于网络的一些常用命令。如ifconfig,ping,netstar,route,还应该了解一些网络参数配置所在文件,如/etc/hosts,/etc/host.conf,/etc/resolv.conf. /etc/sysconfig/network-scripts/ifcfg-eth0.
网络编程的主要目的是要获得其他计算机上提供的服务,目前软件系统体系结构一般分为C/S和B/S两种模式。
使用代码进行编程首先要了解网络中的各种协议(主要是TCP/IP协议),任何编程都要按照协议内容进行编码,各层之间,高低层之间,各种通信,都要按照协议规定来具体实施。

9.2.基本软件体系

C/S,模式即客户端/服务器端(client/server)模式,基本信息交互的时序是客户端发出请求服务器接收请求服务器发出响应客户端接收响应。C/S模式的优点在于可以充分发挥客户端PC的处理能力,很多工作可以在客户端处理之后再提交给服务器,所以C/S模式服务器响应快。缺点是客户端需要安装响应的客户端软件,在有大型机群的地方安装软件十分不方便,同时几乎没有软件可以对任何类型的操作系统都兼容,所以有兼容性限制。
B/S,即浏览器/服务器模式(brower/server),随着互联网的发展,C/S架构也有了它的变异版,即B/S,B/S模式利用不断完善的www浏览器技术,结合多种脚本语言等,在浏览器上就可以实现复杂又强大的功能,是一种全新的软件系统构造技术。
在B/S模式下只需要一个浏览器就可以访问服务器并进行信息交互,优点是客户机只需要有浏览器且可以上网就能满足要求,维护安装都很容易。缺点是所有的事物处理都在服务器上发生,加重服务器负担,使得服务器响应速度变慢。

9.3.字节顺序

计算机中的基本存放单元是字节,一个字节可以存放一个ASCII码,字符型的量只占一个字节,但是如汉字或整型就占了多个字节,这个时候就涉及到字节存放顺序问题。
字节顺序是指一个多字节的量将连续的字节存入内存时的顺序,有两种情况:
Big-Endian:低位字节保存在内存高地址端
Little-Endian:低位字节保存在内存低地址端
比如一个int tmp=5,那么就有四个字节的内存空间来保存这个5,5的连续字节是0x00 00 00 05,假设内存空间从低到高的空间是abcd,那么Big模式下就按照dcba来存放这个5,而Little模式下就按照abcd来存放这个5
在不同的计算机内,由于系统不同,所以选择的顺序也可能不同,但是在数据传输发达的今天,一个任何顺序的量都可以传输到另外一个顺序的计算机中去,这样就需要字节顺序转换。否则就会造成数据传输错误。
网络中一般规定以Big-Endian的顺序为标准顺序,所以对于网络中的数据,都应该先将其转换为Big-Endian的顺序才能正常传输。

9.4.字节顺序变换函数

1.uint16_t htons(uint16_t hostshort)
将主机字节顺序转换成网络字节顺序,参数是一个短整型,一般用于操作端口号(端口号就是16位的数),返回值就是一个16位的短整型数据,是网络字节顺序。
头文件是<netinet/in.h>
2.uint32_t htonl(uint32_t hostlong)
将主机字节顺序转换成网络字节顺序,参数是一个长整型,一般用于操作IP地址(IP地址就是32位的数),返回值就是一个32位的长整型数据,是网络字节顺序。
头文件是<netinet/in.h>
3.in_addr_t inet_addr(const char *cp)
将一个点分十进制的IP转换成网络字节数,一般用于初始化sockaddr结构体的IP地址,括号中一般填一个具体的IP,返回一个32位的长
头文件是<arpa/inet.h>
4.uint16_t ntohs(uint16_t netshort)
将网络字节顺序转换为主机字节顺序,参数是一个短整型,返回值就是一个16位的短整型数据,是主机字节顺序。
头文件是<netinet/in.h>
5.uint32_t ntohs(uint32_t netlong)
将网络字节顺序转换为主机字节顺序,参数是一个长整型,返回值就是一个32位的长整型数据,是主机字节顺序。
头文件是<netinet/in.h>

9.5.套接字结构体

套接字(socket)是网络通信的基本操作单元,它提供了不同主机间进程双向通信的端点,这些进程在通信前各自建立一个套接字,并且通过对套接字的读写操作实现网络通信功能。
套接字分为三种:
字节流套接字:最常见的套接字类型,TCP协议使用此接口,提供面向连接的,无差错的,发送先后顺序一致的,包长度不限和非重复的网络信包传输。
数据包套接字:UDP协议使用此接口,它是无连接的服务,以独立的信包进行网络传输,传输不保证顺序性、可靠性和无重复性,通常用于单个报文传输或可靠性不重要的场合。
原始套接字:提供对网络下层通讯协议的直接访问,主要用于开发新的协议或用于提取协议较隐蔽的功能。
socket作为一种网络进程间通信,就需要明确进程所在主机的网络地址以及进程所使用的端口,通信双方都需要遵守这样的协议。所以一个通用的地址结构体sockaddr。
struct sockaddr
{
unsigned short sa_family /地址协议簇,格式为AF_XXX
char sa_data[14]//14字符,决定端口和IP
};
sa_family是协议簇,绝大多数选择AF_INET,表示选择TCP/IP协议,sa_data里面是IP和端口,可能是本机的也可能是目标主机的。
这个结构体的端口和IP都在一个字符数组内,使用起来比较困难,所以一般使用一种更新的结构体:
struct sockaddr_in
{
short int sin_family; //地址家族协议簇
unsigned short int sin_port;//端口号
struct in_addr sin_addr;//IP地址
unsigned char sin_zero[8];//空数组,用于调整和sockaddr结构 体有同样的大小
};
这个结构体和sockaddr有一样的大小,而且将IP和端口分开,这样方便使用。
需要注意的是,IP地址并不是定义一个4字节的字符数组,而是定义在一个新的结构体中,实际上该结构体也只有一个成员:
struct in_addr
{
unsigned long s_addr;
};
这个结构体用于单独定义IP地址,所以也只有4个字节。并不影响sockaddr_in的大小。
一般都会使用sockaddr_in结构体来初始化套接字结构体,但是部分函数的定义任然是使用的sockaddr,所以有些时候是需要将sockaddr_in类型转换成sockaddr,而且由于两者所占字节一样,所以是可以实现字节强转,这仅仅是为了符合函数定义而去做的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值