session概述

session机制

session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。 保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发回给服务器。一般这个cookie的名字都是类似于SEEESIONID,而。比如weblogic对于web应用程序生成的cookie,JSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是JSESSIONID。

session,简而言之就是在服务器上保存用户操作的历史信息。服务器使用session id来标识session,session id由服务器负责产生,保证随机性与唯一性,相当于一个随机密钥,避免在握手或传输中暴露用户真实密码。但该方式下,仍然需要将发送请求的客户端与session进行对应,所以可以借助cookie机制来获取客户端的标识(即session id),也可以通过GET方式将id提交给服务器。

  • session的原理图:

HttpClient session的使用

下面我们结合实例来学习session的一个简单使用场景。玩家登陆游戏,登陆成功,服务器返回sessionID标识此次会话。后面的领取每日登陆奖励请求中都加入此sessionID,服务器上保存用户操作的历史信息实现服务端管理客户端的功能。根据sessionID管理登陆的玩家的会话,并更新玩家领取奖励信息。

服务器接口设计

根据上面设计的使用场景,我们的服务器需要支持玩家登录和更新每日登录领取奖励。我们设计了如下的两个服务器接口:

登陆接口

  • URL

    http://host:port/devicelogin

  • Method

    POST

  • 参数

    {
    "DeviceID" : "device id of the phone"
    }
  • 返回值

    http response code 200,登陆成功,http头部set-cookie自动包含sessionID。

    {
    "IsLottery" : true,
    "NoLootCount" : 0
    }

参数1:今日是否已领取每日奖励 参数2:装备宝箱未出高级装备次数

客户端解析sessionID,并放入后续http请求中。

更新每日奖励接口

  • URL

    http://host:port/lotteryed

  • Method

    POST

  • 参数

    NULL

  • 返回值

    http response code 200(更新成功)

客户端实现

工程创建

打开终端,使用如下命令新建工程:

cocos new HelloWorld -p com.your_company.HelloWorld -l cpp

按照上面的操作,我们新建了一个Cocos2d-x v3.x的HelloWorld工程。

工程创建好后,让我们来完成httpClient的post请求玩家登陆,和每日登陆领取金币奖励的客户端网络处理。 在上一节如何使用httpClient中已经介绍了httpClient的用法。 下面我们直接进入正题,开始编写代码

首先,在HelloWorldScene.cpp文件中加入下面的实现。 引入头文件和命名空间

#include "network/HttpClient.h"
using namespace cocos2d::network;

login

登陆请求实现

根据服务器接口,新建http请求,添加请求参数。实现代码如下:

void HelloWorld::login()
{
HttpRequest* request = new HttpRequest();
request->setUrl("http://172.100.104.128:8001/devicelogin");//1
request->setRequestType(HttpRequest::Type::POST);
request->setResponseCallback(CC_CALLBACK_2(HelloWorld::onLoginHttpRequestCompleted,this)); // 添加post请求参数
const char* postData = "{\
\"DeviceID\" : \"device id of the phone\"\
}";
request->setRequestData(postData, strlen(postData));//2
request->setTag("login POST");//3
//cocos2d::network::HttpClient::getInstance()->enableCookies(NULL);
cocos2d::network::HttpClient::getInstance()->send(request);
request->release();
}
  1. 设置登陆请求url
  2. 添加请求参数
  3. 设置http请求的tag

登陆的请求回调处理

上面的登陆请求设置了onLoginHttpRequestCompleted方法作为响应函数。无论服务器返回怎样的状态onLoginHttpRequestCompleted都将被调用。在响应方法中我们加入了打印登陆返回信息的代码。实现如下:

void HelloWorld::onLoginHttpRequestCompleted(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response)
{
if (!response)
{
return;
} if (0 != strlen(response->getHttpRequest()->getTag()))
{
log("%s completed", response->getHttpRequest()->getTag());
} //打印 http header信息
std::vector<char> *header = response->getResponseHeader();
for (unsigned int i = 0; i < header->size(); i++)
{
printf("%c", (*header)[i]);
}
printf("\n"); //TODO 登陆成功,服务器会通过set-Cookie,返回sessionID,解析sessionID并保存,用于接下来的请求 int statusCode = response->getResponseCode();
log("response code: %d", statusCode);
if (!response->isSucceed())
{
log("response failed");
log("error buffer: %s", response->getErrorBuffer());
return;
} // 打印 response data
std::vector<char> *buffer = response->getResponseData();
for (unsigned int i = 0; i < buffer->size(); i++)
{
printf("%c", (*buffer)[i]);
}
printf("\n");
}

编译并运行程序。查看登陆请求的的打印信息。

登陆成功的打印信息如下:

HTTP/1.1 200 OK
Set-Cookie: GSessionID=MTQwNjI1Mjg3MnxEdi1CQkFFQ180SUFBUkFCRUFBQV8tWF9nZ0FIQm5OMGNtbHVad3dGQUFOMVNVUUdkV2x1ZERNeUJnSUFCUVp6ZEhKcGJtY01DZ0FJWkdWMmFXTmxTVVFHYzNSeWFXNW5EQmdBRm1SbGRtbGpaU0JwWkNCdlppQjBhR1VnY0dodmJtVUdjM1J5YVc1bkRBb0FDRzVwWTJ0T1lXMWxCbk4wY21sdVp3d0NBQUFHYzNSeWFXNW5EQWtBQjJGalkyOTFiblFHYzNSeWFXNW5EQUlBQUFaemRISnBibWNNQ3dBSmFYTk1iM1IwWlhKNUJHSnZiMndDQWdBQUJuTjBjbWx1Wnd3TkFBdHViMHh2YjNSRGIzVnVkQU5wYm5RRUFnQUFCbk4wY21sdVp3d0tBQWgxYzJWeVJHRjBZUVp6ZEhKcGJtY01BZ0FBfGH2499HK_RENNLNURPmZcbqXAhNonoWkv926tH3MJwC; Path=/; Expires=Fri, 25 Jul 2014 02:47:52 UTC; Max-Age=3600; HttpOnly
Date: Fri, 25 Jul 2014 01:47:52 GMT
Content-Length: 35
Content-Type: text/plain; charset=utf-8 cocos2d: response code: 200
Http Test, dump data: {"IsLottery":false,"NoLootCount":0}

通过打印信息,我们可以看到登陆请求,服务器返回的信息中,通过Set-Cookie返回了SessionID。

lotteryed

每日登陆奖励

将登陆成功返回的SessionID,加入到http请求的header中进行每日登陆奖励请求。 每日登陆奖励的网络请求的代码和登陆的请求代码很相似,区别在于他们拥有各自的url、网络请求完成的响应处理和不同的请求tag。

实现要点:

在http header中加入SessionID的Cookie,发起请求。

实现代码如下:

void HelloWorld::lottery()
{
HttpRequest* request = new HttpRequest();
request->setUrl("http://172.100.104.128:8001/lotteryed");//1
request->setRequestType(HttpRequest::Type::POST);
request->setResponseCallback(CC_CALLBACK_2(HelloWorld::onHttpRequestCompleted,this)); //setHeader
std::vector<std::string> headers;
headers.push_back("Cookie: GSessionID=MTQwNjI1NjIxMXxEdi1CQkFFQ180SUFBUkFCRUFBQWNfLUNBQU1HYzNSeWFXNW5EQW9BQ0dSbGRtbGpaVWxFQm5OMGNtbHVad3dZQUJaa1pYWnBZMlVnYVdRZ2IyWWdkR2hsSUhCb2IyNWxCbk4wY21sdVp3d0xBQWxwYzB4dmRIUmxjbmtFWW05dmJBSUNBQUVHYzNSeWFXNW5EQTBBQzI1dlRHOXZkRU52ZFc1MEEybHVkQVFDQUFBPXz_BEw8Oo-XGEbCambVDQt2o636QUT_qg2Aj1EZX97ekw==");
request->setHeaders(headers);//2 //cocos2d::network::HttpClient::getInstance()->enableCookies(NULL); request->setTag("lotteryed POST");//3 cocos2d::network::HttpClient::getInstance()->send(request);
request->release();
}
  1. 设置每日登陆奖励的请求url
  2. 将sessionID加入到http请求的头部
  3. 设置http请求的tag

领取每日登陆奖励的网络请求回调处理

在http请求完成的回调中,我们可以通过请求tag区分,当前回调对应哪个网络请求。当然也可以使用setResponseCallback方法设置对应的响应回调处理方法。

由于lottery的http请求回调没返回什么实际参数。奖励领取成功返回http response code 200。

void HelloWorld::onLotteryHttpRequestCompleted(cocos2d::network::HttpClient *sender, cocos2d::network::HttpResponse *response)
{
if (!response)
{
return;
} int statusCode = response->getResponseCode();
log("response code: %d", statusCode);
if (!response->isSucceed())
{
log("response failed");
log("error buffer: %s", response->getErrorBuffer());
return;
} //TODO领取奖励成功
}

编译并运行,输出如下信息:

cocos2d: response code: 200

response code: 200 表明使用sessionID进行的每日登陆奖励领取的网络请求成功了。

sessionID的其他实现方式:

在3.x的版本中,HttpClient::enableCookies方法支持http会话使用cookie。 由于sessionID的保存和传递是通过cookie实现的,所以我们可以很方便的使用HttpClient::enableCookies方法来实现http client session。

cocos2d::network::HttpClient::getInstance()->enableCookies(NULL);

小结

通过以上的玩家登陆游戏和领取每日登陆的网络请求,我们学习了httpclient session的使用。

(25)HttpClient session的更多相关文章

  1. Mina、Netty、Twisted一起学(六):session

    开发过Web应用的同学应该都会使用session.由于HTTP协议本身是无状态的,所以一个客户端多次访问这个web应用的多个页面,服务器无法判断多次访问的客户端是否是同一个客户端.有了session就 ...

  2. PAT-乙级-1040. 有几个PAT(25)

    1040. 有几个PAT(25) 时间限制 120 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CAO, Peng 字符串APPAPT中包含了两个单 ...

  3. Windows Phone开发(25):启动器与选择器之WebBrowserTask

    原文:Windows Phone开发(25):启动器与选择器之WebBrowserTask 从名字上就看出来,这个家伙就是打开浏览并浏览到指定页面. 它有两个用途完全一样的属性:Uri属性是Syste ...

  4. (25)uniGUI for C++ builder之UniHTMLMemo初使用及uniGUI如何调用javaScript

    (25)uniGUI for C++ builder之UniHTMLMemo初使用及uniGUI如何调用javaScript 2018年09月29日 22:58:20 中国银行之路在脚下 阅读数:11 ...

  5. pat02-线性结构3. 求前缀表达式的值(25)

    02-线性结构3. 求前缀表达式的值(25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 算术表达式有前缀表示法.中缀表示法和后缀表示法 ...

  6. PAT (Basic Level) Practise (中文)-1040. 有几个PAT(25)

    1040. 有几个PAT(25)     http://www.patest.cn/contests/pat-b-practise/1040 字符串APPAPT中包含了两个单词“PAT”,其中第一个P ...

  7. Qt 学习之路 2(25):画刷和画笔

    Home / Qt 学习之路 2 / Qt 学习之路 2(25):画刷和画笔 Qt 学习之路 2(25):画刷和画笔  豆子  2012年11月5日  Qt 学习之路 2  17条评论 前面一章我们提 ...

  8. pat06-图5. 旅游规划(25)

    06-图5. 旅游规划(25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该 ...

  9. Koa2学习(八)使用session

    Koa2学习(八)使用session koa2框架不提供session的处理方法,这里我们需要借助一个第三方中间件koa-session来处理session. 先安装插件: $ npm i koa-s ...

随机推荐

  1. ios开发之--NSString和NSArray互转

    将string字符串转换为array数组 NSArray  *array = [Str componentsSeparatedByString:@","];//分隔符逗号 将arr ...

  2. Host ‘host_name’ is blocked

    参考:http://web2.0coder.com/archives/163 之前服务器遇到了这个错误: Host ‘host_name‘ is blocked because of many con ...

  3. Nginx遇上Access Denied提示怎么解决

    这几天在摆弄linux下面的各种服务器,对nginx非常有兴趣. 于是把phpmyadmin传上去了,先是phpmyadmin配了半天,结果配好之后发现phpmyadmin一些logo.css.js文 ...

  4. JS控制元素可见(显示)与不可见(隐藏)

    方法一: document.getElementById("id").style.visibility="hidden"; document.getElemen ...

  5. 在Win64系统上动态加载无签名驱动:WIN64LUD

    1.WIN64LUD的全称是WIN64 Load Unsigned Driver,功能如其名,在WIN64系统上加载无签名的驱动. 2.支持Windows 7/8/8.1/2008R2/2012/20 ...

  6. 【python系列】python2.x和python3.x的区别

    刚接触python使用的是python2.x的书籍,但是发现python3.x和python2.x有不小的区别,以下做一些记录 性能 Py3.0运行 pystone benchmark的速度比Py2. ...

  7. nutch 1.7导入Eclipse

    1.下载Nutch1.7的包 apache-nutch-1.7-src.zip,解压之后应该包括 bin,conf,src等目录 2.将解压之后的 apache-nutch-1.7 文件夹放到ecli ...

  8. [SQL] 理解SQL SERVER中的逻辑读,预读和物理读

    SQL SERVER数据存储的形式 在谈到几种不同的读取方式之前,首先要理解SQL SERVER数据存储的方式.SQL SERVER存储的最小单位为页(Page).每一页大小为8k,SQL SERVE ...

  9. Unity3D笔记七 GUILayout

    一.说到GUILayout就要提到GUI,二者的区别是什么 GUILayout是游戏界面的布局.GUI(界面)和GUILayout(界面布局)功能上面是相似的从命名中就可以看到这两个东西非常相像,但是 ...

  10. csrf_token之全局认证与局部认证

    1.settings.py没有注释到csrf.当post请求的方式会报错. 接下来就解决问题! 1. django中间件 最多5个 - process_request 请求 - process_vie ...