OSI模型
发送端
应用层
表示层
会话层
传输层
网络层
数据链路层
物理层
Hub集线器
Hub:多端口中继器
hub并不记忆该信息包是由哪个MAC地址发出,哪个MAC地址在Hub的哪个端口
Hub的特点:
共享宽带
半双工
工作在物理层
在同一个冲突域中
以太网桥
冲突域
学习源地址,转发是根据目标地址
有一个mac地址表
mac地址 和网桥端口的映射
网桥可以隔离冲突域
由于广播地址只能出现在目标地址,而网桥只能学习源地址,所以网桥不能隔断广播,故ABCD在一个广播域中
工作在数据链路层(mac)
交换机
升级版的网桥
路由器
隔断广播
选择路由表中到达目标最好的路径
维护和检查路由信息
连接广播域
工作在网络层
vlan
分隔广播域
安全
灵活管理
TCP/IP协议
应用层
传输层
网路层
链路层
物理层
TCP特性
工作在传输层
面向连接协议
全双工协议
半关闭
错误检查
将数据打包成段,排序
确认机制
数据恢复,重传
流量控制,滑动窗口
拥塞控制,慢启动和拥塞避免算法
URG:紧急指针
ACK:
PSH:
RST:
SYN:
FIN:
TCP四次挥手
TIME_WAIT的作用:
由于第二次的数据传送过程中,可能存在数据先发后到的情况,如果直接进行close状态,可能存在收不到部分剩余数据,所以进行time_wait状态等待足够的时间
窗口:
表示现在允许对方发送的数据量,也就是告诉对方,从本报文段的确认号开始允许对方发送的数据量,如windows size is 3,seq 1,2,3 ack 4 seq 4,5,6,ack 7…
检验和:
提供额外的可靠性
紧急指针:
标记紧急数据在数据字段中的位置
拥塞控制:
- 慢启动
- 拥塞避免
- 快速重传
- 快速恢复
当前所使用的拥塞控制算法
/proc/sys/net/ipv4/tcp_congestion_control
UDP特性
tcp和udp的区别有:
5. udp是无连接的,tcp是面向连接的;
6. udp是不可靠传输,tcp是可靠传输;
7. udp是面向报文传输,tcp是面向字节流传输。
RARP:逆地址解析协议
exp:
一般dhcp服务器维护了一些ip和mac的关系,当机器启动时向dhcp服务器发送自己mac来获取ip
IP包头
标识:占16位,它是一个计数器,通常,每发送一个报文,该值会加1,也用于数据包分片,在同一个包的若干分片中,该值是相同的
标志:占3位,目前只有后两位有意义
DF:Don’t Fragment,中间的一位,只有当DF=0时才允许分片,DF=1表示是完整的一个包,不是切出来的
MF: More Fragment,最高位,MF=1表示后面还有分片,MF=0表示最后一个分片
自定义用户栈解析udp包:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define NETMAP_WITH_LIBS
#include <net/netmap_user.h>
#include <sys/poll.h>
using namespace std;
#define PROTO_IP 0x800
#define PROTO_UDP 17
#define ETH_LENGTH
#pragma pack(1)
//֡ͷ
struct ethhdr
{
unsigned char dst[ETH_LENGTH];
unsigned char src[ETH_LENGTH];
unsigned short proto;
};
//IPͷ
struct iphdr
{
unsigned char version:4,
hdrlen:4;
unsigned char tos;
unsigned short length;
unsigned short id;
unsigned short flag_offset;
unsigned char ttl;
unsigned char protocal;
unsigned short check;
unsigned int sip;
unsigned int short dip;
};
//udp
struct udphdr
{
unsigned short sport;
unsigned short dport;
unsigned short length;
unsigned short check;
};
struct udppkt
{
struct ethhdr eh;
struct iphdr ip;
struct udphdr udp;
unsigned char data[0];
};
int main()
{
struct nm_desc *nmr = nm_open("netmap:lo",NULL,0,NULL);
perror(nm_desc != NULL);
struct pollfd pfd = {0};
pfd.fd = nmr->fd;
pdf.event = POLLIN;
struct nm_pkthdr h;
while(1)
{
int ret = poll(&pfd,1,-1);
if(ret < 0) continue;
if(pfd.revents & POLLIN)
{
unsigned char *stream = nm_nextpkt(nmr,&h);
struct ethhdr *eh = (struct ethhdr*)stream;
if(ntohs(eh->proto) == PROTO_IP)
{
struct udppkt *udp = (struct udppkt*) stream;
if(udp->ip.proto = PROTO_UDP)
{
int udp_length = ntohs(udp->udp.length);
udp->data[udp_length-8]='\0';
printf("udp->%s",udp->data);
}
}
}
}
}
udp发包程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc,char * argv[])
{
if(argc != 3)
{
printf("请传递对方的ip和端口号");
return -1;
}
int port = atoi(argv[2]);
if(port<1025 || port>65535)
{
printf("端口号范围应为1025~65535");
return -1;
}
int udp_socket_fd = socket(AF_INET,SOCK_DGRAM,0);
if(-1 == udp_socket_fd)
{
//perror("socket failed\n");
printf("socket failed\n");
return -1;
}
struct sockaddr_in dest_addr = {0};
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
dest_addr.sin_addr.s_addr = inet_addr(argv[1]);
char buf[1024] = {0};
while(1)
{
printf("please input msg:");
scanf("%s",buf);
sendto(udp_socket_fd,buf,strlen(buf),0,(struct sockaddr*)&dest_addr,sizeof(dest_addr));
if(strcmp(buf,"exit")==0)
{
break;
}
memset(buf,0,sizeof(buf));
}
close(udp_socket_fd);
return 0;
}