上一篇文章,讲解了简单的登陆情况。接下来我们继续讲解登陆模块。

在正常的游戏服务器情况下。在尚未登录前可以查看服务器大区情况,登陆后也可以查看服务器大区情况,然后选择大区服务器。进行登录操作。

这样的情况就需要我们有一个登录服务器来负责,目前大区服务器的状态,是正常。拥挤,爆满。还是停服维护。那么这样登录服务器,如果进行控制和输出呢?

如何与大区服务器正常进行通信已经同步登录状态呢?

登录服务器,可以看作是我们其他大区服务器的网关服务器。那么势必为了保证服务器的高可用性,已经内存等资源消耗。我们这里的数据交换肯定不能依赖于socket连接进行。这样消耗会很大,这里其实只需要查看服务器状态和登陆即可。那么我们需要http就能顺利完成的工作。无需长连接,就无需考虑连接状态。

那么这种情况,http虽然能减少消耗,返回服务器状态。但是也要保证玩家的登陆状态,还要与其他服务器保持同步状态。那么基于IIS或者tomcat肯定是无法完成了。

这里就有了自定义开发的基于Socket 的服务器程序来今天http协议监听。具体的文章之前有过介绍(详见)。

今天我们就来真正完成http登陆模块。

  Sz.Network.SocketPool.ListenersBox.GetInstance.SetParams(new MessagePool(), typeof(MarshalEndian));
             Sz.Network.SocketPool.ListenersBox.GetInstance.Start("tcp:*:9527", "http://*:8001/login/");

依旧是上一篇文章的代码,进行http的绑定的 login 进行监听。

在 MessagePool 类的  函数

  public void ActiveHttp(HttpClient client, string bind, Dictionary<string, string> parms)
         {
             if (bind.Equals("/login/"))
             {
                 string strHtml = "ret=";
                 strHtml += "Login OK!";
                 client.OutputStream.WriteLine(strHtml);
                 client.Close();
             }
         }

这样我们可以判断出,请求 bind 是来至于 login的绑定,后面的 parms 是此处请求的参数信息,不管是post还是get请求方式。这里如果需要了解参数的获取方式请详见以前的文章《C# 利用socekt做到http监听,怎么样才能做到高性能》

那么我们开启服务器先测试一下,

可以看到,我们监听login是成功的,

我们可以开始登陆操作了,登陆我们要解决的就是一个http的连接如何保持登陆状态。

这里的灵感来至于腾讯,百度等api接口的思路创建的登陆验证方式。

为了方便进行,我们需要从nuget处获取一个第三方类库 json.net 进行数据的json格式输出。

修改一下 ActiveHttp

 string strHtml = "ret=";
             if (bind.Equals("/login/"))
             {
                 foreach (var item in parms)
                 {
                     Console.WriteLine("参数:"+item.Key + ":" + item.Value);

                 }
                 strHtml += "Login OK!";
             }
             client.OutputStream.WriteLine(strHtml);
             client.Close();

在浏览器输入 http://127.0.0.1:8001/login/?username=test1&pwd=test1&logintime=2015-4-16%2012:00

请不要在意密码是不是明文传输的。

 [-- ::::Info ] Create Http Socket Remote Socket LocalEndPoint: RemoteEndPoint:
 参数:username:test1
 参数:pwd:test1
 参数:logintime:-- :

正常接收到get传来的登陆数据。

我们想创建一个密钥 key值

string key = "89bf54aca24a457ea32a6a0d81cbcc4e";

在创建一个回复类

  class LoginRet
         {
             public string Ret { get; set; }

             public string PWDKey { get; set; }
         }
         public void ActiveHttp(HttpClient client, string bind, Dictionary<string, string> parms)
         {
             LoginRet loginRet = new LoginRet();
             if (bind.Equals("/login/"))
             {
                 if (parms["username"] == "test1" && parms["pwd"] == "test1")
                 {
                     loginRet.Ret = "Login OK!";
                     string pwdkey = parms["username"] + parms["pwd"] + key + parms["logintime"];
                     byte[] pwdkeyBuffer = UTF8Encoding.Default.GetBytes(pwdkey);
                     loginRet.PWDKey = Convert.ToBase64String(pwdkeyBuffer);
                     Logger.Info("用户 " + parms["username"] + " 登陆完成 密钥:" + loginRet.PWDKey);
                 }
                 else { loginRet.Ret = "Login Error!"; }
             }
             else
             {
                 loginRet.Ret = "Login Error!";
             }
             string jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(loginRet);
             client.OutputStream.WriteLine(jsonStr);
             client.Close();
         }

修改一下处理方法,这里我采用的加密方式,仅仅是最简单的,就是把 登陆名 + 登陆密码 + 密钥 + 登录时间 转换成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);
            }

修改一下访问模式

客户端登陆代码更改为

 BufferWriter bw = );
             bw.Write(ConnectManager.GetInstance.Ret.PWDKey);//发送登陆凭据
             bw.Write("test1");//发送用户名
             bw.Write("2015-4-16 12:00");//发送时间
             bw.Write(this.username.Text.TrimEnd());
             ConnectManager.GetInstance.Client.SendMsg(bw.GetMessage());
             bw.Dispose();

服务器socket 登陆验证。

 string pwdkey = this.bufferReader.ReadString();
                     string username = this.bufferReader.ReadString();
                     string loginTime = this.bufferReader.ReadString();
                     string name = this.bufferReader.ReadString();

                     if (pwdkey == Convert.ToBase64String(UTF8Encoding.Default.GetBytes(username + ServerManager.key + loginTime)))
                     {
                         if (!LoginManager.GetInstance.LoginNames.Contains(username))
                         {
                             LoginManager.GetInstance.LoginNames.Add(username);
                             if (!LoginManager.GetInstance.LoginIPs.ContainsKey(Session.ID))
                             {
                                 LoginManager.GetInstance.LoginIPs[Session.ID] = username;
                                 LoginManager.GetInstance.Sessions.Add(Session);
                             }
                             srWriter.Write(true);
                             srWriter.Write(name + " 登陆聊天室");
                             Logger.Info(Session.RemoteEndPoint + " " + name + " 登陆成功");
                             ServerManager.GetInstance.Tell_All(srWriter.GetMessage());
                         }
                         else
                         {
                             srWriter.Write(false);
                             srWriter.Write("登录名称重复,请换一个");
                             Logger.Info(Session.RemoteEndPoint + " " + name + " 登录名称重复!");
                             Session.SendMsg(srWriter.GetMessage());
                         }
                     }

此时我们在socket登陆验证只需要验证传入的参数,pwdkey能否生成相同的。则为登陆成功。

完成了正常的游戏登陆流程,莫倩,页游,手游,都是第三方运营平台,登陆账号和密码,都是第三方的。如果需要http登陆,密钥key到游戏内部验证。

一步一步开发Game服务器(二)登陆2的更多相关文章

  1. 一步一步开发Game服务器(三)加载脚本和服务器热更新(二)完整版

    上一篇文章我介绍了如果动态加载dll文件来更新程序 一步一步开发Game服务器(三)加载脚本和服务器热更新 可是在使用过程中,也许有很多会发现,动态加载dll其实不方便,应为需要预先编译代码为dll文 ...

  2. 一步一步开发Game服务器(二)完成登陆,聊天

    我知道这样的文章在博客园已经多的大家都不想看了,但是这是我的系列文章开始,请各位大神见谅了. 多线程,线程执行器,(详见),socket通信相关 (详见) 本人blog相关文章测试代码,示例,完整版s ...

  3. 一步一步开发Game服务器(四)地图线程

    时隔这么久 才再一次的回归正题继续讲解游戏服务器开发. 开始讲解前有一个问题需要修正.之前讲的线程和定时器线程的时候是分开的. 但是真正地图线程与之前的线程模型是有区别的. 为什么会有区别呢?一个地图 ...

  4. 一步一步跟我学DeviceOne开发 - 仿微信应用(一,二,三)

    这是一个系列的文档,长期目标是利用DeviceOne开发一些目前使用广泛的优质手机应用,我们会最大化的实现这些应用的每一个功能和细节,不只停留在简单的UI模仿和Demo阶段,而是一个基本可以使用的实际 ...

  5. 一步一步开发Game服务器(一)

    什么是服务器?对于很多人来说也许只是简单成为在服务器端运行的程序的确如此,服务器通常意义就是说在服务器端运行的程序而已.那么我们怎么理解和分析游戏服务器哪? 传统意义上来说,程序运行后,正常流程, 启 ...

  6. JAVA+PHP+阿里云组件纯手工实现POP、SMTP、IMAP开发邮件服务器(二)

    java开发邮件服务器的接收模块 用java建立socket服务端,监听端口25,实现SMTP协议.即可完成邮件服务器的接收模块. 这里要注意的是,SMTP协议其实可以分为两种.一种是你用手机.PC等 ...

  7. 跟我一步一步开发自己的Openfire插件

    http://www.blogjava.net/hoojo/archive/2013/03/07/396146.html 跟我一步一步开发自己的Openfire插件 这篇是简单插件开发,下篇聊天记录插 ...

  8. xmppmini 项目详解:一步一步从原理跟我学实用 xmpp 技术开发 2.登录的实现

    第二章登录的实现 金庸<倚天屠龙记> 张三丰缓缓摇头,说道:“少林派累积千年,方得达成这等绝技,决非一蹴而至,就算是绝顶聪明之人,也无法自创.”他顿了一顿,又道:“我当年在少林寺中住过,只 ...

  9. 一步一步实现HTTP服务器-开篇

    缘起 翻开清单,一条条计划一直列在那里,一天又一天,不知道什么时候写下了它,也知不道什么时候完成它,它一直在那静静的等待着. 静下心来,反思自己,才发现自己是多么的无知,多么的没有毅力.设定了无数目标 ...

随机推荐

  1. js 预处理用户上传图片

    前几个月闲得无聊写得一段代码,没想最近刚好用上了,在硬盘里翻了半天找回来,还没好好整理直接用上了手机用户拍照上传的图片一般都在1M 到4M 之间,如果只是用作头像尺寸就可以缩小很多,1M甚至几M的图转 ...

  2. IOAPIC重定位中断处理函数思路整理

    因为小可并非硬件编程出身,汇编基础又比较差...所以刚开始理解利用IOAPIC重定位技术的时候相当困难. 何为IOAPIC? 首先,必须认识到它是一个硬件,可编程的硬件.我理解的它在整个流程中的作用如 ...

  3. myeclipse中导入js报如下错误Syntax error on token "Invalid Regular Expression Options", no accurate correc

    今天在使用bootstrap的时候引入的js文件出现错误Syntax error on token "Invalid Regular Expression Options", no ...

  4. ASP.NET Identity 2新增双重认证、帐号锁定、防伪印章功能并修复了一些bug

    Microsoft最近发布了ASP.NET Identity 2,该版本支持双重认证.帐号锁定以及防伪印章功能,还增强了用户帐号和索引.此外新版本还包含一个改进的密码验证器并修复了一些bug. 借助于 ...

  5. Orchard 微软CMS项目介绍

    我之前的项目中使用了Orchard, 它依据依赖注入的思想而做的模块化让我深深为之着迷,这里开始宣传一下这个架构. 包含的概念非常之多,我现在也不甚了解.Orchard就是自己想控制它改变它的话需要非 ...

  6. MySQL KEY分区

    200 ? "200px" : this.width)!important;} --> 介绍 KEY分区和HASH分区相似,但是KEY分区支持除text和BLOB之外的所有数 ...

  7. ASP.NET MVC 5 - 控制器

    MVC代表: 模型-视图-控制器 .MVC是一个架构良好并且易于测试和易于维护的开发模式.基于MVC模式的应用程序包含: · Models: 表示该应用程序的数据并使用验证逻辑来强制实施业务规则的数据 ...

  8. Azure SQL Database (21) 将整张表都迁移到Azure Stretch Database里

    <Windows Azure Platform 系列文章目录>  Azure SQL Database (19) Stretch Database 概览      Azure SQL Da ...

  9. 如何创建一个RESTful WCF Service

    原创地址:http://www.cnblogs.com/jfzhu/p/4044813.html 转载请注明出处 (一)web.config文件 要创建REST WCF Service,endpoin ...

  10. ABP(现代ASP.NET样板开发框架)主题线下交流会(上海)开始报名了!

    点这里进入ABP系列文章总目录 ABP主题线下交流会(上海)开始报名了 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称.它是采用最佳实践和流行技术 ...