一步一步开发Game服务器(二)登陆2
上一篇文章,讲解了简单的登陆情况。接下来我们继续讲解登陆模块。
在正常的游戏服务器情况下。在尚未登录前可以查看服务器大区情况,登陆后也可以查看服务器大区情况,然后选择大区服务器。进行登录操作。
这样的情况就需要我们有一个登录服务器来负责,目前大区服务器的状态,是正常。拥挤,爆满。还是停服维护。那么这样登录服务器,如果进行控制和输出呢?
如何与大区服务器正常进行通信已经同步登录状态呢?
登录服务器,可以看作是我们其他大区服务器的网关服务器。那么势必为了保证服务器的高可用性,已经内存等资源消耗。我们这里的数据交换肯定不能依赖于socket连接进行。这样消耗会很大,这里其实只需要查看服务器状态和登陆即可。那么我们需要http就能顺利完成的工作。无需长连接,就无需考虑连接状态。
那么这种情况,http虽然能减少消耗,返回服务器状态。但是也要保证玩家的登陆状态,还要与其他服务器保持同步状态。那么基于IIS或者tomcat肯定是无法完成了。
这里就有了自定义开发的基于Socket 的服务器程序来今天http协议监听。具体的文章之前有过介绍(详见)。
今天我们就来真正完成http登陆模块。
1 Sz.Network.SocketPool.ListenersBox.GetInstance.SetParams(new MessagePool(), typeof(MarshalEndian)); 2 Sz.Network.SocketPool.ListenersBox.GetInstance.Start("tcp:*:9527", "http://*:8001/login/");
依旧是上一篇文章的代码,进行http的绑定的 login 进行监听。
在 MessagePool 类的 函数
1 public void ActiveHttp(HttpClient client, string bind, Dictionary<string, string> parms) 2 { 3 if (bind.Equals("/login/")) 4 { 5 string strHtml = "ret="; 6 strHtml += "Login OK!"; 7 client.OutputStream.WriteLine(strHtml); 8 client.Close(); 9 } 10 }
这样我们可以判断出,请求 bind 是来至于 login的绑定,后面的 parms 是此处请求的参数信息,不管是post还是get请求方式。这里如果需要了解参数的获取方式请详见以前的文章 《C# 利用socekt做到http监听,怎么样才能做到高性能》
那么我们开启服务器先测试一下,
可以看到,我们监听login是成功的,
我们可以开始登陆操作了,登陆我们要解决的就是一个http的连接如何保持登陆状态。
这里的灵感来至于腾讯,百度等api接口的思路创建的登陆验证方式。
为了方便进行,我们需要从nuget处获取一个第三方类库 json.net 进行数据的json格式输出。
修改一下 ActiveHttp
1 string strHtml = "ret="; 2 if (bind.Equals("/login/")) 3 { 4 foreach (var item in parms) 5 { 6 Console.WriteLine("参数:"+item.Key + ":" + item.Value); 7 8 } 9 strHtml += "Login OK!"; 10 } 11 client.OutputStream.WriteLine(strHtml); 12 client.Close();
在浏览器输入 http://127.0.0.1:8001/login/?username=test1&pwd=test1&logintime=2015-4-16%2012:00
请不要在意密码是不是明文传输的。
1 [2015-04-16 12:10:38:287:Info ] Create Http Socket Remote Socket LocalEndPoint:127.0.0.1:8001 RemoteEndPoint:127.0.0.1:4332 2 参数:username:test1 3 参数:pwd:test1 4 参数:logintime:2015-4-16 12:00
正常接收到get传来的登陆数据。
我们想创建一个密钥 key值
string key = "89bf54aca24a457ea32a6a0d81cbcc4e";
在创建一个回复类
1 class LoginRet 2 { 3 public string Ret { get; set; } 4 5 public string PWDKey { get; set; } 6 }
1 public void ActiveHttp(HttpClient client, string bind, Dictionary<string, string> parms) 2 { 3 LoginRet loginRet = new LoginRet(); 4 if (bind.Equals("/login/")) 5 { 6 if (parms["username"] == "test1" && parms["pwd"] == "test1") 7 { 8 loginRet.Ret = "Login OK!"; 9 string pwdkey = parms["username"] + parms["pwd"] + key + parms["logintime"]; 10 byte[] pwdkeyBuffer = UTF8Encoding.Default.GetBytes(pwdkey); 11 loginRet.PWDKey = Convert.ToBase64String(pwdkeyBuffer); 12 Logger.Info("用户 " + parms["username"] + " 登陆完成 密钥:" + loginRet.PWDKey); 13 } 14 else { loginRet.Ret = "Login Error!"; } 15 } 16 else 17 { 18 loginRet.Ret = "Login Error!"; 19 } 20 string jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(loginRet); 21 client.OutputStream.WriteLine(jsonStr); 22 client.Close(); 23 }
修改一下处理方法,这里我采用的加密方式,仅仅是最简单的,就是把 登陆名 + 登陆密码 + 密钥 + 登录时间 转换成64为字符串,(这里各位同学可以根据自己项目的实际情况和需求改为md5也好,自己写算法也好,都可以)
这样就得到了登陆成功后的凭证,拿着这个凭证可以在我们任何服务器相同规则下进行无需第二次验证登陆。
在浏览器输入 http://127.0.0.1:8001/login/?username=test1&pwd=test1&logintime=2015-4-16%2012:00再一次使用这个 url 测试
接下来我们抛弃浏览器,用客户端程序来试试,
WebRequest request = WebRequest.Create("http://127.0.0.1:8001/login/?username=test1&pwd=test1&logintime=2015-4-16%2012:00"); request.Method = "GET"; string str = new System.IO.StreamReader(request.GetResponse().GetResponseStream(), UTF8Encoding.Default).ReadToEnd(); Ret = Newtonsoft.Json.JsonConvert.DeserializeObject<LoginRet>(str); if (Ret != null && Ret.Ret) { ConnectManager.GetInstance.AddMsg("登陆成功" + Ret.PWDKey); }
修改一下访问模式
客户端登陆代码更改为
1 BufferWriter bw = new BufferWriter(1); 2 bw.Write(ConnectManager.GetInstance.Ret.PWDKey);//发送登陆凭据 3 bw.Write("test1");//发送用户名 4 bw.Write("2015-4-16 12:00");//发送时间 5 bw.Write(this.username.Text.TrimEnd()); 6 ConnectManager.GetInstance.Client.SendMsg(bw.GetMessage()); 7 bw.Dispose();
服务器socket 登陆验证。
1 string pwdkey = this.bufferReader.ReadString(); 2 string username = this.bufferReader.ReadString(); 3 string loginTime = this.bufferReader.ReadString(); 4 string name = this.bufferReader.ReadString(); 5 6 if (pwdkey == Convert.ToBase64String(UTF8Encoding.Default.GetBytes(username + ServerManager.key + loginTime))) 7 { 8 if (!LoginManager.GetInstance.LoginNames.Contains(username)) 9 { 10 LoginManager.GetInstance.LoginNames.Add(username); 11 if (!LoginManager.GetInstance.LoginIPs.ContainsKey(Session.ID)) 12 { 13 LoginManager.GetInstance.LoginIPs[Session.ID] = username; 14 LoginManager.GetInstance.Sessions.Add(Session); 15 } 16 srWriter.Write(true); 17 srWriter.Write(name + " 登陆聊天室"); 18 Logger.Info(Session.RemoteEndPoint + " " + name + " 登陆成功"); 19 ServerManager.GetInstance.Tell_All(srWriter.GetMessage()); 20 } 21 else 22 { 23 srWriter.Write(false); 24 srWriter.Write("登录名称重复,请换一个"); 25 Logger.Info(Session.RemoteEndPoint + " " + name + " 登录名称重复!"); 26 Session.SendMsg(srWriter.GetMessage()); 27 } 28 }
此时我们在socket登陆验证只需要验证传入的参数,pwdkey能否生成相同的。则为登陆成功。
完成了正常的游戏登陆流程,莫倩,页游,手游,都是第三方运营平台,登陆账号和密码,都是第三方的。如果需要http登陆,密钥key到游戏内部验证。
一步一步开发Game服务器(二)登陆2相关推荐
- 一步一步开发Game服务器(二)完成登陆,聊天
我知道这样的文章在博客园已经多的大家都不想看了,但是这是我的系列文章开始,请各位大神见谅了. 多线程,线程执行器,(详见),socket通信相关 (详见) 本人blog相关文章测试代码,示例,完整版s ...
- 路由器二次开发一步一步把工业路由器变成一个高端的可指定出网、节点和链路的路由器,包含详细过程及快捷脚本(五)
路由器二次开发一步一步把工业路由器变成一个高端的可指定出网.节点和链路的路由器,包含详细过程及快捷脚本(五). 如果没有 路由器 可以采用 废旧的电脑,详细环境部署参考第(一)篇文章,这里采用800米 ...
- 路由器二次开发一步一步把工业路由器变成一个高端的可指定出网、节点和链路的路由器,包含详细过程及快捷脚本(四)
路由器二次开发一步一步把工业路由器变成一个高端的可指定出网.节点和链路的路由器,包含详细过程及快捷脚本(四). 如果没有 路由器 可以采用 废旧的电脑,详细环境部署参考第(一)篇文章,这里采用800米 ...
- 路由器二次开发一步一步把工业路由器变成一个高端的可指定出网、节点和链路的路由器,包含详细过程及快捷脚本(二)
路由器二次开发一步一步把工业路由器变成一个高端的可指定出网.节点和链路的路由器,包含详细过程及快捷脚本(二). 如果没有路由器可以采用废旧的电脑,详细环境部署参考第(一)篇文章,这里采用800米的工业 ...
- 群辉服务器更新系统教程,男人的生产力工具 篇二百四十六:新手玩转群晖NAS:一步一步教你更新群晖DSM系统...
男人的生产力工具 篇二百四十六:新手玩转群晖NAS:一步一步教你更新群晖DSM系统 2020-08-05 10:46:03 18点赞 175收藏 59评论 新手与新知男人的生产力工具 篇二百三十九:新 ...
- 一步一步在阿里云上架一个应用系统(云服务器ECS和轻量应用服务器选型)1
一步一步在阿里云上架一个应用系统(云服务器ECS和轻量应用服务器选型) - 1 一步一步在阿里云上架一个应用系统(云服务器ECS选购配置) - 2 文章目录 前言 步骤 云服务器 所有组件 云服务器 ...
- 高级性能服务器编程模型【IOCP完成端口】开发实现【二】
因为需要参考各种资料,所以还是需要一些时间才能够做好的. 而且在开发中,还会面对一些不得不仔细去解决的问题. 我打算尽量从Win32API的基础上面进行开发,能够不使用Delphi封装的类就不用,任何 ...
- Java程序员从笨鸟到菜鸟之(一百零八)一步一步学习webservice(二)webservice基本原理
本来这第二篇打算讲解"开发第一个基于XFire的webservice"的内容来着.但是想想.开发实例只是局限于了会用的层面上.如果想真正的理解webservice还是需要挖掘其原理 ...
- 一步一步学Spring Boot(二)课程发布了~~~
课程名称 <一步一步学Spring Boot(二)> 学习地址 CSDN学习地址: http://edu.csdn.net/lecturer/994 51CTO学习地址:http://ed ...
最新文章
- 解析1G到5G技术与设备发展历程
- Mysql的事务事务的特征事务的隔离级别
- 单元测试,只是测试吗?
- 笔试:当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? ?(2nd)...
- Bootstrap4代码模板
- 微信开放平台Android应用的签名
- 我对这个页面做了什么?
- Leetcode每日一题:1030.matrix-cells-in-distance-order(距离顺序排列矩阵单元格)
- python用链接表实现栈_python 用链表实现栈(计算器1)
- C++类头文件交叉引用出现error C2143: 语法错误: 缺少“
- JS中的this是什么,this的四种用法
- 姿态估计(人体关键点检测)之CPN
- HIT-哈工大数据结构-作业3(C++)
- 冒泡排序的概念和代码范例 Python
- html如何提取图片颜色代码,PS怎么提取颜色做色卡?
- 多目标学习在推荐系统中的应用
- 年薪超过 50 万的程序员在哪些公司工作?
- 绿色数据中心:避免能耗还是提高能效
- 当我们在聊VR时,究竟是在聊什么?
- 哈理工OJ-1584-青蛙过河【贪心+二分】