Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C#] 发送的消息应该保证顺序 #5

Open
chentmin opened this issue Jul 31, 2017 · 3 comments
Open

[C#] 发送的消息应该保证顺序 #5

chentmin opened this issue Jul 31, 2017 · 3 comments

Comments

@chentmin
Copy link
Contributor

现在在C#端, 就算调用方是单线程在调用发送, 底下会把发送放到个线程池中, 短时间内发送多条消息时, 更容易发生消息的顺序改变的情况.

这样的话, 就要求使用snet的项目对C#发过来的消息的顺序不能有要求, 甚至可能在逻辑上会有问题, 比如客户端是先跳再放的技能, 服务器先收到了放技能的消息.

		public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback callback, object state)
		{
			AsyncResult ar1 = new AsyncResult (callback, state);
			ThreadPool.QueueUserWorkItem ((object ar2) => {
				AsyncResult ar3 = (AsyncResult)ar2;
				try {
					Write(buffer, offset, count);
				} catch(Exception ex) {
					ar3.Error = ex;
				}
				ar3.IsCompleted = true;
				((ManualResetEvent)ar3.AsyncWaitHandle).Set();
				if (ar3.Callback != null)
					ar3.Callback(ar3);
			}, ar1);
			return ar1;
		}
@chentmin
Copy link
Contributor Author

本来就要在写入的时候把要发送的字节数copy到rewriter以备之后重发, 不如就在写入的线程里, 只把要写的字节数刷到rewriter里, 然后通知负责flush的线程有数据要发送. flush线程负责从上次刷成功的index开始, 写入剩余未写入的部分. 这样子修改的好处是

  • 合并多个小write
  • 写线程单线程
  • 逻辑简单, 写线程只负责把rewriter里的未发送成功的数据发出去, 重连成功和正常情况是一样的代码. 断线重连就真的只需要断开旧连接, 发起新连接的时候重置上次发送成功的index就可以.

需要额外处理发送得很慢的情况, 逻辑线程要写数据时, 未发送的数据数量超过了rewriter的大小. 可以考虑

  • 超过了就直接断线, 有64k(根据配置)的数据没有发成功, 本来就表示这连接有问题
  • 也可以临时增加rewriter的大小, 让逻辑线程可以把数据刷进去先返回. rewriter大小达到另一个配置的未发送消息的上限后, 断线

@patricksuo
Copy link

@chentmin 请问你们有修复这个问题吗?

@chentmin
Copy link
Contributor Author

木有, 偶c#不溜

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants