跳到主要内容
CNode

分享一个原创memcache客户端 原来可以插入code的 重新编辑了下

社区
Xxujun52011发布于 14 年前最后回复 14 年前
452280
var net = require('net');

exports.connect = function(port, host) {
	return new memcache(port, host);
}

function memcache(port, host) {
	this.conn = null;
	this.port = port || 11211;
	this.host = host || '';
	this.error = ['ERROR', 'NOT_FOUND', 'CLIENT_ERROR', 'SERVER_ERROR'];
	this.crlf = "
";
	this.queue = [];
	this.nextData = '';
	this.init();
}

memcache.prototype = {
	init : function(){
		this.buffer = new Buffer('');
		this.cmd = null;
		this.callback = null;
		this.receiveTimes = 0;
		this.headLength = 0;
		this.bodyLength = 0;
		if (this.nextData.length > 0) this.receive(new Buffer(this.nextData));
	},
	connect : function(callback){
		if (this.conn) return callback.call(this);
		var conn = net.connect(this.port, this.host),
			self = this;
		conn.on('connect', function(){
			self.conn = conn;
			callback.call(self);
		});
		conn.on('data', function(data){
			self.receive(data);
		});
		conn.on('error', function(e){
			console.log(e);
			setTimeout(function(){
				self.connect(callback);
			}, 10);
		});
	},
	fixKey : function(key) {
		return key.substr(0, 250).replace(/\s/g, '_');
	},
	query : function(data, callback, cmd) {
		var idx = data.indexOf(' '),
			cmd = cmd || (idx == -1 ? data : data.substr(0, idx)).toLowerCase();
		this.connect(function(){
			this.queue.push({
				cmd : cmd,
				callback : callback
			});
			this.conn.write(data + this.crlf);
		});
	},
	send : function(cmd, key, value, callback, lifetime, flags) {
		if (typeof(callback) != 'function') {
			lifetime = callback;
			callback = null;
		}
		try {
			val = JSON.stringify(value);
		} catch(e) {
			try {
				val = value.toString();
			} catch(e) {
				val = '';
			}
		}
		var flags = flags || 0,
			lifetime = lifetime || 0,
			buffer = new Buffer(val),
			bufferLength = buffer.length || 0,
			query = [cmd, this.fixKey(key), flags, lifetime, bufferLength];
		this.query(query.join(' ') + this.crlf + val, callback);
	},
	receive : function(data) {
		if (this.receiveTimes == 0) {
			var last = this.queue.shift();
			this.cmd = last.cmd;
			this.callback = last.callback;
		}
		this.buffer = Buffer.concat([this.buffer, data]);
		this.receiveTimes++;
		result = this[this.cmd+'Handler']();
		if (result === null || result === undefined) return;
		try {
			this.callback(result);
		} catch(e) {}
		this.init();
	},
	add : function(key, value, callback, lifetime, flags) {
		this.send('add', key, value, callback, lifetime, flags);
	},
	set : function(key, value, callback, lifetime, flags) {
		this.send('set', key, value, callback, lifetime, flags);
	},
	replace : function(key, value, callback, lifetime, flags) {
		this.send('replace', key, value, callback, lifetime, flags);
	},
	get : function(key, callback) {
		this.query('get '+this.fixKey(key), callback);
	},
	delete : function(key, callback) {
		this.query('delete '+this.fixKey(key), callback);
	},
	flush : function(callback) {
		this.query('flush_all', callback, 'flush');
	},
	stats : function(callback) {
		this.query('stats', callback);
	},
	version : function(callback) {
		this.query('version', callback);
	},
	close : function(){
		var self = this;
		if (this.queue.length == 0) {
			this.conn.end();
			this.conn.destroy();
			this.conn = null;
		} else {
			setTimeout(function(){
				self.close();
			}, 10);
		}
	},
	getLine : function(data, line){
		if (Buffer.isBuffer(data)) data = data.toString();
		var line = line ? parseInt(line) : 0,
			data = data.split("
");
		return data[line] ? data[line]+"
" : false;
	},
	storeHandler : function(){
		var line = this.getLine(this.buffer);
		this.nextData = this.buffer.slice(new Buffer(line).length);
		if (line.toLowerCase().trim() == 'stored') {
			return true;
		} else {
			return false;
		}
	},
	addHandler : function(){
		return this.storeHandler();
	},
	setHandler : function(){
		return this.storeHandler();
	},
	replaceHandler : function(){
		return this.storeHandler();
	},
	getHandler : function(){
		if (this.receiveTimes == 1) {
			//第一次开始接收数据
			var line = this.getLine(this.buffer),
				header = line.split(/\s+/g);
			//不存在此KEY
			if (header[0].toLowerCase() == 'end') return false;
			this.headLength = new Buffer(line).length;
			this.bodyLength = parseInt(header[3]);
		}
			//实际buffer长度
		var bufferLength = this.buffer.length,
			//buffer应有的长度
			dataLength = this.headLength + this.bodyLength + 'END'.length + 2 * this.crlf.length;
		if (bufferLength >= dataLength) {
			var body = this.buffer.slice(this.headLength, this.headLength + this.bodyLength).toString();
			this.nextData = this.buffer.slice(dataLength).toString();
			try {
				return JSON.parse(body);
			} catch(e) {
				return body;
			}
		}
		return null;
	},
	deleteHandler : function(){
		var line = this.getLine(this.buffer);
		this.nextData = this.buffer.slice(new Buffer(line).length);
		if (line.toLowerCase().trim() == 'deleted') {
			return true;
		} else {
			return false;
		}
	},
	flushHandler : function(){
		var line = this.getLine(this.buffer);
		this.nextData = this.buffer.slice(new Buffer(line).length);
		if (line.toLowerCase().trim() == 'ok') {
			return true;
		} else {
			return false;
		}
	},
	statsHandler : function(){
		var buffer = this.buffer.toString(),
			idx = buffer.indexOf('END');
		if (idx != -1) {
			lines = buffer.trim().split("
");
			var stats = {};
			for(var i=0; i<lines.length-1; i++) {
				var line = lines[i].trim().split(/\s+/g);
				stats[line[1]] = line[2];
			}
			this.nextData = new Buffer(buffer.substr(idx + 'END'.length + this.crlf.length));
			return stats;
		}
		return null;
	},
	versionHandler : function(){
		var line = this.getLine(this.buffer),
			header = line.split(/\s+/);
		this.nextData = this.buffer.slice(new Buffer(line).length);
		return header[1];
	}
}
查看回复

回复 (4)

X
xbl1949#414 年前

红哇哇一篇啊~

X
xujun52011#314 年前
引用 xieren58汗,这怎么看

囧...现在可以看了, 我以为不能插入code, 原来可以的

X
xieren58#214 年前

汗,这怎么看~~

X
xujun52011#114 年前

我擦编辑器处理错误了"result = thisthis.cmd+'Handler';"这里本来应该是result = this中括号this.cmd+'Handler'中括号();

参与回复

登录后即可参与回复。登录