1、Linux网络编程/套接字编程
现在大多数计算机网络都是根据TCP/IP协议栈搭建起来的,为了具体实现TCP/IP协议栈,Linux操作系统就对外提供了一套可供程序员做网络开发所用的操作接口,这就是Socket编程接口,这就是用来进行Linux网络编程项目开发的一些最基本的接口函数,比如socket、listen、connect、accept、send、read和write等等。总而言之,Socket是Linux操作系统下的一套API工具,Linux网络编程就是依靠这套工具实现TCP/IP协议栈的。
2、TCP和UDP的区别
基本上所有的网络服务都分为两种,一种是基于面向连接的可靠通信,一种是无面向连接的不可靠通信,分别对应是TCP/IP协议栈里传输层的TCP协议和UDP协议,他们接受下层网络层IP协议的服务同时为上层应用层的各种协议提供服务,因此Linux环境下Socket网络编程的程序设计也有两种:①基于TCP服务应用,数据流套接字(SOCK_STREAM); ②基于UDP服务应用 数据报套接字(DGRAM):
1、TCP是面向链接的,虽然说网络的不安全不稳定特性决定了多少次握手都不能保证连接的可靠性,但TCP的三次握手在很大程度上保证了连接的可靠性;而UDP不是面向连接的,UDP传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,当然也不用重发,所以说UDP是无连接的、不可靠的一种数据传输协议。
2、也正由于1所说的特点,使得UDP的开销更小数据传输速率更高,因为不必进行收发数据的确认,所以UDP的实时性更好。知道了TCP和UDP的区别,就不难理解为何采用TCP传输协议的MSN比采用UDP的QQ传输文件慢了,但并不能说QQ的通信是不安全的,因为程序员可以手动对UDP的数据收发进行验证,比如发送方对每个数据包进行编号然后由接收方进行验证什么的,即使是这样,UDP因为在底层协议的封装上没有采用类似TCP的“三次握手”而实现了TCP所无法达到的传输效率。
3、TCP的三次握手和四次断开
相对于Socket开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不需要控制这个过程.但是对于理解TCP底层运作机制,相当有帮助。首先了解TCP数据包的封装格式,位码即tcp标志位,有6种标示:SYN(synchronou建立联机) ACK(acknow -ledgement确认) PSH(pus传送) FIN(finis结束) RST(reset重置) URG(urgent紧急),Sequence number(顺序号码)
所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个TCP数据包。三次握手的目的是客户端连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时将触发三次握手。
第一次握手:主机A发送位码syn=1,随机产生seq number=100的数据包到服务器,主机B由SYN=1知道,A要求建立联机;
第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=300的包
第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。
完成三次握手后,主机A与主机B开始传送数据,数据传输完成后四次断开的过程和三次握手类似,只不过是客户端和服务器端之间要传输的是四个FIN和ACK标志位为1的数据包。使用一些抓包工具比如wireshark就可以明显看到三次握手中3个TCP包和四次断开中4个数据包的传输情况以及数据包中标志位的变化情况。
4、采用TCP协议进行Socket网络程序设计
5、采用UDP协议进行Socket网络程序设计
采用UDP协议进行程序设计和使用TCP是类似的,就是因为UPD是无面向连接通信协议,所以协议本身没有提供机制保证数据转发的可靠性,在实际编程中服务器端不需要使用listen函数将套接字设置为监听状态也不需要使用accept函数专门以阻塞方式等待客户端的连接,客户端也不需要调用connect函数发起连接,绑定了服务器方的IP地址和端口号就可以相互传输数据了。
6、主机字节序与网络字节序的转换
计算机在内存中存储整数(如端口号)的格式即主机字节序有两种,大端模式(big-endian)和小模式(little-endian),大端模式就是将数据的高序字节存储在起始地址(低地址),小端模式就是将数据的高序字节存储在高地址。在网络上面有着许多类型的机器,不同的CPU有不同的字节序类型,因此这些机器的主机字节序是不一样的,如Intel处理器的数据存放都是采用小端模式,而IBM PowerPC处理器却相反;举例描述两种主机字节序的区别:将4字节整形数据0x1234abcd写入到以0x0000开始的内存中,结果为:内存地址 big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x23 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
网络字节序是TCP/IP协议栈中规定好的一种数据表示格式,他与具体的CPU类型、操作系统等
平台无关,就是为了保证数据在不同主机之间传输时能够被正确解释,网络字节序采用大端模式,而大多数计算机都采用小端模式,所以由主机向网络中发送数据,以及接受数据都要进行字节序的转换,例如端口号的转来转去,否则就会出现数据的不一致。例如上述程序中,如果没有使用字节转换函数就直接使用十进制格式的端口号对sin_port赋值,运行此程序后,通过netstat –A inet查看网络接口信息,会发现Local Address栏显示的本地地址(服务器套接字)端口号,与程序中选择的并不一样。
为了统一起来,在Linux下面,有专门的字节转换函数.
uint32_t htonl ( uint32_t hostlong)
uint32_t ntohl ( uint32_t netlong)
在这类转换函数中,h 代表host, n代表 network,s代表short ,l代表long 。其中,htonl/htols函数是将32位整形数据从主机字节顺序转换为网络字节顺序;ntohl/ntohs函数是将32位整形数据从网络字节顺序转换为主机字节顺序。
7、字符串的IP和32位的IP转换
我们通常使用的IP都是互联网标准点分十进制格式的字符串IP地址, 而在网络通信中比如结构体sockaddr_in.sin_addr结构中的成员变量s_addr用的是32位的整数IP地址,如果直接用字符串形式赋值会警告:赋值时将指针赋给整数,未做类型转换。Linux专门提供了一个系统调用完成这项工作,
int_addr_t inet_addr ( const char *string);
输入参数string是ASCII码表示的字符串IP地址,如“99.99.177.195”;
返回值:如果这个函数成功,函数的返回值便是32位的网络序列IP地址。如果输入地址不合法不则会返回0,并且将errno置为INADDR_NONE。
本文详细介绍了Linux下的Socket网络编程,包括TCP和UDP的区别、TCP的三次握手和四次断开过程,以及如何进行TCP和UDP协议的Socket程序设计。此外,还讨论了主机字节序与网络字节序的转换方法,确保数据在不同主机间正确传输。

2781

被折叠的 条评论
为什么被折叠?



