区块链学习

一、tcp和udp的区别,如何设计可靠udp传输转载自:https://www.cnblogs.com/williamjie/p/11133180.htmlUDP不属于连接协议,具有资源消耗少,处理速度快的优点,所以通常音频,视频和普通数据在传送时,使用UDP较多,因为即使丢失少量的包,也不会对接受结果产生较大的影响。传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。最简单的方式是在应用层模仿传输层TCP的可靠性传输。下面不考虑拥塞处理,可靠UDP的简单设计。1、添加seq/ack机制,确保数据发送到对端2、添加发送和接收缓冲区,主要是用户超时重传。3、添加超时重传机制。详细说明:送端发送数据时,生成一个随机seq=x,然后每一片按照数据大小分配seq。数据到达接收端后接收端放入缓存,并发送一个ack=x的包,表示对方已经收到了数据。发送端收到了ack包后,删除缓冲区对应的数据。时间到后,定时任务检查是否需要重传数据。目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT。二、RSA算法设计三、https过程HTTP的请求过程:1、TCP建立连接后,客户端会发送报文给服务端;2、服务端接收报文并作出响应;3、客户端收到响应后解析给用户;HTTPS的请求过程:1、客户端发送请求到服务端;2、服务器返回证书和公钥;3、客户端验证证书和公钥的有效性,如果有效,则生成对称密钥并使用公钥加密发送到服务端;4、服务端使用私钥解密报文,并使用收到的对称密钥加密报文,发送到客户端;5、客户端使用对称密钥解密报文;6、SSL加密建立四、tendermint共识五、以太坊EVM是否熟悉

2021-3-1 1082 0
区块链学习

一、go语言基础(1)一个包怎么调用另一包的函数,go语言中公有性和私有性怎么表达?函数大写表示公有,小写表示私有(2)简单的介绍一下闭包使用场景,优缺点?首先闭包的特点是当闭包函数引用外部变量的时候,会把这个变量放在堆中,所以在内部函数引用外部函数的变量时,值不会被释放packagemainimport"fmt"funcexternalFunc(countint)func()int{returnfunc()int{count++returncount}}funcmain(){//这时候的external是个函数,externalFunc函数返回了个匿名函数external:=externalFunc(1)//这时候的count==1fmt.Println(external())//输出2fmt.Println(external())//输出3fmt.Println(external())//输出4}用法1.函数计数器//函数计数器funccounter(ffunc())func()int{n:=0returnfunc()int{f()n+=1returnn}}//测试的调用函数funcfoo(){fmt.Println("callfoo")}funcmain(){cnt:=counter(foo)cnt()cnt()cnt()fmt.Println(cnt())}/*输出结果:callfoocallfoocallfoocallfoo4*/2)装饰器和中间件,即函数作为参数传递funcwrapping(ffunc()string){fmt.Println("domywork...")fmt.Println("wrappingfunction:",f())fmt.Println("myworkfinished!")}funcsayHello()string{return"Hello!"}funcsayByeBye()string{return"ByeBye!"}funcmain(){wrapping(sayHello)wrapping(sayByeBye)}/*输出:domywork...wrappingfunction:Hello!myworkfinished!domywork...wrappingfunction:ByeBye!myworkfinished!*/(3)map和arraymake的使用区别?go语言中new和make是内置函数,主要用来创建分配类型内存。new(T)创建一个没有任何数据的类型为T的实例,并返回该实例的指针;make(T,args)只能创建slice,map,channel,并返回一个有初始值args(非零)的T类型的实例,非指针。二者都是内存的分配(堆上),但是make只用于slice、map、channel的初始化,而new用于类型的内存分配,并且内存内置为0.make返回的还是这三个引用类型本身;而new返回的是指向类型的指针。slice和array接近,不过更加的灵活,可以在新的元素加入的时候增加长度。slice总是指向底层的一个array。slice是一个指向array的指针,这是其与array不同的地方;slice是引用类型,这意味着当赋值某个slice到另外一个变量,两个引用会指向同一个array。例如,如果一个函数需要一个slice参数,在其内对slice元素的修改也会体现在函数调用者中,这和传递底层的array指针类似。append:向slice追加零值或者其他的x值,并且返回追加后的新的slice。如果原来的slice没有足够的容量,那么append会分配一个足够大的,新的slice来存放原来的slice和后面追加的值。因此返回的slice可能和原来的不是指向同一个arraySlice所允许申请的最大容量大小,与当前值类型和当前平台位数有直接关系slice扩容机制1.如果切片的容量小于1024个元素,那么扩容的时候slice的cap就翻番,乘以2;一旦元素个数超过1024个元素,增长因子就变成1.25,即每次增加原来容量的四分之一。2.如果扩容之后,还没有触及原数组的容量,那么,切片中的指针指向的位置,就还是原数组,如果扩容之后,超过了原数组的容量,那么,Go就会开辟一块新的内存,把原来的值拷贝过来,这种情况丝毫不会影响到原数组。make创建make([]T,length,capacity)slice1:=make([]T,length)length表示slice中已经使用的数据长度capacity表示slice中指针执行的数组容量,如果缺省capacity和length大小相等(4)defer的工作模式go的defer语句是用来延迟执行函数的,而且延迟发生在调用函数return之后,同时defer的执行顺序和栈类似,先进后出(5)匿名函数的使用(难点)常用的感觉就是闭包和gofunc协程了,再说吧。。。。。二、面向对象和并发(1)go语言如何表现继承go中没有extends关键字,所以没有原生级别的继承。go本质上是使用interface实现的,是使用组合来实现继承,用组合来代替继承。在go的结构体struct,通过匿名成员的方式实现继承,比如,Student继承了MentypeMenstruct{namestringageint}typeStudentstruct{Menscoreint}对于接口interface,通过直接引入另一接口的方式实现继承,比如,ReadWriter继承了Reader和WritertypeReaderinterface{}typeWriterinterface{}typeReadWriterinterface{ReaderWriter}(2)接口的优点,使用场景。实现代码解耦(3)并发通信采用什么消息机制。goroutine+channel数据共享

2021-3-1 1094 0
2021-2-17 1024 0