1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048 |
- package penet
- import (
- "container/list"
- crand "crypto/rand"
- "encoding/binary"
- "errors"
- "github.com/chrislusf/seaweedfs/weed/glog"
- mrand "math/rand"
- "net"
- "runtime"
- "runtime/debug"
- "sync"
- "time"
- )
- type DataSend struct {
- Seq uint32
- Acked bool
- Resend byte
- Fast bool
- Code byte
- Time uint32
- Data []byte
- }
- type DataRecv struct {
- Seq uint32
- AckCnt byte
- Code byte
- Data []byte
- }
- type UdpSend struct {
- Id uint64
- sock *net.UDPConn
- remote *net.UDPAddr
- seq uint32
- rtt float64
- rttMax float64
- rttMin float64
- rate uint32
- mss uint32
- interval uint32
- data []DataSend
- dataBegin int
- dataLen int
- sendRnd int
- sendList *list.List
- sendListLock sync.Mutex
- writable chan bool
- writeMax int
- isClose bool
- closing bool
- opening byte
- conn *Conn
- resendCnt int
- name string
- acked uint32
- recvWnd uint32
- }
- const (
- TypeData uint8 = 1
- TypeAck uint8 = 2
- TypeClose uint8 = 3
- TypeSYN uint8 = 8
- )
- var (
- ErrClose = errors.New("conn close")
- ErrTimeout = errors.New("conn timeout")
- mss uint32 = 1200
- defaultRate = mss * 3000
- dropRate = 0.0
- writeMaxSep = 5
- resendLimit = true
- )
- func NewUdpSend(conn *Conn, id uint64, sock *net.UDPConn, remote *net.UDPAddr, name string) *UdpSend {
- u := &UdpSend{
- conn: conn,
- Id: id,
- sock: sock,
- remote: remote,
- mss: mss,
- interval: 20,
- data: make([]DataSend, 4),
- seq: 1,
- rate: defaultRate, // 修复bug: 太高导致压测的时候内存爆炸,速度慢
- rtt: 200,
- rttMax: 200,
- rttMin: 200,
- sendList: list.New(),
- writable: make(chan bool, 1),
- name: name,
- }
- u.writeMax = int(u.rate/u.mss) / writeMaxSep // fixed bug: 初始化 修复bug: 写入太多,应该一点点写
- u.recvWnd = uint32(u.writeMax)
- return u
- }
- func (u *UdpSend) send(nowTime time.Time, buf []byte) {
- var sendMax = int(u.rate / u.mss)
- u.writeMax = sendMax / writeMaxSep
- // glog.V(4).Info("send", u.dataLen, u.name, sendMax, uint32(u.rtt))
- var sendCount = uint32(u.rate / u.mss / (1000 / u.interval))
- var sendTotal = sendCount
- if sendCount > u.recvWnd/5 {
- sendCount = u.recvWnd / 5
- }
- if sendCount <= 0 {
- sendCount = 1
- }
- now := uint32(nowTime.UnixNano() / int64(time.Millisecond))
- resendCnt := 0
- for i := 0; i < u.dataLen; i++ {
- if sendCount <= 0 {
- break
- }
- index := (i + u.dataBegin) % len(u.data)
- d := &u.data[index]
- if d.Acked == false && now-d.Time >= uint32(u.rtt*2.0) {
- glog.V(4).Infof("resend, seq:%v id:%v rtt:%v name:%v", d.Seq, u.Id, uint32(u.rtt), u.name)
- // data包: type0 flag1 id2 len3 seq4 tm5 sndwnd6
- // 发送窗口就是配置值,其实发送窗口不需要发送出去
- // 接收端能发送了,要告诉对面开始发送。这个逻辑可以通过接受端的发送通道来发送。
- headLen := structPack(buf, "BBQHIII", uint8(TypeData),
- d.Code, uint64(u.Id), uint16(len(d.Data)+4+4+4), d.Seq, uint32(now), uint32(sendMax))
- copy(buf[headLen:], d.Data)
- u.sock.WriteToUDP(buf[:headLen+len(d.Data)], u.remote)
- d.Time = now
- d.Resend++
- d.Fast = false
- sendCount--
- resendCnt++
- u.resendCnt++
- }
- }
- u.sendRnd++
- if u.sendRnd > 100 && u.dataLen > 0 {
- u.sendRnd = 0
- var resendMax = uint32(float64(u.dataLen) * 0.6)
- if u.resendCnt > 2 {
- glog.V(0).Infof("resendCnt:%v resendMax:%v remain:%v rtt:%v id:%v", u.resendCnt,
- resendMax, u.dataLen, uint32(u.rtt), u.Id)
- u.resendCnt = 0
- }
- // 修复bug: 之前使用lastrecvtime,存在新增发送数据数据那瞬间,出现超时情况
- if u.data[u.dataBegin].Resend > 10 {
- glog.V(0).Infof("resend too much, close, id:%v name:%v drop seq:%v remain:%v",
- u.Id, u.name, u.data[u.dataBegin].Seq, u.dataLen)
- u.conn.close(true, true)
- }
- }
- var resendToomuch bool
- if uint32(resendCnt) > sendTotal/3 && resendLimit { // 修复bug: 限速
- resendToomuch = true
- glog.V(4).Infof("resend too much, slow, %v %v", resendCnt, sendTotal)
- }
- u.sendListLock.Lock()
- for ; sendCount > 0; sendCount-- {
- sendData := u.sendList.Front()
- if sendData == nil {
- break
- }
- if sendMax-u.dataLen <= 0 || resendToomuch {
- break
- }
- if u.dataLen >= len(u.data) {
- newData := make([]DataSend, 2*len(u.data))
- copy(newData, u.data[u.dataBegin:])
- copy(newData[len(u.data)-u.dataBegin:], u.data[:u.dataBegin])
- u.dataBegin = 0
- u.data = newData
- }
- u.sendList.Remove(sendData)
- hType := uint8(0)
- sdata, ok := sendData.Value.([]byte)
- if !ok {
- // 发送控制消息
- mesCode, _ := sendData.Value.(byte)
- hType = mesCode
- }
- headLen := structPack(buf, "BBQHIII", uint8(TypeData), hType,
- uint64(u.Id), uint16(len(sdata)+4+4+4), u.seq, uint32(now), uint32(sendMax))
- copy(buf[headLen:], sdata)
- u.sock.WriteToUDP(buf[:headLen+len(sdata)], u.remote)
- glog.V(4).Infof("send, seq:%v id:%v %v", u.seq, u.Id, u.name)
- index := (u.dataBegin + u.dataLen) % len(u.data)
- u.data[index] = DataSend{
- Seq: u.seq,
- Time: now,
- Code: hType,
- Data: sdata,
- }
- u.seq++
- u.dataLen++
- }
- listRemain := u.writeMax - u.sendList.Len()
- u.sendListLock.Unlock()
- if listRemain > 0 {
- select {
- case u.writable <- !u.isClose:
- default:
- }
- }
- if u.isClose && u.dataLen == 0 && u.closing == false { // 修复bug: 之前5秒删除,实际发送没完成
- // 修复bug: 接受端write端close为true, 导致5秒后呗删除,来不及接受数据。
- glog.V(1).Infof("close and emtpy, rm conn, id:%v name:%v seq:%v listlen:%v",
- u.Id, u.name, u.seq, u.sendList.Len())
- u.closing = true
- u.conn.close(false, true)
- }
- }
- func testDrop() bool {
- if dropRate < 0.01 {
- return false
- }
- var v uint32
- var b [4]byte
- if _, err := crand.Read(b[:]); err != nil {
- v = mrand.Uint32()
- } else {
- v = binary.BigEndian.Uint32(b[:])
- }
- if v%1000 < uint32(dropRate*1000) {
- return true
- }
- return false
- }
- func (u *UdpSend) recv(buf []byte) {
- if testDrop() {
- return
- }
- now := uint32(time.Now().UnixNano() / int64(time.Millisecond))
- // ack包: type0 flag1 id2 len3 tm4 rcvwnd5 acked6
- head, headLen := structUnPack(buf, "BBQHIII")
- if head[0] == uint64(TypeAck) && u.dataLen > 0 {
- firstSeq := u.data[u.dataBegin].Seq
- acked := uint32(head[6])
- offset := int(int32(acked - firstSeq))
- glog.V(4).Infof("id:%v recv ack: %v offset:%v databegin:%v dataLen:%v firstSeq:%v name:%v",
- u.Id, acked, offset, u.dataBegin, u.dataLen, firstSeq, u.name)
- if offset >= 0 && offset < u.dataLen {
- offset++
- for i := 0; i < offset; i++ { // 修复bug: 清除引用等
- index := (u.dataBegin + i) % len(u.data) // 修复bug,i写成offset
- d := &u.data[index]
- d.Data = nil
- d.Acked = true
- }
- u.acked += uint32(offset)
- u.dataBegin += offset
- u.dataBegin = u.dataBegin % len(u.data)
- u.dataLen -= offset
- glog.V(4).Infof("2 acked ok:%v, id:%v %v", u.acked, u.Id, u.name)
- }
- if u.dataLen > 0 {
- curSeq := u.data[u.dataBegin].Seq
- // var ackedSeq = []uint32{}
- for i := headLen; i < len(buf); i += 4 {
- seq := binary.BigEndian.Uint32(buf[i:])
- offset := int(int32(seq - curSeq))
- if offset < 0 || offset >= u.dataLen {
- continue
- }
- index := (u.dataBegin + offset) % len(u.data)
- d := &u.data[index]
- if d.Seq == seq {
- d.Acked = true
- d.Data = nil // 修复bug: memory leak
- // ackedSeq = append(ackedSeq, seq)
- } else {
- panic("index not correct")
- }
- }
- // if len(ackedSeq) > 0 {
- // glog.V(0).Info("seq:", ackedSeq)
- // }
- }
- var i = 0
- for ; i < u.dataLen; i++ {
- index := (i + u.dataBegin) % len(u.data)
- d := &u.data[index]
- if d.Acked == false {
- break
- }
- // fmt.Println("acked->", d.Seq)
- // if d.Seq == 7 {
- // fmt.Println("data:", u.data[u.dataBegin:u.dataBegin+5])
- // }
- }
- if i > 0 {
- u.acked += uint32(i)
- u.dataBegin += i
- u.dataBegin = u.dataBegin % len(u.data)
- u.dataLen -= i
- glog.V(4).Infof("3 acked ok:%v, id:%v %v %v", u.acked, u.Id, u.dataBegin, u.name)
- }
- sendTime := uint32(head[4])
- rtt := now - sendTime
- if rtt > 0 {
- if firstSeq < 3 {
- u.rtt = float64(rtt) // 初始值
- } else {
- u.rtt = u.rtt*0.8 + float64(rtt)*0.2
- }
- if u.rtt < 50.0 {
- u.rtt = 50
- }
- // glog.V(4).Infof("rtt:%v u.rtt:%v id:%v", rtt, u.rtt, u.Id)
- }
- u.recvWnd = uint32(head[5])
- }
- }
- func structPack(b []byte, format string, param ...interface{}) int {
- j := 0
- for i, s := range format {
- switch s {
- case 'I':
- p, _ := param[i].(uint32)
- binary.BigEndian.PutUint32(b[j:], p)
- j += 4
- case 'B':
- p, _ := param[i].(uint8)
- b[j] = p
- j++
- case 'H':
- p, _ := param[i].(uint16)
- binary.BigEndian.PutUint16(b[j:], p)
- j += 2
- case 'Q':
- p, _ := param[i].(uint64)
- binary.BigEndian.PutUint64(b[j:], p)
- j += 8
- default:
- panic("structPack not found")
- }
- }
- return j
- }
- func structUnPack(b []byte, format string) ([]uint64, int) {
- var re = make([]uint64, 0, len(format))
- defer func() {
- if err := recover(); err != nil {
- // log.Error(err)
- re[0] = 0
- }
- }()
- j := 0
- for _, s := range format {
- switch s {
- case 'I':
- re = append(re, uint64(binary.BigEndian.Uint32(b[j:])))
- j += 4
- case 'B':
- re = append(re, uint64(b[j]))
- j++
- case 'H':
- re = append(re, uint64(binary.BigEndian.Uint16(b[j:])))
- j += 2
- case 'Q':
- re = append(re, uint64(binary.BigEndian.Uint64(b[j:])))
- j += 8
- default:
- panic("structUnPack not found")
- }
- }
- return re, j
- }
- type UdpRecv struct {
- conn *Conn
- Id uint64
- sock *net.UDPConn
- remote *net.UDPAddr
- acked uint32
- lastTm uint32
- sndWnd uint32
- recvCnt uint32
- isClose bool
- isNew byte
- isRecved bool
- recvList *list.List
- recvListLock sync.Mutex
- readable chan byte
- readDeadline *time.Time
- seqData map[uint32]*DataRecv
- dataList *list.List
- name string
- }
- func NewUdpRecv(conn *Conn, id uint64, sock *net.UDPConn, remote *net.UDPAddr, name string) *UdpRecv {
- return &UdpRecv{
- Id: id,
- conn: conn,
- sock: sock,
- remote: remote,
- acked: 0,
- recvList: list.New(),
- dataList: list.New(),
- seqData: make(map[uint32]*DataRecv),
- readable: make(chan byte, 1),
- isNew: 50,
- name: name,
- sndWnd: 1000,
- }
- }
- func (u *UdpRecv) SetReadDeadline(t time.Time) {
- u.readDeadline = &t
- }
- func (u *UdpRecv) sendAck(nowTime time.Time, buf []byte) {
- u.recvListLock.Lock()
- for {
- if d, ok := u.seqData[u.acked+1]; ok {
- u.acked++
- if d.Code == TypeClose {
- if u.isClose == false {
- glog.V(1).Info("recv close:", u.Id)
- u.conn.close(false, true)
- u.isClose = true
- }
- } else {
- u.recvList.PushBack(d.Data)
- }
- d.Data = nil
- delete(u.seqData, u.acked)
- } else {
- break
- }
- }
- recvListLen := u.recvList.Len()
- u.recvListLock.Unlock()
- // glog.V(4).Info("acked:", u.acked, u.Id, recvListLen, u.name)
- if recvListLen > 0 { // 修复bug,用标志可能会有读不到的数据 修复bug: 去掉 && u.isClose == false,导致读取延迟
- select {
- case u.readable <- 1:
- default:
- }
- } else if u.isClose == true { // 修复bug:快速close
- select {
- case u.readable <- 0:
- default:
- }
- }
- if u.readDeadline != nil && !u.readDeadline.IsZero() {
- if u.readDeadline.Before(nowTime) { // 修复bug after
- select {
- case u.readable <- 2:
- glog.V(0).Info("read dealline: ", u.Id)
- default:
- }
- }
- }
- var b = buf[:mss]
- buf = buf[mss:]
- var n = 0
- for i := u.dataList.Front(); i != nil; {
- d := i.Value.(*DataRecv)
- next := i.Next()
- if d.AckCnt > 6 || before(d.Seq, u.acked+1) { // 发几次够了,不反复发
- // d.Removed = true
- u.dataList.Remove(i) // 修复bug,删除逻辑不对,需要保存next
- // delete(u.seqData, d.Seq) // 修复bug: 对面已经确认,这里删了,没有重发,也没有了数据。已经收到的数据并且发了ack的数据,不要删了!
- i = next
- continue
- }
- i = next
- if d.AckCnt%3 == 0 {
- binary.BigEndian.PutUint32(b[n:], d.Seq)
- n += 4
- if n >= len(b) {
- wnd := int(u.sndWnd) - recvListLen - len(u.seqData)
- if wnd < 0 {
- wnd = 0
- }
- headLen := structPack(buf, "BBQHIII", uint8(TypeAck), uint8(0), uint64(u.Id), uint16(4+4+4+n),
- u.lastTm, uint32(wnd), u.acked)
- copy(buf[headLen:], b[:n])
- u.sock.WriteToUDP(buf[:headLen+n], u.remote)
- glog.V(4).Infof("id:%v send ack n:%v", u.Id, n)
- n = 0 // 修复bug,没有置零
- u.isRecved = false // 修复bug: 有时候发多一条数据
- }
- }
- d.AckCnt++
- }
- if n > 0 || u.isRecved { // 修复bug: 一直发数据 修复bug: 有时候发多一条数据
- wnd := int(u.sndWnd) - recvListLen - len(u.seqData)
- if wnd < 0 {
- wnd = 0
- }
- headLen := structPack(buf, "BBQHIII", uint8(TypeAck), uint8(0), uint64(u.Id), uint16(4+4+4+n),
- u.lastTm, uint32(wnd), u.acked)
- copy(buf[headLen:], b[:n])
- u.sock.WriteToUDP(buf[:headLen+n], u.remote)
- glog.V(4).Infof("id:%v send ack n:%v datalen:%v", u.Id, n, u.dataList.Len())
- }
- u.isRecved = false
- // 修复bug: 如果自己只是发数据,那么自己的acked通道会没用到。所以要判断自己是否在发送数据。
- if u.isNew > 0 { // 完成的优化:超时不确认第一包,就删除链接。防止旧链接不断发包。
- u.isNew--
- if u.isNew == 0 && u.acked == 0 {
- glog.V(0).Infof("not recv first packet!!! close, id:%v name:%v", u.Id, u.name)
- u.conn.Close()
- }
- if u.acked >= 1 || u.conn.s.seq > 1 {
- u.isNew = 0
- }
- }
- }
- // before seq1比seq2小
- func before(seq1, seq2 uint32) bool {
- return (int32)(seq1-seq2) < 0
- }
- func after(seq1, seq2 uint32) bool {
- return (int32)(seq2-seq1) < 0
- }
- func (u *UdpRecv) recv(buf []byte) {
- if testDrop() {
- return
- }
- u.isRecved = true
- u.recvCnt++
- // data包: type0 flag1 id2 len3 seq4 tm5 sndwnd6
- head, headLen := structUnPack(buf, "BBQHIII")
- if head[0] == uint64(TypeData) {
- seq := uint32(head[4])
- u.lastTm = uint32(head[5])
- u.sndWnd = uint32(head[6])
- glog.V(4).Info(u.Id, " recv seq: ", seq, " len: ", u.dataList.Len())
- if before(seq, u.acked+1) { // 修复bug: 收到before的数据,seqData不会回收。
- // glog.V(0).Info("seq before u.acked:", seq, u.acked, u.Id)
- return
- }
- // 修复bug: 修复没重发问题。之前由于一直会重发,这个逻辑有意义。现在只重发几次。
- // if d, ok := u.seqData[seq]; ok {
- // d.AckCnt = 0
- // if d.Removed == false { // 修复bug:可能没ack导致一直重发,要直到acked全部覆盖。
- // return
- // }
- // }
- // glog.V(4).Info(u.Id, " recv 2 seq: ", seq, " len: ", u.dataList.Len())
- d := &DataRecv{
- Seq: seq,
- Data: buf[headLen:],
- Code: byte(head[1]),
- }
- u.dataList.PushBack(d)
- u.seqData[seq] = d
- }
- }
- func SetRate(rate uint32) {
- defaultRate = rate
- }
- func SetDropRate(rate float64) {
- if rate > 0.001 {
- dropRate = rate
- }
- }
- type Conn struct {
- Id uint64
- s *UdpSend
- r *UdpRecv
- responsed chan bool
- isClose bool
- isSendClose bool
- isRmConn bool
- conns *Conns
- }
- func NewConn(conns *Conns, Id uint64, localConn *net.UDPConn, remote *net.UDPAddr, name string) *Conn {
- conn := &Conn{
- Id: Id,
- conns: conns,
- responsed: make(chan bool, 1),
- }
- conn.s = NewUdpSend(conn, conn.Id, localConn, remote, name)
- conn.r = NewUdpRecv(conn, conn.Id, localConn, remote, name)
- return conn
- }
- func (c *Conn) Write(bb []byte) (n int, err error) {
- if c.isClose {
- return 0, ErrClose
- }
- // 1.对方告诉你满了,是要叫你不要发数据了,而不是还发数据。
- // 2.没有窗口就没法快速地确定对面有没有满,如果你要等到自己的的buffer满,那么可能会比较慢感知到
- // 固定buffer + 停止通知
- b := make([]byte, len(bb)) // 修复bug1:没有拷贝
- copy(b, bb)
- for {
- c.s.sendListLock.Lock()
- remain := c.s.writeMax - c.s.sendList.Len()
- for {
- if len(b) <= 0 {
- break
- }
- if remain <= 0 {
- break
- }
- remain--
- var sendLen = int(mss)
- if len(b) < sendLen {
- // 实际发送值
- sendLen = len(b)
- }
- n += sendLen
- c.s.sendList.PushBack(b[:sendLen])
- // fmt.Println("write:", b[:10])
- b = b[sendLen:]
- }
- c.s.sendListLock.Unlock()
- if len(b) <= 0 {
- break
- }
- // glog.V(0).Info("wait write: ", c.Id)
- w := <-c.s.writable
- if w == false {
- return n, ErrClose
- }
- }
- return n, nil
- }
- func (c *Conn) Read(b []byte) (n int, err error) {
- for {
- c.r.recvListLock.Lock()
- for {
- f := c.r.recvList.Front()
- if f != nil {
- data := f.Value.([]byte)
- copy(b[n:], data)
- maxCap := len(b[n:])
- if maxCap < len(data) {
- // b已满
- f.Value = data[maxCap:]
- n += maxCap
- break
- } else {
- // b未满
- c.r.recvList.Remove(f)
- n += len(data)
- }
- } else {
- // 读完数据了
- break
- }
- }
- c.r.recvListLock.Unlock()
- if n <= 0 {
- // glog.V(4).Info("wait read", c.Id)
- // wait for chan
- r := <-c.r.readable
- if r == 0 { // close之后总是返回初始值
- c.r.recvListLock.Lock()
- rlen := c.r.recvList.Len()
- c.r.recvListLock.Unlock()
- if rlen <= 0 { // 修复bug: 等到read完所有数据才让read返回错误
- return n, ErrClose
- }
- }
- if r == 2 {
- return n, ErrTimeout
- }
- } else {
- break
- }
- }
- return
- }
- func (c *Conn) LocalAddr() net.Addr {
- return c.conns.sock.LocalAddr()
- }
- func (c *Conn) RemoteAddr() net.Addr {
- return c.conns.sock.RemoteAddr()
- }
- func (c *Conn) SetDeadline(t time.Time) error {
- c.r.SetReadDeadline(t)
- return nil
- }
- func (c *Conn) SetReadDeadline(t time.Time) error {
- c.r.SetReadDeadline(t)
- return nil
- }
- func (c *Conn) SetWriteDeadline(t time.Time) error {
- return nil
- }
- func (c *Conn) close(sendClose, rmConn bool) {
- if c.isClose == false {
- c.isClose = true
- c.r.isClose = true
- }
- if sendClose && c.isSendClose == false { // 修复bug:
- c.isSendClose = true
- c.s.sendListLock.Lock()
- c.s.sendList.PushBack(byte(TypeClose))
- c.s.sendListLock.Unlock()
- }
- if rmConn && c.isRmConn == false {
- c.isRmConn = true
- time.AfterFunc(time.Second*5, func() {
- select {
- case c.conns.input <- Input{
- typ: ActRmConn,
- param: c,
- }:
- default:
- }
- })
- }
- }
- func (c *Conn) Close() error {
- if c.isClose == false {
- c.isClose = true
- c.s.isClose = true
- // bug: 接收不能主动关闭
- c.isSendClose = true
- c.s.sendListLock.Lock()
- c.s.sendList.PushBack(byte(TypeClose))
- c.s.sendListLock.Unlock()
- // bug: close之后,5秒数据可能无法完成发送
- }
- return nil
- }
- type Conns struct {
- conns map[uint64]*Conn
- sock *net.UDPConn
- accept chan *Conn
- isClose bool
- isDial bool
- timerRnd uint32
- input chan Input
- }
- func NewConns() *Conns {
- return &Conns{
- conns: make(map[uint64]*Conn),
- accept: make(chan *Conn, 256),
- input: make(chan Input, 2048),
- }
- }
- func Listen(network, address string) (net.Listener, error) {
- addr, err := net.ResolveUDPAddr("udp", address)
- if err != nil {
- return nil, err
- }
- conn, err := net.ListenUDP("udp", addr)
- if err != nil {
- return nil, err
- }
- listener := NewConns()
- listener.sock = conn
- go listener.loop()
- return listener, nil
- }
- var dialConns *Conns
- var dialConnsLock sync.Mutex
- func Dial(network, address string) (net.Conn, error) {
- return DialTimeout(network, address, time.Second*3)
- }
- func DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
- addr, err := net.ResolveUDPAddr("udp", address)
- if err != nil {
- return nil, err
- }
- var b [8]byte
- if _, err := crand.Read(b[:]); err != nil {
- return nil, err
- }
- id := binary.LittleEndian.Uint64(b[:])
- glog.V(0).Info("dial new 3:", id)
- dialConnsLock.Lock()
- if dialConns == nil {
- dialConns = NewConns()
- }
- if dialConns.sock == nil {
- s, err := net.ListenUDP("udp", &net.UDPAddr{})
- if err != nil {
- dialConnsLock.Unlock()
- return nil, err
- }
- dialConns.sock = s
- dialConns.isDial = true
- go dialConns.loop()
- }
- dialConnsLock.Unlock()
- conn := NewConn(dialConns, id, dialConns.sock, addr, "reqer")
- dialConns.input <- Input{
- typ: ActAddConn,
- param: conn,
- }
- // conn.s.sendListLock.Lock()
- // conn.s.sendList.PushBack(byte(TypeSYN))
- // conn.s.sendListLock.Unlock()
- return conn, nil
- }
- func (c *Conns) Accept() (net.Conn, error) {
- for {
- if c.isClose {
- return nil, errors.New("listener close")
- }
- conn := <-c.accept
- if conn == nil {
- return nil, errors.New("listener close")
- }
- return conn, nil
- }
- }
- func (c *Conns) Close() error {
- c.isClose = true
- c.sock.Close()
- c.input <- Input{
- typ: ActEnd,
- }
- return nil
- }
- func (c *Conns) Addr() net.Addr {
- return c.sock.LocalAddr()
- }
- const (
- ActData = 1
- ActTimer = 2
- ActAddConn = 3
- ActRmConn = 4
- ActEnd = 5
- )
- type Input struct {
- typ uint8
- data []byte
- param interface{}
- }
- func (c *Conns) loop() {
- // 这里输入时间和数据
- // 只起一个timer,给所有conn发
- // 之前用setreaddeadline这个不太好,容易出现长时间没超时
- runtime.LockOSThread()
- glog.V(0).Info("loop: ", c.isDial)
- go func() {
- var buf = make([]byte, 2048)
- for {
- n, remote, err := c.sock.ReadFromUDP(buf)
- if n <= 0 || err != nil {
- c.Close()
- return
- }
- b := make([]byte, n)
- copy(b, buf[:n])
- c.input <- Input{
- typ: ActData,
- data: b,
- param: remote,
- }
- if c.isClose {
- return
- }
- }
- }()
- var timerRunning bool
- var releaseMemory uint32
- var buf = make([]byte, mss*3)
- for {
- data := <-c.input
- switch data.typ {
- case ActData:
- head, _ := structUnPack(data.data, "BBQ")
- // fmt.Println(head[0], head[2])
- var dataType = head[0]
- if conn, ok := c.conns[head[2]]; ok {
- // TODO: 给dial中的链接发送成功 -> 暂时不需要,现在dial不判断这些,默认成功
- if dataType == uint64(TypeData) {
- conn.r.recv(data.data)
- } else if dataType == uint64(TypeAck) {
- conn.s.recv(data.data)
- }
- } else {
- if c.isDial == false && dataType == uint64(TypeData) && c.isClose == false { // 不需要TypeSYN
- // glog.V(0).Info("create new:", head[2])
- // 只有主动listen的,才有新链接,而dial自己就会创建新连接,不用创建
- conn := NewConn(c, head[2], c.sock, data.param.(*net.UDPAddr), "rsper")
- c.conns[conn.Id] = conn
- conn.r.recv(data.data)
- select {
- case c.accept <- conn:
- default:
- }
- if timerRunning == false {
- timerRunning = true
- go c.runTimer(c.timerRnd)
- glog.V(0).Info("start timer, round:", c.timerRnd, c.isDial)
- }
- }
- }
- case ActTimer:
- now := time.Now()
- for _, conn := range c.conns {
- conn.s.send(now, buf)
- conn.r.sendAck(now, buf)
- }
- if len(c.conns) == 0 && timerRunning {
- glog.V(0).Info("no conn, stop timer, round:", c.timerRnd, c.isDial)
- c.timerRnd++
- timerRunning = false
- debug.FreeOSMemory()
- }
- releaseMemory++
- if releaseMemory > 50*60 {
- releaseMemory = 0
- go func() {
- debug.FreeOSMemory() // 修复bug: go在windows不回收内存
- }()
- }
- case ActAddConn:
- conn := data.param.(*Conn)
- c.conns[conn.Id] = conn
- if timerRunning == false {
- timerRunning = true
- go c.runTimer(c.timerRnd)
- glog.V(0).Info("start timer, round:", c.timerRnd, c.isDial)
- }
- case ActRmConn:
- conn := data.param.(*Conn)
- // fmt.Println("rm conn:", conn.Id)
- conn.isClose = true
- conn.s.isClose = true
- conn.r.isClose = true
- if _, ok := c.conns[conn.Id]; ok {
- glog.V(0).Info("rm conn ok:", conn.Id, c.isDial, len(c.conns))
- close(conn.r.readable)
- close(conn.s.writable) // 修复bug: 没有close
- delete(c.conns, conn.Id)
- }
- case ActEnd:
- c.timerRnd++
- timerRunning = false
- c.isClose = true
- for _, conn := range c.conns {
- conn.isClose = true
- conn.s.isClose = true
- conn.r.isClose = true
- close(conn.r.readable)
- close(conn.s.writable)
- }
- close(c.accept)
- c.conns = make(map[uint64]*Conn)
- return
- }
- }
- }
- func (c *Conns) runTimer(rnd uint32) {
- // runtime.LockOSThread()
- for {
- time.Sleep(20 * time.Millisecond)
- // C.usleep(20 * 1000)
- if rnd != c.timerRnd {
- glog.V(0).Info("timer stop, round:", rnd, c.isDial)
- }
- if c.isClose || rnd != c.timerRnd {
- return
- }
- c.input <- Input{typ: ActTimer}
- }
- }
|