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

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

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

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

登录服务器,可以看作是我们其他大区服务器的网关服务器。那么势必为了保证服务器的高可用性,已经内存等资源消耗。我们这里的数据交换肯定不能依赖于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. shared_ptr

    省去对象指针的显示delete typedef tr1::shared_ptr<int> IntPtr; IntPtr fun() { IntPtr p = new int(3); ret ...

  2. 在windows上如何安装python web引擎jinja2

    首先要把你的Python文件夹加到环境变量里头去.假设你的Python文件夹位于C:\Python34,那么你需要打开CMD并输入: SETX PATH "%path%;C:\Python3 ...

  3. 微软StockTrader应用程序

    这是一个采用 .NET Enterprise Application Server 技术的端到端示例应用程序.应用程序代码可以从 这里 下载. 代码中演示了WCF服务和移动开发,包括用Xamarin ...

  4. ABP理论学习之MVC控制器(新增)

    返回总目录 本篇目录 介绍 AbpController基类 本地化 异常处理 响应结果的包装 审计日志 授权 工作单元 其他 介绍 ABP通过Abp.Web.Mvc nuget包集成了ASP.NET ...

  5. 【完全开源】百度地图Web service API C#.NET版,带地图显示控件、导航控件、POI查找控件

    目录 概述 功能 如何使用 参考帮助 概述 源代码主要包含三个项目,BMap.NET.BMap.NET.WindowsForm以及BMap.NET.WinformDemo. BMap.NET 对百度地 ...

  6. UWP开发之控件:用WebView做聊天框

    目录 说明 WebView存在的价值 使用WebView的几个重要技巧 使用WebView做的聊天框 说明 大家都知道,无论是之前的Winform.WPF还是现在的IOS.Android开发中,都存在 ...

  7. Python读取二进制文件

    import os import sys import socket mypath = sys.argv[1] if not os.path.exists(mypath): print "T ...

  8. %~dp0是什么意思

    转载自 www.cnblogs.com/yxsylyh 转载内容如下: cd /D %~dp0的意思如下: 更改当前目录为批处理本身的目录 比如你有个批处理a.bat在D:\qq文件夹下 a.bat内 ...

  9. R in Action 读书笔记(5)

    MindMapper原文件

  10. org.artofsolving.jodconverter.office.OfficeException: failed to start and connect

    org.artofsolving.jodconverter.office.OfficeException: failed to start and connect docviewer 调用 openo ...