Giter Club home page Giter Club logo

cellnet's Issues

proc gorillaws接收消息崩溃

客户端发送消息包到服务器,服务器崩溃

func (WSMessageTransmitter) OnRecvMessage(ses cellnet.Session) (msg interface{}, err error) {

	conn, ok := ses.Raw().(*websocket.Conn)

	// 转换错误,或者连接已经关闭时退出
	if !ok || conn == nil {
		return nil, nil
	}

	var messageType int
	var raw []byte
	messageType, raw, err = conn.ReadMessage()

	if err != nil {
		return
	}

	switch messageType {
	case websocket.BinaryMessage:
		msgID := binary.LittleEndian.Uint16(raw)
		msgData := raw[MsgIDSize:]

		msg, _, err = codec.DecodeMessage(int(msgID), msgData)
	}

	return
}
msgID := binary.LittleEndian.Uint16(raw)

应改为

msgID := binary.LittleEndian.Uint16(raw[:MsgIDSize])

HTTP(测试中)

我看HTTP(测试中),请问一下,这个有发布计划吗?

BroadcastToClientList 有一个小BUG

不是大问题,只是新创建空间后,地址没有赋给self对象造成的。
表现 BroadcastToClientList 指定用户不能正常收到广播。

review源码中发现问题出在:
router\routerconn.go 187行,


list = make([]int64, 0)
改成
self[routerSes] = make([]int64, 0)
list = self[routerSes]

@davyxu

concurrent write to websocket connection

hi, davyxu

我在使用 cellnet 做 websocket 服务的时候,发现 event.send 会出现写并发的情况。
例如,在 websocket 例子中复制发送的内容几行:
ev.Send(&jsongamedef.TestEchoJsonACK{Content: "roger1"})
ev.Send(&jsongamedef.TestEchoJsonACK{Content: "roger2"})
ev.Send(&jsongamedef.TestEchoJsonACK{Content: "roger3"})
ev.Send(&jsongamedef.TestEchoJsonACK{Content: "roger4"})
ev.Send(&jsongamedef.TestEchoJsonACK{Content: "roger5"})
触发会报 concurrent write to websocket connection.

另外,目前 websocket 链接接收的是文本,以后会考虑加入二进制,支持 protobuf 呢?

cellnet 很棒:)

目前master的example websocket 無作用

依照index.html發送封包
server無法解析

[DEBU] websocket_server 2018/11/15 10:17:58 session closed: 2
[DEBU] gorillawsproc 2018/11/15 10:17:58 #ws.recv(server)@3 len: 0 SessionAccepted | {}
[DEBU] websocket_server 2018/11/15 10:17:58 server accepted
[DEBU] gorillawsproc 2018/11/15 10:17:58 #ws.recv(server)@3 len: 0 |

換回8月中抓的版本可正常運行

封包长度有限制

@davyxu 你好,我在使用cellnet的时候,发现V5版本有默认封包长度限制,客户端发送的是完整封包(大约30K),而服务端收到的就大概只有10K左右,然后服务端就会报错,Session会断开再连接,具体错误提示如下,请问一下该如何解决?

[ERRO] tcppeer 2018/06/27 20:54:58 session closed, sesid: 2, err: msg not exists, '26479'
[DEBU] tcpproc 2018/06/27 20:54:58 #tcp.recv(server)@2 len: 0 SessionClosed | {}
[DEBU] tcpproc 2018/06/27 20:55:00 #tcp.recv(server)@3 len: 0 SessionAccepted | {}

PS:V4版本没这个问题。

【错误】lineraPipe 没有友好的退出

func (self *lineraPipe) Stop(result int) {
self.exitSignal <- result
}
func (self *lineraPipe) Wait() int {
return <-self.exitSignal
}

Stop 执行后,并没有友好地停止之前的读取 datachan 循环。

回调地狱 Callback Hell

cellnet 是回调模式。如果用cellnet 实现逻辑服务器,一般需要访问其他服务(例如 查询好友信息, 锁服务端等) 。 这样很容易掉入Callback Hell。 请问,实际的项目中,你是如何解决这个问题的?

建议工程的描述加上 server framework关键字

因为这几天在不断搜索golang相关的游戏服务器技术,但却很难搜到cellnet,是因为一般人都是搜的 game, server framework这几个关键字。。而出来的都是些几百k的项目。 很少有人会去搜索 network library吧~ 所以只是个建议,让更多人发现cellnet.

这一块不是很能看懂,为什么要执行两次DecodeMessage

func (self *DecodePacketHandler) Call(ev *Event) {

	var err error
	ev.Msg, err = DecodeMessage(ev.MsgID, ev.Data)

	r := errToResult(err)
	if r != Result_OK {
		ev.Msg, _ = DecodeMessage(ev.MsgID, ev.Data)

		ev.SetResult(r)
	}

}

这一块不是很能看懂,为什么要执行两次DecodeMessage, 望解答

问题和建议

1,问题
客户端socket 断了, 我知道是哪个socket 端了吗?
Send发消息是堵塞的吗? 如果我有几千个链接,发到后面不是要延迟好久? 然后ses 发东西的时候类似线程安全吗?
Peer 在客户端断开的时候, 发消息会宕机 , 这个还需要自己处理好多东西,
2, 建议,
感觉网络通信框架 和protobuf 还有其他的 协议要分开,没必要都支持了, 就做纯的网络框架,其他功能通过插件的方式实现
感觉golang 的特色 chan 用的很少, 总觉得不能发挥go 的优势

哈哈哈哈
很赞的设计

Pick 函数的规范实现

更简洁的实现是

func (self *Pipe) Pick(retList *[]interface{}) (exit bool) {
self.listGuard.Lock()
defer self.listGuard.UnLock()

for len(self.list) == 0 {
	self.listCond.Wait()
}

// 复制出队列
   // 下面的代码保持一样的

}

rpc调用修改建议

当同一个消息使用rpc在不同的地方多次调用时, 会发生callback函数错乱调用,即A处的结果会调用到B处的callback函数
建议:为每一个rpc指定一个唯一的rpcid,通过rpcid找到callback函数,那么A处的结果必然调用A自己的callback函数

socket中有个错误

`连不上
if err != nil {

		if self.tryConnTimes <= reportConnectFailedLimitTimes {
			log.Errorf("#connect failed(%s) %v", self.name, err.Error())
		}

		if self.tryConnTimes == reportConnectFailedLimitTimes {
			log.Errorf("(%s) continue reconnecting, but mute log", self.name)
		}

		// 没重连就退出
		if self.autoReconnectSec == 0 {
			break
		}

		// 有重连就等待
		time.Sleep(time.Duration(self.autoReconnectSec) * time.Second)

		// 继续连接
		continue
	}`

if self.tryConnTimes <= reportConnectFailedLimitTimes应该是>=吧

peer mysql如何获取db连接池对象

type mysqlConnector struct {
	peer.CorePeerProperty
	peer.CoreContextSet
	peer.CoreSQLParameter

	db      *sql.DB
	dbGuard sync.RWMutex
}
func NewWrapper(drv *sql.DB) *Wrapper {

	return &Wrapper{
		drv: drv,
	}
}

db连接池对象是私有的,与数据库交互的封装需要传入连接池对象,是否应该提供接口获取连接池对象

Send的问题

const sendTotalTryCount = 100

func (self *ltvStream) Flush() error {

	var err error
	for tryTimes := 0; tryTimes < sendTotalTryCount; tryTimes++ {

		err = self.outputWriter.Flush()

		// 如果没写完, flush底层会将没发完的buff准备好, 我们只需要重新调一次flush
		if err != io.ErrShortWrite {
			break
		}
	}

	return err
}

假设要发送唯一一个非常大的包,而接收端接收非常缓慢,导致tryTimes超过sendTotalTryCount

这种情况下,是否会出现sendThtread永远阻塞在BeginPick上,而对端永远接收不到完整的包

为啥不用io.ReadAtLeast ,这样不会粘包么

pktstream.go里
Read函数部分
直接readFull有点不靠谱吧,这样封包没发全会直接断开的吧,tcp搞的和udp一样一个包一个包发有什么特殊含义么。
主要我用websocket发送消息的时候,send我不知道是不是writeFull....内部实现又看不到。
用ReadAtLeast不就没啥问题了么。

not enough arguments in call to codec.EncodeMessage

# github.com/davyxu/cellnet/proc/gorillaws \github.com\davyxu\cellnet\proc\gorillaws\transmitter.go:79:40: not enough arguments in call to codec.EncodeMessage have (interface {}) want (interface {}, cellnet.ContextSet)

client构建脏包,导致server崩溃

client构建的tcp包,如果有意将ltv中的包长度小于实际长度,则server会崩溃。server在对数据copy的时候,轻信ltv注明长度,引发range溢出。

StringHash not unique, may cause msgid same

这是测试代码
func TestStringHash(t *testing.T) {
a:="msg_protos.PKT_S2C_Reconnection_World_Status"
b:="msg_protos.ShipEquipFireReq"
t.Logf("a:%d,b:%d",StringHash(a),StringHash(b))
}
这是结果
strhash_test.go:8: a:7809,b:7809
如此下来,StringHash会有重复,会导致file.go MsgID 重复。
希望能换个MsgID的实现方式

支持一下自定义listener

listener net.Listener

标准的库的net.Listener是很好,但是遇到CC攻击获取其他高并发的情况下就麻烦了
比如我想用用这个库 https://github.com/valyala/tcplisten

所以支持一下自定义Listener,

还有网络库怎么能少得了这个方便的东西:
func setMaxConn() error { var RLimit syscall.Rlimit err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &RLimit) if err != nil { return err } log.Info("get setrlimit success", zap.Uint64("cur", RLimit.Cur), zap.Uint64("max", RLimit.Max)) RLimit.Cur = 800000 RLimit.Max = 800000 err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &RLimit) if err != nil { return err } err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &RLimit) if err != nil { return err } log.Info("set setrlimit success", zap.Uint64("cur", RLimit.Cur), zap.Uint64("max", RLimit.Max)) return nil }

建议给封包那边写个文档说明

写客户端通信组件的时候也方便点不是吗。最近我在写个js和wx小程序的项目。客户端发包和解包的时候得和cellnet对应一下。我这里是写完了。但是要是有个文档我估计会更方便别人做一些后续开发。
只是提一下建议。

websocket 客服端关闭服务端无法释放 Goroutine

我尝试建立大量链接,并关闭后,统计链接数量,一直持续增长
后来发现是github.com/davyxu/cellnet/peer/gorillaws/session.go
cleanup() 时没有清理干净导致修改后代码为
// 清理资源
func (self *wsSession) cleanup() {

self.cleanupGuard.Lock()

defer self.cleanupGuard.Unlock()

// 关闭连接
if self.conn != nil {
	self.conn.Close()
	self.conn = nil
}
   //没有清理这个
self.Close()
// 通知完成
self.exitSync.Done()

}
之后就正常,希望修复下这个问题。

relay功能?

tcp 里面支持

// 带有RPC和relay功能
type MsgHooker struct {
}

请问什么是relay? 适用于怎么样的场景?

websocket session.close

websocket 中调用 session.close 会引起并发写入的 panic

msg := ev.Msg.(*jsongamedef.TestEchoJsonACK)
ev.Send(&jsongamedef.TestEchoJsonACK{Content: "roger"})
ev.Ses.Close()

panic: concurrent write to websocket connection
goroutine 19 [running]:
github.com/gorilla/websocket.(*messageWriter).flushFrame(0xc042127d28, 0xc04204c501, 0xc04204c518, 0x0, 0x0, 0x0, 0x0)
github.com/davyxu/cellnet/websocket.(*wsSession).Close(0xc04210a340)

TCP 性能问题

func (self *tcpSession) sendLoop() {

tcp里面发送数据能一次多发几个包吗?游戏里面很多小包,这样服务于服务之间性能很低,日志可以在这个循环里面输出。

func WriteFull(writer io.Writer, p []byte) error {

这个没必要for ,以golang的尿性,再大的包都是一次性发送完成才返回。如果实际发送字节小于[]byte数组的长度,那基本上socket已经异常了,应该执行Close(). 发送缓冲区满了会阻塞在Write()

还有,tcp的设置一下发送和接收超时啊。这个东西没得的话,阻塞了都不知道咋回事

缺少peer_websocket.go

您好,克隆下来有peer_tcp.go,但找不到 peer_websocket.go,目前比较常跟client连接的是websocket
可否补上?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.