网络前三层协议的代码模拟
生活随笔
收集整理的這篇文章主要介紹了
网络前三层协议的代码模拟
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
最近看了一篇文章覺得非常好:
?https://www.zhihu.com/question/21546408/answer/2303205686
為了加深印象,特寫了一個程序來模擬一下其中的傳輸
傳送門:github
因為代碼和現實的一些差異,可能顯得有些地方設計的有些丑陋了,有想法的可以多提提意見~
首先是主機層?
package modelimport "fmt"//主機 type Computer struct {Ip string//ipMac string//mac地址SubnetMask string//子網掩碼DefaultGateway string//默認網關Arp map[string]string//arp 用于緩存ip到mac的關系ExchangeBoard *ExchangeBoard//所屬的交換機Port int//所屬的交換機的端口MsgCh chan Message //監聽消息MsgList []Message//消息存儲下來 } func (c *Computer)IsSubnet(ip string)bool{return isIpSubNet(c.Ip,ip,c.SubnetMask) } func (c *Computer)NewMessage(ip,msg string)Message{mac:=""if c.IsSubnet(ip){//同一個子網走正常ipmac=c.Arp[ip]}else{mac=c.Arp[c.DefaultGateway]//不是同一個子網走默認網關}return Message{Head: MessageHead{FromMac: c.Mac,ToMac: mac,FromIp: c.Ip,ToIp: ip,FromPort: c.Port,},Body: msg,} } func (c *Computer)SendMessage(message Message){//只知道目標ipc.ExchangeBoard.SendMessage(message)//通過交換機發送消息 } func (c *Computer)Wait(){go func() {for{select {case v:=<-c.MsgCh:if v.Head.ToMac==""{//第一次,不知道我的mac,需要通過ip驗證if v.Head.ToIp==c.Ip{if v.Head.IsArpReq{//arp請求c.Arp[v.Head.FromIp]=v.Head.FromMac//更新自己的arp表message:=Message{Head: MessageHead{FromMac: c.Mac,ToMac: v.Head.FromMac,FromIp: c.Ip,ToIp: v.Head.FromIp,IsArpRes: true,FromPort: c.Port,},}c.MsgList=append(c.MsgList,v)//不確定要不要發送c.ExchangeBoard.SendMessage(message)//通過交換機響應}}} else if v.Head.ToMac==c.Mac{//收到消息,確實是自己的macif v.Head.IsArpRes{wait=truec.Arp[v.Head.FromIp]=v.Head.FromMac//只更新自己的arp表即可}else{fmt.Println(fmt.Sprintf("[%s]電腦收到[%s]的消息啦:%s",c.Mac,v.Head.FromMac,v.Body))//正常請求,接收即可c.MsgList=append(c.MsgList,v)}}}}}() }然后是交換機:
?
package modelimport ("fmt""time" )//交換機 type ExchangeBoard struct {MacPort map[string]int//mac與端口映射表PortList PortSenderM//所有的端口 端口后可能是電腦,也可能是交換機//ExchangeBoardPortM ExchangeBoardPortM//交換機與別的交換機連接的端口,比如A的端口上是B 就是A.ExchangeBoardPortM= [B]1Router *Router//路由器Port int //交換機與路由器連接的端口 } func NewExchangeBoard()*ExchangeBoard{return &ExchangeBoard{MacPort: map[string]int{},PortList: PortSenderM{},} } func (e *ExchangeBoard)NewMessage(ip,msg string)Message{//交換機本身沒有自己的初始消息return Message{} } func (exchangeBoard *ExchangeBoard)SetSender(portSenderM PortSenderM){for k,v:=range portSenderM{exchangeBoard.PortList[k]=v} } func (exchangeBoard *ExchangeBoard)GetSender(port int)Sender{return exchangeBoard.PortList[port] } var wait bool func (e *ExchangeBoard)SendMessage(message Message){e.MacPort[message.Head.FromMac]=message.Head.FromPort//更新mac與端口映射表,每次都更新,防止機器換端口if message.Head.ToMac==""{//目標mac為空,發送廣播message.Head.IsArpReq=truefor k,v:=range e.PortList{if k==message.Head.FromPort && !message.Head.IsFromRouter{//發送方端口不對其發送消息 且不是從路由器來的消息continue}e.commonSendMessage(v,message)}//這一段主要是為了解決同一個交換機下的機器不用通過路由器廣播,如果同交換機下找不到,再走路由器time.Sleep(1*time.Second)if wait{wait=falsereturn}if !message.Head.IsFromRouter{message.Head.ToMac=e.Router.PortMacM[e.Port].Mace.Router.SendMessage(message)//給路由器也發}}else{//有macif port,ok:=e.MacPort[message.Head.ToMac];ok{if port==-1{e.Router.SendMessage(message)}else{e.commonSendMessage(e.PortList[port],message)}}else{//廣播,更新mac地址表,不存在了fmt.Println("?")}} } //給指定端口機器發送消息 func (e *ExchangeBoard)commonSendMessage(v interface{},message Message){switch v.(type) {case *Computer:v.(*Computer).MsgCh<-message//case *ExchangeBoard:// message.Head.FromPort=v.(*ExchangeBoard).ExchangeBoardPortM[e]//交換機的的fromport需要替換// v.(*ExchangeBoard).SendMessage(message)} }然后是路由器:
?
package modelimport ("strings" )//路由器 type Router struct {IpPort IpPort//ip網段與端口映射表 路由表 分為靜態和動態Arp map[string]string//arp 用于緩存ip到mac的關系PortExchangeBoardM PortExchangeBoardM //路由器端口列表PortMacM PortMacM//保存端口和mac,ip的關系 初始化就有 } type NextPort struct {Next *Router//下一跳Port int//端口 } type MacAndIp struct {Mac stringIp string }func (r *Router)SendMessage(message Message){if message.Head.IsArpReq || message.Head.IsArpRes{r.Arp[message.Head.FromIp]=message.Head.FromMac}port:=r.GetPortFromIp(message.Head.ToIp)//根據路由表找到ip對應的端口message.Head.FromMac=r.PortMacM[port].Mac//來源mac置為路由器發送端口的macmessage.Head.ToMac=r.Arp[message.Head.ToIp]//需要根據arp得到ip對應的macmessage.Head.IsFromRouter=truemessage.Head.FromPort=-1//-1代表在交換機上 路由器沒有插在正常的lan口上,而是wan口,這里用-1表示r.PortExchangeBoardM[port].SendMessage(message)//向指定端口發送消息 }func (r *Router)GetPortFromIp(ip string)int{for k,v:=range r.IpPort{ipList:=strings.Split(k,"/")if len(ipList)==0{panic("error")}if isIpSubNet(ip,ipList[0],SubNetM[ipList[1]]){if v.Next!=nil{return v.Next.GetPortFromIp(ip)}return v.Port}}panic("數據不可達") }還有一些其他的方法先不展示了,直接初始化各個設備,插上設備:
package mainimport ("mac-ip/model""time" ) var exchangeBoard1,exchangeBoard2,exchangeBoard3 *model.ExchangeBoard var senderM1=model.PortSenderM{0:&model.Computer{Ip: "192.168.0.1",Mac: "AAAA",SubnetMask: "255.255.255.0",DefaultGateway: "192.168.0.254",ExchangeBoard:exchangeBoard1,Port: 0,},1:&model.Computer{Ip: "192.168.0.2",Mac: "BBBB",SubnetMask: "255.255.255.0",DefaultGateway: "192.168.0.254",ExchangeBoard: exchangeBoard1,Port: 1,}, } var senderM2=model.PortSenderM{0:&model.Computer{Ip: "192.168.1.1",Mac: "CCCC",SubnetMask: "255.255.255.0",DefaultGateway: "192.168.1.254",ExchangeBoard: exchangeBoard2,Port: 0,},1:&model.Computer{Ip: "192.168.1.2",Mac: "DDDD",SubnetMask: "255.255.255.0",DefaultGateway: "192.168.1.254",ExchangeBoard: exchangeBoard2,Port: 1,}} var senderM3=model.PortSenderM{0:&model.Computer{Ip: "192.168.2.1",Mac: "EEEE",SubnetMask: "255.255.255.0",DefaultGateway: "192.168.2.254",ExchangeBoard: exchangeBoard3,Port: 0,},1:&model.Computer{Ip: "192.168.2.2",Mac: "FFFF",SubnetMask: "255.255.255.0",DefaultGateway: "192.168.2.254",ExchangeBoard: exchangeBoard3,Port: 1,}} var router=&model.Router{IpPort: model.IpPort{"192.168.0.0/24":&model.NextPort{Next: nil,Port: 0,},"192.168.1.0/24":&model.NextPort{Next: nil,Port: 1,},},Arp: map[string]string{},PortExchangeBoardM: nil,PortMacM: model.PortMacM{0:model.MacAndIp{Mac: "ABAB",Ip: "192.168.0.254",},1:model.MacAndIp{Mac: "CDCD",Ip: "192.168.1.254",},}, } func init(){exchangeBoard1,exchangeBoard2,exchangeBoard3=model.NewExchangeBoard(),model.NewExchangeBoard(),model.NewExchangeBoard()exchangeBoard1.SetSender(senderM1)exchangeBoard2.SetSender(senderM2)exchangeBoard3.SetSender(senderM3)router.PortExchangeBoardM=model.PortExchangeBoardM{0:exchangeBoard1,1:exchangeBoard2,}exchangeBoard1.Router=routerexchangeBoard1.Port=0exchangeBoard2.Router=routerexchangeBoard2.Port=1initComputer(exchangeBoard1,exchangeBoard2,exchangeBoard3)wait(exchangeBoard1,exchangeBoard2,exchangeBoard3)//監聽消息 } func main(){computer,_,computer3,_:=exchangeBoard1.GetSender(0),exchangeBoard1.GetSender(1),exchangeBoard2.GetSender(0),exchangeBoard3.GetSender(0)computer.SendMessage(computer.NewMessage("192.168.0.2","arp"))computer.SendMessage(computer.NewMessage("192.168.1.1","arp"))//computer.SendMessage(computer.NewMessage("192.168.2.1","arp"))time.Sleep(1*time.Second)computer.SendMessage(computer.NewMessage("192.168.0.2","hello"))//computer.SendMessage(computer.NewMessage("192.168.0.2","hello2"))//computer2.SendMessage(computer2.NewMessage("192.168.0.1","hello2"))computer.SendMessage(computer.NewMessage("192.168.1.1","hello3"))computer3.SendMessage(computer3.NewMessage("192.168.0.1","hello4"))for{} } func wait(ExchangeBoardList ...*model.ExchangeBoard){for i,_:=range ExchangeBoardList{go func(i int) {for _,v:=range ExchangeBoardList[i].PortList{if _,ok:=v.(*model.Computer);ok{v.(*model.Computer).Wait()}}}(i)} } func initComputer(exchangeBoardList ...*model.ExchangeBoard){for _,exchangeBoard:=range exchangeBoardList{for _,v:=range exchangeBoard.PortList{if computer,ok:=v.(*model.Computer);ok{computer.ExchangeBoard=exchangeBoardcomputer.MsgCh=make(chan model.Message,20)computer.Arp=map[string]string{}}}} }?
跑起來:
沒毛病
目錄結構是這樣的:
總結
以上是生活随笔為你收集整理的网络前三层协议的代码模拟的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【移动安全高级篇】————4、Andro
- 下一篇: android:completionth