linux网络编程2
24.9.18学习目录
- 一.数据包的传送
- 1.数据包在每层间的传送
- 2.链路层的封包
- 3.网络层、传输层封包格式
- 二.字节序
- 1.概念
- 2.字节序转换函数
- 三.IP地址转换
- 四.UDP
- 1.概述
- 2.网络编程接口socket
- 3.UDP的C/S架构
- 4.UDP编程
一.数据包的传送
1.数据包在每层间的传送
传送方数据从运用层到链路层间都会添加信息,确保数据的能准确传入到接收方,而接受发从链路层到运用层会对添加的数据进行验证并删除
2.链路层的封包
封包的类型主要为两个,但常用的是以太网封装方法
目的地址和源地址都是MAC地址
类型指的是采用什么类型的协议
以太网常用在有线局域网;
IEEE常用在无线局域网;
3.网络层、传输层封包格式
其添加的数据如图中,每一行都占4个字节
二.字节序
1.概念
字节序是指多字节数据的存储顺序
在数据传输过程中字节序的不同会导致信息接收时理解错误,因此需要注意接收方和传送方的字节序
分类:
小端格式:将低位字节数据存储在低地址
大端格式:将高位字节数据存储在低地址
高地址为MSB;低地址为LSB
判断字节的存储方式:
#include <stdio.h>union un
{int a;char b;
};int main(int argc,char const *argv[])
{union un myun;myun.a = 0x12345678;printf("a = %#x\n",myun.a);printf("b = %#x\n",myun.b);if(myun.b = 0x78){printf("小端存储\n");}else{printf("大端存储\n");}return 0;
}
注意:
- 网络协议指定了通讯字节序为大端
- 只有在多字节数据处理时才需要考虑字节序
- 运行在同一台计算机上的进程互相通信时,一般不用考虑字节序
- 异构计算机之间通讯,需要转换自己的字节序为网络字节序,可以通过特定的函数进行转换
2.字节序转换函数
(1)转换为网络字节序函数
#include <arpa/inet.h>
//长整型
uint32_t htonl(uint32_t hostint32);//短整型
uint16_t htons(uint16_t hostint16);
(2)转换为主机字节序函数
#include <arpa/inet.h>
//长整型
uint32_t ntohl(uint32_t hostint32);//短整型
uint16_t ntohs(uint16_t hostint16);
三.IP地址转换
将用户识别的IP(为字符串)转换为机器能识别的整型
(1)地址间的相互转换:
#include <arpa/inet.h>
//将点分十进制字符串转换为32为无符号整数
int inet_pton(int family,const char *strptr,void *addrptr)
family:协议族,有AF_INET为IPV4的网络协议、AF_INET6
为IPV6的网络协议
strptr:点分十进制字符串
addrptr:32位无符号整数的地址
#include <arpa/inet.h>
//将32位无符号整数转换为点分十进制字符串
const char *inet_ntop(int family,const void *addrptr,char *strptr,size_t len);
len:为strptr缓冲区长度
(2)用于IPV4地址的转换的函数
该两个函数在TCP和UDP网络编程中比较常用
#include <sys/sochet.h>
#include <netinet/in.h>
#include <arpa/inet.h>//将点分十进制字符串转换为整数
int_addr_t inet_addr(const char *cp)//将整数转换为点分十进制字符串
char *inet_ntoa(struct in_addr in);
cp:为点分十进制的IP地址
in:为保存IP地址的结构体
四.UDP
1.概述
常用于语音和视频通话
特定:
- 相较于TCP速度稍快些
- 简单的请求、应答应用程序可以使用UDP
- 对于海量数据传输不应该使用UDP
- 广播和多播应用必须使用UDP
2.网络编程接口socket
socket(也称套接字)提供不同主机上的进程之间的通信;
其是一种文件描述符。代表了一个通信管道的一个端点;
对其操作类似于文件的操作,使用read、write等函数;
获取socket的方法为socket();
socket主要分类:
- SOCK_STREAM:流式套接字,用于TCP
- SOCK_DGRAM:数据报套接字,用于UDP
- SOCK_RAW:原始套接字,对于其他层次的协议操作时需要使用这个类型
3.UDP的C/S架构
UDP网络编程流程:
(1)服务器:
使用socket()函数创建socket;
是用bind()函数将服务器的ip地址、端口号和socket进行绑定;
使用recvfrom()函数等待接收用户请求的发送;
使用sendto()函数给用户发送数据;
(2)客户端:
使用socket()函数创建socket;
使用sendto()函数给服务器发送数据;
使用recvfrom()函数接收服务器发送的数据;
使用close()函数关闭socket
4.UDP编程
(1)socket函数创建socket
#include <sys/socket.h>
int socket(int family,int type,int protocol);
type:套接字类型
protocol:协议类别,有0、IPPROTO_TCP、IPPROTO_UDP等
特点:
创建socket时,系统不分配端口
创建的socket时指定发起服务的请求,当作为服务器时,需要将其该为被动的
(2)IPv4套接字地址结构
注意:
不同格式地址能被传入套接字函数,地址必须要强制转换成通用套接字地址结构体,因为不同场合使用的结构体不一样,但调用的函数是一样的;
以下三个在linux中都已经定义好了,能直接使用
#include <netinet/in.h>
struct in_addr
{in_addr_t s_addr;//IP地址
};//网络编程中通用协议
//在定义源地址和目的地址时,使用下面结构体
struct socketaddr_in
{sa_family_t sin_family;//协议族in_port_t sin_port;//端口号struct in_addr sin_addr;//ip地址char sin_zero[8];//填充
};//通用的地址结构体
struct sockaddr
{sa_family_t sa_family;//协议族char sa_data[14];//填充
};
当调用编程接口函数,且该函数需要传入地址结构时需要进行强制转换
bind(sockfd,(struct sockaddr*)&my_addr,sizeof(my_addr));