linux 网络基础1

发布时间 2023-07-20 21:27:54作者: snowa

linux 1 网络基础

1.mac地址

网卡->物理地址 通常不会重复 虚拟网卡除外 48位 6字节

00:00:00:00:00:00

2.ip地址

标识主机Id 为虚拟的 有ipv4(32位) ipv6(64位)

分为子网ID 和主机 ID 其中的计算需要子网掩码搭配 netmask

ip中连续的1覆盖的位 子网ip

连续0覆盖的位 主机id

ip:(二进制)10.1.1.2 ->0000 1010 0000 0001 0000 0001 0000 0010

netmask->255.255.255.0->1111 1111 1111 1111 1111 1111 0000 0000

10.1.1 子网id 主机id2

网段地址:10.1.1.0

广播地址:10.1.1.255

可设置范围

1-254

3.ping

127.0.0.1->254 都是属于对本机进行联通

4.ip地址分类

ip地址分类

5.ip netmask设置

linux中

sudo  ifconfig ens33 192.168.26.33 netmask 255.255.255.0

6.桥接和net的区别

桥接和net

7.端口

每个程序都有一个/多个端口
作用:用来标识应用程序

port:2字节 0-65535 其中0-1023知名端口 自定义端口1024-65535

端口类似于进程号,同一时刻只能只能标志一个,可以重复使用

8.网络分层模型

网络分层模型

物理层:双绞线的接口类型 光纤的传输速度
数据链路层:mac 负责收发数据
网络层:ip给两台主机 提供路径选择
传输层:port 区分数据递送到哪一个应用层
会话层:建立链接
表示层:解码
应用层:拿到数据
物 数 网 传 会 话 层

开发中 四层 TCP/IP模型

四层模型

8.协议

规定数据传输的方式和格式

应用层协议
ftp:文件传输协议
http:超文本传输协议

传输层协议
tcp:传输控制协议
udp:用户数据报协议

网络层
ip:因特网互联协议
icmp:因特网控制报文协议 ping命令
ugmp:因特网管理协议】链路层
arp:地址解析协议 通过Ip找mac
rarp:反向地址解析协议 通过mac找ip

ttl->最大在网络出游走数

ttl

防止在路由器内循环

9.组包过程

组包图

圆圈内通过

10.arp通信

地址解析协议 ip找mac地址

arp通信

a->广播发送信息 传给b b返回mac(局域网)

11.网络模式

B/S 网页/服务器 开发周期段

CS 客户端/服务器->客户端计算 容易开挂 开发时间长

12.socket

socket图

13.网络字节序

大小端 存储

网络字节序

网络传输

网络传输

字节序转换

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
//小转大
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
//大转小
h表示host,n表示network,l表示32位长整数,s表示16位短整数。
//如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。


转大端

小端转大端数据

转小端

大端转小端

14.点分十进制转换
#include <arpa/inet.h>
 int inet_pton(int af, const char *src, void *dst);
功能: 将点分十进制串 转成32位网络大端的数据("192.168.1.2"  ==>   )
参数:
    af : 
        AF_INET         IPV4
        AF_INET6        IPV6
  src: 点分十进制串的首地址 
  dst : 32位网络数据的地址 
成功返回1


#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src,               char *dst, socklen_t size);
功能: 将32位大端的网络数据转成点分十进制串
参数:
   af : AF_INET
   src : 32位大端的网络数 地址
   dst : 存储点分十进制串 地址
   size : 存储点分制串数组的大小 
返回值: 存储点分制串数组首地址
15.ipv4套接结构体
ipv4套接字结构体

struct sockaddr_in {

​        sa_family_t  sin_family; /* address family: AF_INET */ //sin_family: 协议 AF_INET

​        in_port_t   sin_port;  /* port in network byte order *///sin_portL端口

​        struct in_addr sin_addr;  /* internet address */

​      };

​      /* Internet address. */

​      struct in_addr {

​        uint32_t    s_addr;   /* address in network byte order */ //  sin_addr ip地址

​      };

sin_family: 协议 AF_INET

sin_portL端口

 sin_addr ip地址
通用套接字结构体

struct sockaddr {

  sa_family_t sa_family;   /* address family, AF_xxx */

  char sa_data[14];     /* 14 bytes of protocol address */

};

需要强转为套接字结构体 这样可以使得结构体统一 Ipv4 和ipv6无需两个接口

socket通信流程

客户端 tcp 出错重传 每次发送数据对方都会回ACK
电话 建立链接 关闭链接

客户端流程

创建套接字api

#include <sys/socket.h>

int socket(int domain, int type, int protocol);

创建套接字

参数:

domain:AF_INET

type: SOCK_STREAM 流式套接字 用于tcp通信

protocol: 0

成功返回文件描述符,失败返回-1

链接服务器

#include <sys/socket.h>
 int connect(intsockfd , const struct sockaddr *addr,
                   socklen_t addrlen);
功能: 连接服务器

sockfd:  socket套接字
addr:  ipv4套接字结构体的地址
addrlen: ipv4套接字结构体的长度
客户端代码
#include<unistd.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<sys/socket.h>
int main()
{
int sock_fd;
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
//链接服务器
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
inet_pton(AF_INET, "172.23.128.1", &addr.sin_addr.s_addr);
connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr));
char buf[1024]="";
while (1)
{
printf("发送信息\n");
	int n = read(STDIN_FILENO, buf,sizeof(buf));
	write(sock_fd, buf, n);
printf("接收信息中\n");
	n = read(sock_fd, buf, sizeof(buf));
	write(STDOUT_FILENO, buf, n);
}
return 0;
}

服务器代码

tcp服务器流程

tcp服务器通信步骤
1.创建套接字
2.绑定
3.监听
4.提取
5.读写
6.关闭

服务器创建api

给套接字绑定固定的端口和ip

\#include <sys/socket.h>

 int bind(int sockfd, const struct sockaddr *addr,

​        socklen_t addrlen);

sockfd: 套接字

addr: ipv4套接字结构体地址

addrlen: ipv4套接字结构体的大小

返回值:

成功返回0 失败返回;-1

监听

 listen

include <sys/socket.h>

int listen(int sockfd, int backlog);

参数:

   sockfd : 套接字

   backlog : 已完成连接队列和未完成连接队里数之和的最大值 128

19 accept 提取

\#include <sys/socket.h>

 int accept(int socket, struct sockaddr *restrict address,

​      socklen_t *restrict address_len);

如果连接队列没有新的连接,accept会阻塞

功能: 从已完成连接队列提取新的连接

参数:

   socket : 套接字

   address : 获取的客户端的的ip和端口信息 iPv4套接字结构体地址

   address_len: iPv4套接字结构体的大小的地址

socklen_t len = sizeof(struct sockaddr );

返回值: 新的已连接套接字的文件描述符


示例

#include<unistd.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
int main()
{
	//服务器代码编写
	//创建套接字
	int sock_fd;
	int cfd_1;

	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	
	//绑定
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8080);
	inet_pton(AF_INET, "192.168.26.132", &addr.sin_addr.s_addr);
	
	bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr));
	

	//监听
	listen(sock_fd, 128);

	//提取套接字
	struct sockaddr_in cliaddr;

	socklen_t len = sizeof(cliaddr);

	 cfd_1=accept(sock_fd, (struct sockaddr*)&cliaddr, &len);

	char buf[1024] = "";
	//读写
	while (1)
	{
		printf("发送信息\n");
		bzero(buf, sizeof(buf));
		int n = read(STDIN_FILENO, buf, sizeof(buf));
		write(cfd_1, buf, n);

		printf("读取消息如下:\n");

		n = read(cfd_1, buf, sizeof(buf));
		printf("%s\n", buf);


	}

	return 0;
}