v0.25.0版本使用了v1.9.0版本的zengl语言库,在配置文件中增加了backlog及timezone的配置,此外,在内建模块中增加了bltSetTimeZone的模块函数。

项目下载地址:

    zenglServer源代码的相关地址:https://github.com/zenglong/zenglServer  当前版本对应的tag标签为:v0.25.0

zenglServer v0.25.0:

    v0.25.0版本使用了v1.9.0版本的zengl语言库,在配置文件中增加了backlog及timezone的配置,此外,在内建模块中增加了bltSetTimeZone的模块函数。

使用v1.9.0版本的zengl语言库,test_self.zl和test_def.zl测试脚本:

    当前版本使用了v1.9.0版本的zengl语言库中:

[root@localhost zenglServer]# ./zenglServer -v
zenglServer version: v0.25.0
zengl language version: v1.9.0
[root@localhost zenglServer]# 

    1.9.0版本的zengl语言增加了self的特殊类名,可以在class类结构中使用self来表示当前所在类的类名。为了测试self特殊类名,当前版本在 my_webroot/v0_25_0/ 目录中增加了test_self.zl的测试脚本:

use builtin;

class Test
	act;
	arg;
	fun Do(act, arg, obj)
		self obj;
		obj.act = act;
		obj.arg = arg;
		if(act == 'play')
			self.play(arg);
		else
			self.other(arg);
		endif
		self.Print(obj);
	endfun

	fun play(game)
		print 'play: ' + game;
	endfun

	fun other(str)
		print 'other: ' + str;
	endfun

	fun Print(obj)
		self obj;
		print 'obj.act: ' + obj.act;
		print 'obj.arg: ' + obj.arg;
	endfun
endclass

Test test;
test = bltArray();
Test.Do('play', 'football', test);
Test.Do('hello', 'worlds', test);
Test.Print(test);

    上面脚本在Test类结构中,就使用了self来表示Test类名。之前的zengl版本需要使用Test.play这样的语法来调用类方法,1.9.0版本开始则可以使用self.play这样的语法来调用当前类中的方法。此外,之前版本只能使用Test obj;这样的语法来声明类变量,1.9.0版本开始可以使用self obj这样的语法用当前类来声明变量。

    上面的test_self.zl脚本在命令行中的执行结果如下:

[root@localhost zenglServer]# ./zenglServer -r /v0_25_0/test_self.zl
play: football
obj.act: play
obj.arg: football
other: worlds
obj.act: hello
obj.arg: worlds
obj.act: hello
obj.arg: worlds
[root@localhost zenglServer]# 

    此外,1.9.0版本的zengl语言库还增加了zenglApi_SetDefLookupHandle和zenglApi_SetDefLookupResult接口,zenglServer可以使用这些接口来设置预定义的宏值,当前版本在内建模块和openssl模块中就使用了这些接口来设置预定义的宏值,例如,在module_builtin.c的C源文件中,就定义了和内建模块相关的预定义宏值的查询函数:

/**
 * 內建模块的def宏值查询函数,该查询函数会根据查询名称返回对应的宏值
 * 例如:def TRUE ___BUILTIN_TRUE___; 这个语句,就会调用下面这个函数,并将___BUILTIN_TRUE___作为查询名称传递给该函数,
 * 函数在经过查询后,就会设置整数1作为TRUE的宏值,因此这个语句等效于 def TRUE 1;
 */
int module_builtin_def_lookup_handle(ZL_EXP_VOID * VM_ARG, ZL_EXP_CHAR * defValName)
{
	char tmpstr[20];
	int retval = 1;
	if(strcmp(defValName, "___BUILTIN_TRUE___") == 0) // 用于脚本中定义TRUE的宏值
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "1");
	}
	else if(strcmp(defValName, "___BUILTIN_FALSE___") == 0) // 用于脚本中定义FALSE的宏值
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "0");
	}
	else if(strcmp(defValName, "___BUILTIN_NULL___") == 0) // 用于脚本中定义NULL的宏值
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "0");
	}
	else if(strcmp(defValName, "___BUILTIN_WRITE_FILE_MODE_WRITE___") == 0) // 用于在脚本中定义bltWriteFile模块函数写入模式的宏值
	{
		snprintf(tmpstr, 20, "%d", WRITE_FILE_MODE_WRITE);
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, tmpstr);
	}
	else if(strcmp(defValName, "___BUILTIN_WRITE_FILE_MODE_APPEND___") == 0) // 用于在脚本中定义bltWriteFile模块函数追加模式的宏值
	{
		snprintf(tmpstr, 20, "%d", WRITE_FILE_MODE_APPEND);
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, tmpstr);
	}
	return !retval;
}

    在module_openssl.c的C源文件中定义了和openssl模块相关的预定义宏值的查询函数:

/**
 * openssl模块的def宏值查询函数,该查询函数会根据查询名称返回对应的宏值
 * 例如:def RSA_SIGN_SHA ___OPENSSL_NID_sha___; 这个语句,就会调用下面这个函数,并将___OPENSSL_NID_sha___作为查询名称传递给该函数,
 * 函数在经过查询后,就会设置整数0作为RSA_SIGN_SHA的宏值,因此这个语句等效于 def RSA_SIGN_SHA 0;
 */
int module_openssl_def_lookup_handle(ZL_EXP_VOID * VM_ARG, ZL_EXP_CHAR * defValName)
{
	int retval = 1;
	if(strcmp(defValName, "___OPENSSL_NID_sha___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "0");
	}
	else if(strcmp(defValName, "___OPENSSL_NID_sha1___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "1");
	}
	else if(strcmp(defValName, "___OPENSSL_NID_ripemd160___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "2");
	}
	else if(strcmp(defValName, "___OPENSSL_NID_md5___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "3");
	}
	else if(strcmp(defValName, "___OPENSSL_NID_md5_sha1___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "4");
	}
	else if(strcmp(defValName, "___OPENSSL_NID_sha256___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "5");
	}
	else if(strcmp(defValName, "___OPENSSL_NID_sha256WithRSAEncryption___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "6");
	}
	else if(strcmp(defValName, "___OPENSSL_NID_sha512___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "7");
	}
	else if(strcmp(defValName, "___OPENSSL_NID_sha512WithRSAEncryption___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "8");
	}
	else if(strcmp(defValName, "___OPENSSL_RSA_PKCS1_PADDING___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "0");
	}
	else if(strcmp(defValName, "___OPENSSL_RSA_PKCS1_OAEP_PADDING___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "1");
	}
	else if(strcmp(defValName, "___OPENSSL_RSA_SSLV23_PADDING___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "2");
	}
	else if(strcmp(defValName, "___OPENSSL_RSA_NO_PADDING___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "3");
	}
	else if(strcmp(defValName, "___OPENSSL_RSA_PUBLIC___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "1");
	}
	else if(strcmp(defValName, "___OPENSSL_RSA_PRIVATE___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "0");
	}
	else if(strcmp(defValName, "___OPENSSL_RSA_USE_EVP___") == 0)
	{
		retval = zenglApi_SetDefLookupResult(VM_ARG, ZL_EXP_FAT_INT, "1");
	}
	return !retval;
}

    使用预定义宏值的好处在于,当底层预定义宏值对应的具体的值发生改变时,不需要再调整脚本中的代码了。当前版本在 my_webroot/v0_25_0/ 目录中增加了test_def.zl的测试脚本:

use builtin;

def TRUE 	___BUILTIN_TRUE___;
def FALSE 	___BUILTIN_FALSE___;
def WRITE_MODE 	___BUILTIN_WRITE_FILE_MODE_WRITE___;
def APPEND_MODE ___BUILTIN_WRITE_FILE_MODE_APPEND___;
def NULL 	___BUILTIN_NULL___;

def RSA_SIGN_SHA 	___OPENSSL_NID_sha___;
def RSA_SIGN_SHA1 	___OPENSSL_NID_sha1___;
def RSA_SIGN_RIPE160 	___OPENSSL_NID_ripemd160___;
def RSA_SIGN_MD5 	___OPENSSL_NID_md5___;
def RSA_SIGN_MD5_SHA1 	___OPENSSL_NID_md5_sha1___;
def RSA_SIGN_SHA256 	___OPENSSL_NID_sha256___;
def RSA_SIGN_SHA256_WITH_RSA 	___OPENSSL_NID_sha256WithRSAEncryption___;
def RSA_SIGN_SHA512 	___OPENSSL_NID_sha512___;
def RSA_SIGN_SHA512_WITH_RSA 	___OPENSSL_NID_sha512WithRSAEncryption___;

def RSA_PAD_PKCS1 	___OPENSSL_RSA_PKCS1_PADDING___;
def RSA_PAD_OAEP 	___OPENSSL_RSA_PKCS1_OAEP_PADDING___;
def RSA_PAD_SSLV23 	___OPENSSL_RSA_SSLV23_PADDING___;
def RSA_PAD_NO 		___OPENSSL_RSA_NO_PADDING___;

def RSA_PUBLIC 		___OPENSSL_RSA_PUBLIC___;
def RSA_PRIVATE 	___OPENSSL_RSA_PRIVATE___;

def USE_EVP		___OPENSSL_RSA_USE_EVP___;

print 'TRUE: ' + TRUE;
print 'FALSE: ' + FALSE;
print 'WRITE_MODE: ' + WRITE_MODE;
print 'APPEND_MODE: ' + APPEND_MODE;
print 'NULL: ' + NULL;

print 'RSA_SIGN_SHA: ' + RSA_SIGN_SHA;
print 'RSA_SIGN_SHA1: ' + RSA_SIGN_SHA1;
print 'RSA_SIGN_RIPE160: ' + RSA_SIGN_RIPE160;
print 'RSA_SIGN_MD5: ' + RSA_SIGN_MD5;
print 'RSA_SIGN_MD5_SHA1: ' + RSA_SIGN_MD5_SHA1;
print 'RSA_SIGN_SHA256: ' + RSA_SIGN_SHA256;
print 'RSA_SIGN_SHA256_WITH_RSA: ' + RSA_SIGN_SHA256_WITH_RSA;
print 'RSA_SIGN_SHA512: ' + RSA_SIGN_SHA512;
print 'RSA_SIGN_SHA512_WITH_RSA: ' + RSA_SIGN_SHA512_WITH_RSA;

print 'RSA_PAD_PKCS1: ' + RSA_PAD_PKCS1;
print 'RSA_PAD_OAEP: ' + RSA_PAD_OAEP;
print 'RSA_PAD_SSLV23: ' + RSA_PAD_SSLV23;
print 'RSA_PAD_NO: ' + RSA_PAD_NO;

print 'RSA_PUBLIC: ' + RSA_PUBLIC;
print 'RSA_PRIVATE: ' + RSA_PRIVATE;

print 'USE_EVP: ' + USE_EVP;

    上面脚本在命令行中的执行结果类似如下所示:

[root@localhost zenglServer]# ./zenglServer -r /v0_25_0/test_def.zl
TRUE: 1
FALSE: 0
WRITE_MODE: 1
APPEND_MODE: 2
NULL: 0
RSA_SIGN_SHA: 0
RSA_SIGN_SHA1: 1
RSA_SIGN_RIPE160: 2
RSA_SIGN_MD5: 3
RSA_SIGN_MD5_SHA1: 4
RSA_SIGN_SHA256: 5
RSA_SIGN_SHA256_WITH_RSA: 6
RSA_SIGN_SHA512: 7
RSA_SIGN_SHA512_WITH_RSA: 8
RSA_PAD_PKCS1: 0
RSA_PAD_OAEP: 1
RSA_PAD_SSLV23: 2
RSA_PAD_NO: 3
RSA_PUBLIC: 1
RSA_PRIVATE: 0
USE_EVP: 1
[root@localhost zenglServer]# 

backlog及timezone配置:

    当前版本的zenglServer在config.zl配置文件中增加了backlog和timezone的配置:

def TRUE 1;
def FALSE 0;
def KBYTE 1024;

.....................................................................

backlog = 10; // 设置TCP连接队列中可以等待的连接数(backlog的值只是建议值,不同的系统会根据这个值设置不同的等待连接数,例如linux 2.4.7中当backlog为1时,实际可以等待的连接数会是4等),当队列中等待连接的数量满了时,新请求的连接就会报连接被拒绝的错误

timezone = 'Asia/Shanghai'; // 设置时区

pidfile = "zenglServer.pid"; // 设置记录主进程的进程ID的文件名(该文件名可以是相对于当前工作目录的路径)

    backlog可以设置zenglServer在TCP连接队列中可以等待的连接数,当连接数满了时,新的请求就会报连接被拒绝的错误,因此,当并发量大的时候,除了增加zenglServer的进程数外,还可以适当的增大backlog的值。此外,timezone配置可以设置zenglServer中脚本所使用的默认时区。

bltSetTimeZone模块函数:

    当前版本除了可以在配置文件中使用timezone来配置默认时区外,还可以在脚本中使用新增的bltSetTimeZone模块函数来设置脚本所在的时区,该模块函数在源文件中的定义如下(定义在module_builtin.c文件中):

/**
 * bltSetTimeZone模块函数,设置当前脚本所在进程的时区
 * 第一个参数timezone必须是字符串类型,表示需要设置的时区,例如:America/New_York表示设置为纽约时区,Europe/London表示设置为伦敦时区等
 * 具体的时区格式,可以参考GNU官网的介绍:https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
 * 返回值为1表示设置成功
 *
 * 示例:
	use builtin;

	print bltDate('%Y-%m-%d %H:%M:%S'); // 使用配置文件中timezone变量定义的时区来显示当前时间

	bltSetTimeZone("America/New_York"); // 切换到纽约时区

	print bltDate('%Y-%m-%d %H:%M:%S'); // 以纽约时区来显示当前时间

	bltSetTimeZone("Europe/London");    // 切换到伦敦时区

	print bltDate('%Y-%m-%d %H:%M:%S'); // 以伦敦时区来显示当前时间

	bltSetTimeZone("Asia/Shanghai");    // 切换到亚洲上海时区

	print bltDate('%Y-%m-%d %H:%M:%S'); // 以上海时区来显示当前时间

	bltSetTimeZone("");					// 切换到系统默认时区

	print bltDate('%Y-%m-%d %H:%M:%S'); // 使用默认时区来显示当前时间

	执行结果类似如下所示:
	2022-01-25 19:41:04
	2022-01-25 06:41:04
	2022-01-25 11:41:04
	2022-01-25 19:41:04
	2022-01-25 11:41:04

	模块函数版本历史:
	 - v0.25.0版本新增此模块函数
 */
ZL_EXP_VOID module_builtin_set_time_zone(ZL_EXP_VOID * VM_ARG, ZL_EXP_INT argcount)
{
	ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
	const char * func_name = "bltSetTimeZone";
	if(argcount < 1)
		zenglApi_Exit(VM_ARG,"usage: %s(timezone)", func_name);
	zenglApi_GetFunArg(VM_ARG,1,&arg);
	if(arg.type != ZL_EXP_FAT_STR) {
		zenglApi_Exit(VM_ARG,"the first argument [timezone] of %s must be string", func_name);
	}
	char * timezone = (char *)arg.val.str;
	if(setenv("TZ", timezone, 1) == -1) {
		zenglApi_Exit("%s: failed to setenv TZ [%d] %s \n", (char *)func_name, errno, strerror(errno));
	}
	tzset();
	zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_INT, ZL_EXP_NULL, 1, 0);
}

    该模块函数接受一个字符串参数,表示需要设置的时区,例如:America/New_York表示设置为纽约时区,Europe/London表示设置为伦敦时区等,具体的时区格式,可以参考GNU官网的介绍:https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html

test_timezone.zl脚本:

    为了测试上面的bltSetTimeZone模块函数,当前版本在 my_webroot/v0_25_0/ 目录中增加了test_timezone.zl的测试脚本:

use builtin;

print bltDate('%Y-%m-%d %H:%M:%S');

bltSetTimeZone("America/New_York");

print bltDate('%Y-%m-%d %H:%M:%S');

bltSetTimeZone("Europe/London");

print bltDate('%Y-%m-%d %H:%M:%S');

bltSetTimeZone("Asia/Shanghai");

print bltDate('%Y-%m-%d %H:%M:%S');

bltSetTimeZone("");

print bltDate('%Y-%m-%d %H:%M:%S');

    上面脚本分别切换到了纽约时区,伦敦时区,以及亚洲上海时区进行测试,该脚本的执行结果类似如下所示:

[root@localhost zenglServer]# ./zenglServer -r /v0_25_0/test_timezone.zl
2022-01-29 13:40:08
2022-01-29 00:40:08
2022-01-29 05:40:08
2022-01-29 13:40:08
2022-01-29 05:40:08
[root@localhost zenglServer]# 

结束语:

    梦不会逃走,逃走的一直都是自己。

—— 蜡笔小新

 

上下篇

下一篇: zenglServer v0.25.1 使用v1.9.1版本的zengl语言库

上一篇: zenglServer v0.24.0 增加bltVersionCompare,mysqlAffectedRows模块函数,为bltStr增加format可选参数

相关文章

zenglServer v0.14.0 正则表达式模块

zenglServer v0.10.0 使用zengl脚本的编译缓存,跳过编译过程

zenglServer v0.18.0 直接在命令行中执行脚本

zenglServer v0.4.0 daemon守护进程, epoll事件驱动

zenglServer v0.9.0 pydebugger 远程调试

zenglServer v0.24.0 增加bltVersionCompare,mysqlAffectedRows模块函数,为bltStr增加format可选参数