抽样:

void GameRequest::initRequset(const char* url, cocos2d::CCObject* pTarget, cocos2d::SEL_CallFuncND pSelector)

{

cocos2d::extension::CCHttpRequest* request = new cocos2d::extension::CCHttpRequest();

request->setUrl(url);

//设置为GET请求:kHttpGet

request->setRequestType(cocos2d::extension::CCHttpRequest::kHttpGet);

//设置处理响应回调函数

if(pTarget != NULL && pSelector != NULL){

request->setResponseCallback(pTarget, pSelector);

}

cocos2d::extension::CCHttpClient::getInstance()->setTimeoutForConnect(15);

cocos2d::extension::CCHttpClient::getInstance()->setTimeoutForRead(15);

cocos2d::extension::CCHttpClient::getInstance()->send(request);

int countme = request->retainCount();

if(countme <= 0)

{

CCLOG("=request retaincount==================%d",request->retainCount());

}

request->release();

}

void CoverScene::checkUserNameRequestCallBack(cocos2d::CCNode *sender, void *data)

{

cocos2d::extension::CCHttpResponse *response = (cocos2d::extension::CCHttpResponse*)data;

if (!response)

{

return;

}

//你能够使用: response->request->reqType获取请求类型

if (0 != strlen(response->getHttpRequest()->getTag()))

{

CCLog("%s completed", response->getHttpRequest()->getTag());

}

//获取状态码

int statusCode = response->getResponseCode();

char statusString[64] = {};

sprintf(statusString, "HTTP Status Code: %d, tag = %s", statusCode, response->getHttpRequest()->getTag());

CCLog("response code: %d", statusCode);

if (!response->isSucceed())

{

//訪问失败获取错误信息

CCLog("response failed");

CCLog("error buffer: %s", response->getErrorBuffer());

return;

}

try {

vector::data

指针到 vector
 的第一个元素成功或为空 vector的位置。

std::vector<char> *buffer = response->getResponseData();

std::string str = std::string(buffer->data(), buffer->size());

Json *dataJson = Json_create(str.data());

std::cout<<Json_getSize(dataJson)<<std::endl;

MessageBoxLayer::getMessageBoxPoint()->callMessageBoxRemove();

if (Json_getSize(dataJson) == 1)

{

//账号password错误

CCLOG("账号password错误.........");

changeToLogin();

}

else

{

Json *infoDataJson = Json_getItem(dataJson, "data");

m_accessToken = Json_getItem(infoDataJson,"token")->valuestring;

GameUser::GetGameUser()->uninqueId = atoll(Json_getItemAt(Json_getItemAt(dataJson, 1),0)->valuestring);

GameUser::GetGameUser()->platform_user_id = Json_getString(infoDataJson, "platform_user_id", "");//Json_String(infoDataJson, "platform_user_id");

CoverScene::m_iType = 0;

getServerListRequest();

}

}

catch (const std::exception& rhs)

{

CCLOG("数据异常");

}

}

#ifndef __CCHTTPREQUEST_H__

#define __CCHTTPREQUEST_H__

#include "cocos2d.h"

#include "ExtensionMacros.h"

#include "HttpRequest.h"

#include "HttpResponse.h"

NS_CC_EXT_BEGIN

/**

* @addtogroup Network

* @{

*/

/** @brief Singleton that handles(操控) asynchronous(asyn 异步 chromous
同步) http requests

* Once the request completed, a callback will issued(公布) in main thread when it provided during make request

*/

class CCHttpClient : public CCObject

{

public:

/** Return the shared instance **/

static CCHttpClient *getInstance();// CCHttpClient
是一个单例类

/** Relase the shared instance **/

static voiddestroyInstance();

{

CCAssert(s_pHttpClient, "");

CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CCHttpClient::dispatchResponseCallbacks), s_pHttpClient);

s_pHttpClient->release();

}

/**

* Add a get request to task queue

* @param request a CCHttpRequest object, which includes url, response callback etc.

please make sure request->_requestData is clear before calling "send" here.

* @return NULL

*/

voidsend(CCHttpRequest* request);//这个用的最多 将CCHttpRequest 增加请求列表

/**

* Change the connect timeout

* @param timeout

* @return NULL

*/

inline voidsetTimeoutForConnect(int value) {_timeoutForConnect = value;};//设置连接超时
时间值

/**

* Get connect timeout

* @return int

*

*/

inline int getTimeoutForConnect() {return _timeoutForConnect;}//获得连接时间

/**

* Change the download timeout

* @param value

* @return NULL

*/

inline voidsetTimeoutForRead(int value) {_timeoutForRead = value;};

/**

* Get download timeout

* @return int

*/

inline intgetTimeoutForRead() {return _timeoutForRead;};

private:

CCHttpClient();//单例类

: _timeoutForConnect(30)

, _timeoutForRead(60)

{

CCDirector::sharedDirector()->getScheduler()->scheduleSelector(

schedule_selector(CCHttpClient::dispatchResponseCallbacks), this, 0, false);

CCDirector::sharedDirector()->getScheduler()->pauseTarget(this);

}

virtual ~CCHttpClient();

//当类是在栈上 类在离开作用域时会调用析构函数释放空间,此时无法调用私有的析构函数

//假设在堆上分配空间,仅仅有在delete时才会调用析构函数。

////////////////////////析构函数私有

当我们规定类仅仅能在堆上分配内存时,就能够将析构函数声明为私有的。

class alloc

{

public:

alloc():

private:

~alloc();

};

假设在栈上分配空间。类在离开作用域时会调用析构函数释放空间,此时无法调用私有的析构函数。

假设在堆上分配空间。仅仅有在delete时才会调用析构函数。

能够加入一个destroy()函数来释放,从而解决不能在析构函数中加入delete的问题。

class alloc

{

public:

alloc():

 destroy(){ delete this;}  

private:

~alloc();

};

/////////////////////////////////////////////////////

bool init(void);

/**

* Init pthread mutex, semaphore, and create new thread for http requests

* @return bool

*/

boollazyInitThreadSemphore(); // 私有函数 无需深究
  用到了很多额外函数 cpp里写的

{

if (s_requestQueue != NULL) {

return true;

} else {

s_requestQueue = new CCArray();

s_requestQueue->init();

s_responseQueue = new CCArray();

s_responseQueue->init();

pthread_mutex_init(&s_requestQueueMutex, NULL);

pthread_mutex_init(&s_responseQueueMutex, NULL);

pthread_mutex_init(&s_SleepMutex, NULL);

pthread_cond_init(&s_SleepCondition, NULL);

pthread_create(&s_networkThread, NULL, networkThread, NULL);

pthread_detach(s_networkThread);

need_quit = false;

}

return true;

}

//Poll function called from main thread to dispatch callbacks when http requests finished

// Poll and notify main thread if responses exists in queue

voiddispatchResponseCallbacks(float delta);  //
分发网络回应  私有函数 无需深究

private:

int _timeoutForConnect;

int _timeoutForRead;

// std::string reqId;

};

// end of Network group

/// @}

NS_CC_EXT_END

#endif //__CCHTTPREQUEST_H__



.cpp

作用域 生存期 static extern..........


以下的 static修饰的函数 生存期全局 作用域内部 外部无法通过extern使用


#include "HttpClient.h"

// #include "platform/CCThread.h"

#include <queue>

#include <pthread.h>

#include <errno.h>

#include "curl/curl.h"

NS_CC_EXT_BEGIN

static pthread_t        s_networkThread;

static pthread_mutex_t  s_requestQueueMutex;

static pthread_mutex_t  s_responseQueueMutex;

static pthread_mutex_ts_SleepMutex;

static pthread_cond_ts_SleepCondition;

static unsigned long    s_asyncRequestCount = 0;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)

typedef int int32_t;

#endif

static bool need_quit = false;

static CCArray* s_requestQueue = NULL;

static CCArray* s_responseQueue = NULL;

static CCHttpClient *s_pHttpClient = NULL; // pointer to singleton

static char s_errorBuffer[CURL_ERROR_SIZE];

typedef size_t (*write_callback)(void *ptr, size_t size, size_t nmemb, void *stream);

// Callback function used by libcurl for collect response data

static size_t writeData(void *ptr, size_t size, size_t nmemb, void *stream)

{

std::vector<char> *recvBuffer = (std::vector<char>*)stream;

size_t sizes = size * nmemb;

// add data to the end of recvBuffer

// write data maybe called more than once in a single request

recvBuffer->insert(recvBuffer->end(), (char*)ptr, (char*)ptr+sizes);

return sizes;

}

// Callback function used by libcurl for collect header data

static size_t writeHeaderData(void *ptr, size_t size, size_t nmemb, void *stream)

{

std::vector<char> *recvBuffer = (std::vector<char>*)stream;

size_t sizes = size * nmemb;

// add data to the end of recvBuffer

// write data maybe called more than once in a single request

recvBuffer->insert(recvBuffer->end(), (char*)ptr, (char*)ptr+sizes);

return sizes;

}

static int processGetTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *errorCode, write_callback headerCallback, void *headerStream);

static int processPostTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *errorCode, write_callback headerCallback, void *headerStream);

static int processPutTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *errorCode, write_callback headerCallback, void *headerStream);

static int processDeleteTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *errorCode, write_callback headerCallback, void *headerStream);

// int processDownloadTask(HttpRequest *task, write_callback callback, void *stream, int32_t *errorCode);

// Worker thread

static void* networkThread(void *data)

{

CCHttpRequest *request = NULL;

while (true)

{

if (need_quit)

{

break;

}

// step 1: send http request if the requestQueue isn't empty

request = NULL;

pthread_mutex_lock(&s_requestQueueMutex); //Get request task from queue

if (0 != s_requestQueue->count())

{

request = dynamic_cast<CCHttpRequest*>(s_requestQueue->objectAtIndex(0));

s_requestQueue->removeObjectAtIndex(0);

// request's refcount = 1 here

}

pthread_mutex_unlock(&s_requestQueueMutex);

if (NULL == request)

{

// Wait for http request tasks from main thread

pthread_cond_wait(&s_SleepCondition, &s_SleepMutex);

continue;

}

// step 2: libcurl sync access

// Create a HttpResponse object, the default setting is http access failed

CCHttpResponse *response = new CCHttpResponse(request);

// request's refcount = 2 here, it's retained by HttpRespose constructor

request->release();

// ok, refcount = 1 now, only HttpResponse hold it.

int32_t responseCode = -1;

int retValue = 0;

// Process the request -> get response packet

switch (request->getRequestType())

{

case CCHttpRequest::kHttpGet: // HTTP GET

retValue = processGetTask(request,

writeData,

response->getResponseData(),

&responseCode,

writeHeaderData,

response->getResponseHeader());

break;

case CCHttpRequest::kHttpPost: // HTTP POST

retValue = processPostTask(request,

writeData,

response->getResponseData(),

&responseCode,

writeHeaderData,

response->getResponseHeader());

break;

case CCHttpRequest::kHttpPut:

retValue = processPutTask(request,

writeData,

response->getResponseData(),

&responseCode,

writeHeaderData,

response->getResponseHeader());

break;

case CCHttpRequest::kHttpDelete:

retValue = processDeleteTask(request,

writeData,

response->getResponseData(),

&responseCode,

writeHeaderData,

response->getResponseHeader());

break;

default:

CCAssert(true, "CCHttpClient: unkown request type, only GET and POSt are supported");

break;

}

// write data to HttpResponse

response->setResponseCode(responseCode);

if (retValue != 0)

{

response->setSucceed(false);

response->setErrorBuffer(s_errorBuffer);

}

else

{

response->setSucceed(true);

}

// add response packet into queue

pthread_mutex_lock(&s_responseQueueMutex);

s_responseQueue->addObject(response);

pthread_mutex_unlock(&s_responseQueueMutex);

// resume dispatcher selector

CCDirector::sharedDirector()->getScheduler()->resumeTarget(CCHttpClient::getInstance());

}

// cleanup: if worker thread received quit signal, clean up un-completed request queue

pthread_mutex_lock(&s_requestQueueMutex);

s_requestQueue->removeAllObjects();

pthread_mutex_unlock(&s_requestQueueMutex);

s_asyncRequestCount -= s_requestQueue->count();

if (s_requestQueue != NULL) {

pthread_mutex_destroy(&s_requestQueueMutex);

pthread_mutex_destroy(&s_responseQueueMutex);

pthread_mutex_destroy(&s_SleepMutex);

pthread_cond_destroy(&s_SleepCondition);

s_requestQueue->release();

s_requestQueue = NULL;

s_responseQueue->release();

s_responseQueue = NULL;

}

pthread_exit(NULL);

return 0;

}

//Configure curl's timeout property

static bool configureCURL(CURL *handle)

{

if (!handle) {

return false;

}

int32_t code;

code = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, s_errorBuffer);

if (code != CURLE_OK) {

return false;

}

code = curl_easy_setopt(handle, CURLOPT_TIMEOUT, CCHttpClient::getInstance()->getTimeoutForRead());

if (code != CURLE_OK) {

return false;

}

code = curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, CCHttpClient::getInstance()->getTimeoutForConnect());

if (code != CURLE_OK) {

return false;

}

curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L);

curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L);

return true;

}

class CURLRaii

{

/// Instance of CURL

CURL *m_curl;

/// Keeps custom header data

curl_slist *m_headers;

public:

CURLRaii()

: m_curl(curl_easy_init())

, m_headers(NULL)

{

}

~CURLRaii()

{

if (m_curl)

curl_easy_cleanup(m_curl);

/* free the linked list for header data */

if (m_headers)

curl_slist_free_all(m_headers);

}

template <class T>

bool setOption(CURLoption option, T data)

{

return CURLE_OK == curl_easy_setopt(m_curl, option, data);

}

/**

* @brief Inits CURL instance for common usage

* @param request Null not allowed

* @param callback Response write callback

* @param stream Response write stream

*/

bool init(CCHttpRequest *request, write_callback callback, void *stream, write_callback headerCallback, void *headerStream)

{

if (!m_curl)

return false;

if (!configureCURL(m_curl))

return false;

/* get custom header data (if set) */

std::vector<std::string> headers=request->getHeaders();

if(!headers.empty())

{

/* append custom headers one by one */

for (std::vector<std::string>::iterator it = headers.begin(); it != headers.end(); ++it)

m_headers = curl_slist_append(m_headers,it->c_str());

/* set custom headers for curl */

if (!setOption(CURLOPT_HTTPHEADER, m_headers))

return false;

}

return setOption(CURLOPT_URL, request->getUrl())

&& setOption(CURLOPT_WRITEFUNCTION, callback)

&& setOption(CURLOPT_WRITEDATA, stream)

&& setOption(CURLOPT_HEADERFUNCTION, headerCallback)

&& setOption(CURLOPT_HEADERDATA, headerStream);

}

/// @param responseCode Null not allowed

bool perform(int *responseCode)

{

if (CURLE_OK != curl_easy_perform(m_curl))

return false;

CURLcode code = curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, responseCode);

if (code != CURLE_OK || *responseCode != 200)

return false;

// Get some mor data.

return true;

}

};

//Process Get Request

static int processGetTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *responseCode, write_callback headerCallback, void *headerStream)

{

CURLRaii curl;

bool ok = curl.init(request, callback, stream, headerCallback, headerStream)

&& curl.setOption(CURLOPT_FOLLOWLOCATION, true)

&& curl.perform(responseCode);

return ok ?

0 : 1;

}

//Process POST Request

static int processPostTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *responseCode, write_callback headerCallback, void *headerStream)

{

CURLRaii curl;

bool ok = curl.init(request, callback, stream, headerCallback, headerStream)

&& curl.setOption(CURLOPT_POST, 1)

&& curl.setOption(CURLOPT_POSTFIELDS, request->getRequestData())

&& curl.setOption(CURLOPT_POSTFIELDSIZE, request->getRequestDataSize())

&& curl.perform(responseCode);

return ok ? 0 : 1;

}

//Process PUT Request

static int processPutTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *responseCode, write_callback headerCallback, void *headerStream)

{

CURLRaii curl;

bool ok = curl.init(request, callback, stream, headerCallback, headerStream)

&& curl.setOption(CURLOPT_CUSTOMREQUEST, "PUT")

&& curl.setOption(CURLOPT_POSTFIELDS, request->getRequestData())

&& curl.setOption(CURLOPT_POSTFIELDSIZE, request->getRequestDataSize())

&& curl.perform(responseCode);

return ok ?

0 : 1;

}

//Process DELETE Request

static int processDeleteTask(CCHttpRequest *request, write_callback callback, void *stream, int32_t *responseCode, write_callback headerCallback, void *headerStream)

{

CURLRaii curl;

bool ok = curl.init(request, callback, stream, headerCallback, headerStream)

&& curl.setOption(CURLOPT_CUSTOMREQUEST, "DELETE")

&& curl.setOption(CURLOPT_FOLLOWLOCATION, true)

&& curl.perform(responseCode);

return ok ? 0 : 1;

}

// HttpClient implementation

CCHttpClient* CCHttpClient::getInstance()

{

if (s_pHttpClient == NULL) {

s_pHttpClient = new CCHttpClient();

}

return s_pHttpClient;

}


void CCHttpClient::destroyInstance()

{

CCAssert(s_pHttpClient, "");

CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CCHttpClient::dispatchResponseCallbacks), s_pHttpClient);

s_pHttpClient->release();

}

CCHttpClient::CCHttpClient()

: _timeoutForConnect(30)

, _timeoutForRead(60)

{

CCDirector::sharedDirector()->getScheduler()->scheduleSelector(

schedule_selector(CCHttpClient::dispatchResponseCallbacks), this, 0, false);

CCDirector::sharedDirector()->getScheduler()->pauseTarget(this);

}

CCHttpClient::~CCHttpClient()

{

need_quit = true;

if (s_requestQueue != NULL) {

pthread_cond_signal(&s_SleepCondition);

}

s_pHttpClient = NULL;

}

//Lazy create semaphore & mutex & thread

bool CCHttpClient::lazyInitThreadSemphore()

{

if (s_requestQueue != NULL) {

return true;

} else {

s_requestQueue = new CCArray();

s_requestQueue->init();

s_responseQueue = new CCArray();

s_responseQueue->init();

pthread_mutex_init(&s_requestQueueMutex, NULL);

pthread_mutex_init(&s_responseQueueMutex, NULL);

pthread_mutex_init(&s_SleepMutex, NULL);

pthread_cond_init(&s_SleepCondition, NULL);

pthread_create(&s_networkThread, NULL, networkThread, NULL);

pthread_detach(s_networkThread);

need_quit = false;

}

return true;

}

//Add a get task to queue

void CCHttpClient::send(CCHttpRequest* request)

{

if (false == lazyInitThreadSemphore())

{

return;

}

if (!request)

{

return;

}

++s_asyncRequestCount;

request->retain();

pthread_mutex_lock(&s_requestQueueMutex);

s_requestQueue->addObject(request);

pthread_mutex_unlock(&s_requestQueueMutex);

// Notify thread start to work

pthread_cond_signal(&s_SleepCondition);

}

// Poll and notify main thread if responses exists in queue

void CCHttpClient::dispatchResponseCallbacks(float delta)

{

// CCLog("CCHttpClient::dispatchResponseCallbacks is running");

CCHttpResponse* response = NULL;

pthread_mutex_lock(&s_responseQueueMutex);

if (s_responseQueue->count())

{

response = dynamic_cast<CCHttpResponse*>(s_responseQueue->objectAtIndex(0));

s_responseQueue->removeObjectAtIndex(0);

}

pthread_mutex_unlock(&s_responseQueueMutex);

if (response)

{

--s_asyncRequestCount;

CCHttpRequest *request = response->getHttpRequest();

CCObject *pTarget = request->getTarget();

SEL_HttpResponse pSelector = request->getSelector();

if (pTarget && pSelector)

{

(pTarget->*pSelector)(this, response);

}

response->release();

}

if (0 == s_asyncRequestCount)

{

CCDirector::sharedDirector()->getScheduler()->pauseTarget(this);

}

}

NS_CC_EXT_END









版权声明:本文博主原创文章,博客,未经同意不得转载。

HttpClient(联网)的更多相关文章

  1. 论述Android通过HttpURLConnection与HttpClient联网代理网关设置

    Android联网主要使用HttpURLConneciton和HttpClient进行联网,在手机联网的时候,我们优先选择wifi网络,其次在选择移动网络,这里所述移动网络主要指cmwap. 大家都知 ...

  2. 转-Android联网 — HttpURLConnection和HttpClient选择哪个好?

    http://www.ituring.com.cn/article/199619?utm_source=tuicool 在Android开发中,访问网络我们是选择HttpURLConnection还是 ...

  3. android两种基本联网方式与一种第三方开源项目的使用

    安卓请求网络的三种方式 在请求网络的时候一般常用的提交方式是post或者get请求,post请求安全,传输大小无限制,但是代码量多些,get请求是浏览器有大小限制,用户提交的信息在浏览器的地址栏显示出 ...

  4. Logstash5.0.X离线安装插件报错,仍然提示无法联网

    本人最初将此解决方案发布在 ELK中文社区 http://elasticsearch.cn/question/1046 由于生产环境无法连接互联网,所有再一台联网机器上将所有插件做了 pack 拖到生 ...

  5. android之HttpClient

    Apache包是对android联网访问封装的很好的一个包,也是android访问网络最常用的类. 下面分别讲一下怎么用HttpClient实现get,post请求. 1.Get 请求 HttpGet ...

  6. android HTTPclient

    Apache包是对android联网访问封装的很好的一个包,也是android访问网络最常用的类. 下面分别讲一下怎么用HttpClient实现get,post请求. 1.Get 请求 1 2 3 4 ...

  7. 一步步教你为网站开发Android客户端---HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新ListView

    本文面向Android初级开发者,有一定的Java和Android知识即可. 文章覆盖知识点:HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新List ...

  8. 【Cocos2d-x】 HttpClient 网络通信(Http)的简单应用

    Cocos2dx 为我们封装了在cocos2dx中http的网络框架,其文件在cocos2dx引擎包的extensions\network文件下的 HttpClient.HttpRequest .Ht ...

  9. HTTPClient模块的HttpGet和HttpPost

    HttpClient常用HttpGet和HttpPost这两个类,分别对应Get方式和Post方式. 无论是使用HttpGet,还是使用HttpPost,都必须通过如下3步来访问HTTP资源. 1.创 ...

随机推荐

  1. Servlet的学习之Session(2)

    在上一篇中我们学习了Session对象默认在一个会话过程中,由服务器创建,能保存在这个会话过程中用户访问多个web资源时产生的需要保存的数据,并在访问服务器中其他web资源时可以将这些数据从Sessi ...

  2. 被忽视的TWaver功能(1)

    应客户需求写个Demo,Demo中包括一些经常使用的功能.包括解析JSON数据生成TWaver中的网元和连线.网元右下角带上不同标识的小图标,连线须要是二次曲线.弹出菜单和信息板.跟大家分享下.先上图 ...

  3. openCV中cvSnakeImage()函数代码分析

    /*M/////////////////////////////////////////////////////////////////////////////////////// // // IMP ...

  4. Android学习笔记(十三)——碎片(一)

    碎片 碎片可看作第二种形式的活动,能够创建碎片来包括视图. 碎片总是嵌入在活动中,一般有两种常见形式: 1.碎片A和碎片B分别处于不同的活动中,当选择碎片A中的某一项时,触发碎片B启动: 2.碎片A和 ...

  5. HDU 2152 Fruit (母函数)

    # include<stdio.h> # include <algorithm> # include <string.h> # include <iostre ...

  6. Net线程安全集合

    在看Supersocket源码的时候发现很多地方都用到了我们不是很常用的线程安全集合,这些都是由net优化后的线程安全集合因此 应该比我们常规lock来效率好一些 比如说: 1 CurrentStac ...

  7. D7升级时候发现许多System函数和网络函数只有Byte版本的,需要注意

    SetLength 对于字符串,是WideChar的长度GetMem 只针对ByteMove 只针对ByteFillChar 只针对ByteWriteFile(API) 只针对Byte SetSock ...

  8. mysql 查询优化案例

    mysql> explain SELECT c.`sn` clientSn,asm.`clientManagerSn`,pry.`productSn`,1 TYPE,pr.`capitalBal ...

  9. 王立平--android中的anim(动画)

    简单有用步骤: 1.新建anim目录. 2.在anim下新建xml文件, 3.在xml下编写自己须要动画. 简单样例: 给Imageview加入动画 public class MainActivity ...

  10. Webserver管理系列:5、利用MSConfig排查木马

    木马程序最喜欢去的地方有两个一个是服务里面,一个是启动里面.利用msconfig我们能够高速的找到可疑程序. 在命令行中输入msconfig回车 选择服务项: 这里面的服务有非常多我们非常难排查,我告 ...