服务端框架
本节介绍 VSOA 服务端框架的开发流程、步骤和注意事项。
开发流程
创建服务端时,不同的开发语言在流程上略有区别,但总体都是按照如下步骤进行:
开发步骤
步骤 1:创建服务端
创建 VSOA 微服务时,每个微服务都需要有一个确定的端口与确定的微服务名。创建服务端时若需要设定密码,则可以通过对应的接口或参数指定该服务的通信密码。
说明:
在使用 C 语言开发方式中,微服务名以 JSON 的格式给出,则必须包含name
字段。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "vsoa_server.h"
#define MY_SERVER_PASSWD "123456"
static vsoa_server_t *server;
int main (int argc, char **argv)
{
struct sockaddr_in addr;
bzero(&addr, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(3001);
addr.sin_addr.s_addr = INADDR_ANY;
#ifdef VSOA_HAS_SIN_LEN
addr.sin_len = sizeof(struct sockaddr_in);
#endif
/*
* Initialize server
*/
server = vsoa_server_create("{\"name\":\"light_server\"}");
if (!server) {
fprintf(stderr, "Can not create VSOA server!\n");
return (-1);
}
/*
* If need password
*/
vsoa_server_passwd(server, MY_SERVER_PASSWD);
return (0);
}
var vsoa = require('vsoa');
/*
* Create server
*/
var server = new vsoa.Server({
info: {
name: 'light_server'
}, passwd: '123456'
});
import java.net.InetSocketAddress;
import com.acoinfo.vsoa.*;
public class light_server {
private static String SERVER_NAME = "light_server";
private static String SERVER_INFO = "\"java language VSOA server\"";
private static String PASSWORD = "123456";
private static String SERVER_ADDR = "0.0.0.0";
private static int SERVER_PORT = 3001;
static Server server;
public static void main(String[] args) {
/*
* Initialize server
*/
try {
ServerOption opt = new ServerOption(SERVER_INFO, PASSWORD, false);
InetSocketAddress address = new InetSocketAddress(SERVER_ADDR, SERVER_PORT);
server = new Server(opt) {
@Override
public void onClient(CliHandle client, boolean link) {
if (!client.isConnected()) {
System.out.println("disconnected");
}
System.out.println("Client link " + link + " address: " + client.address().toString());
}
};
} catch (Exception e1) {
e1.printStackTrace();
return ;
}
}
}
package main
import (
"gitee.com/sylixos/go-vsoa/server"
)
func ServerTest() {
serverOption := server.Option{
Password: "123456",
}
/*
* Create a new server instance
*/
s := server.NewServer("light_server", serverOption)
}
func main() {
ServerTest()
}
from vsoa import Server
# Create a server instance
server = Server(info='light_server', passwd='123456')
步骤 2:启动微服务
微服务创建成功后,需要启动微服务。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "vsoa_server.h"
#define MY_SERVER_PASSWD "123456"
static vsoa_server_t *server;
int main (int argc, char **argv)
{
struct sockaddr_in addr;
bzero(&addr, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(3001);
addr.sin_addr.s_addr = INADDR_ANY;
#ifdef VSOA_HAS_SIN_LEN
addr.sin_len = sizeof(struct sockaddr_in);
#endif
/*
* Initialize server
*/
server = vsoa_server_create("{\"name\":\"light_server\"}");
if (!server) {
fprintf(stderr, "Can not create VSOA server!\n");
return (-1);
}
/*
* If need password
*/
vsoa_server_passwd(server, MY_SERVER_PASSWD);
/*
* Start server
*/
if (!vsoa_server_start(server, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) {
vsoa_server_close(server);
fprintf(stderr, "Can not start VSOA server!\n");
return (-1);
}
return (0);
}
var vsoa = require('vsoa');
var socket = require('socket');
/*
* Create server
*/
var server = new vsoa.Server({
info: {
name: 'light_server'
}, passwd: '123456'
});
/*
* Server start
*/
server.start({
domain: socket.AF_INET, addr: '0.0.0.0', port: 3001
});
import java.net.InetSocketAddress;
import com.acoinfo.vsoa.*;
public class light_server {
private static String SERVER_NAME = "light_server";
private static String SERVER_INFO = "\"java language VSOA server\"";
private static String PASSWORD = "123456";
private static String SERVER_ADDR = "0.0.0.0";
private static int SERVER_PORT = 3001;
static Server server;
public static void main(String[] args) {
/*
* Initialize server
*/
try {
ServerOption opt = new ServerOption(SERVER_INFO, PASSWORD, false);
InetSocketAddress address = new InetSocketAddress(SERVER_ADDR, SERVER_PORT);
server = new Server(opt) {
@Override
public void onClient(CliHandle client, boolean link) {
if (!client.isConnected()) {
System.out.println("disconnected");
}
System.out.println("Client link " + link + " address: " + client.address().toString());
}
};
/*
* Start server
*/
if (!server.start(address, null)) {
return;
}
} catch (Exception e1) {
e1.printStackTrace();
return ;
}
}
}
package main
import (
"gitee.com/sylixos/go-vsoa/server"
)
func ServerTest() {
serverOption := server.Option{
Password: "123456",
}
/*
* Create a new server instance
*/
s := server.NewServer("light_server", serverOption)
s.Serve("localhost:3001")
}
func main() {
ServerTest()
}
from vsoa import Server
# Create a server instance
server = Server(info='light_server', passwd='123456')
# Server start
server.run(host='localhost', port=3001)
说明:
在 Node.js 的环境中,socket.AF_INET
应为vsoa.AF_INET
,详情可见 https://www.npmjs.com/package/vsoa 。
步骤 3:监听事件或循环
VSOA 微服务在启动成功之后,它应当始终监听所有的 VSOA 输入事件。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "vsoa_server.h"
#define MY_SERVER_PASSWD "123456"
static vsoa_server_t *server;
int main (int argc, char **argv)
{
int cnt, max_fd;
fd_set fds;
struct sockaddr_in addr;
struct timespec timeout = { 1, 0 };
bzero(&addr, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(3001);
addr.sin_addr.s_addr = INADDR_ANY;
#ifdef VSOA_HAS_SIN_LEN
addr.sin_len = sizeof(struct sockaddr_in);
#endif
/*
* Initialize server
*/
server = vsoa_server_create("{\"name\":\"light_server\"}");
if (!server) {
fprintf(stderr, "Can not create VSOA server!\n");
return (-1);
}
/*
* If need password
*/
vsoa_server_passwd(server, MY_SERVER_PASSWD);
/*
* Start server
*/
if (!vsoa_server_start(server, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) {
vsoa_server_close(server);
fprintf(stderr, "Can not start VSOA server!\n");
return (-1);
}
while (1) {
FD_ZERO(&fds);
max_fd = vsoa_server_fds(server, &fds);
cnt = pselect(max_fd + 1, &fds, NULL, NULL, &timeout, NULL);
if (cnt > 0) {
vsoa_server_input_fds(server, &fds);
}
}
return (0);
}
var vsoa = require('vsoa');
var socket = require('socket');
/*
* Create server
*/
var server = new vsoa.Server({
info: {
name: 'light_server'
}, passwd: '123456'
});
/*
* Client event
*/
server.onclient = function(client, link) {
console.log(`Client link ${link} address: ${client.address().addr}`);
if (link) {
client.setKeepAlive(5000);
}
};
/*
* Server start
*/
server.start({
domain: socket.AF_INET, addr: '0.0.0.0', port: 3001
});
/*
* Event loop
*/
require('iosched').forever();
import java.net.InetSocketAddress;
import com.acoinfo.vsoa.*;
public class light_server {
private static String SERVER_NAME = "light_server";
private static String SERVER_INFO = "\"java language VSOA server\"";
private static String PASSWORD = "123456";
private static String SERVER_ADDR = "0.0.0.0";
private static int SERVER_PORT = 3001;
static Server server;
public static void main(String[] args) {
/*
* Initialize server
*/
try {
ServerOption opt = new ServerOption(SERVER_INFO, PASSWORD, false);
InetSocketAddress address = new InetSocketAddress(SERVER_ADDR, SERVER_PORT);
server = new Server(opt) {
@Override
public void onClient(CliHandle client, boolean link) {
if (!client.isConnected()) {
System.out.println("disconnected");
}
System.out.println("Client link " + link + " address: " + client.address().toString());
}
};
/*
* Start server
*/
if (!server.start(address, null)) {
return;
}
} catch (Exception e1) {
e1.printStackTrace();
return ;
}
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package main
import (
"time"
"gitee.com/sylixos/go-vsoa/server"
)
func ServerTest() {
serverOption := server.Option{
Password: "123456",
}
/*
* Create a new server instance
*/
s := server.NewServer("light_server", serverOption)
go func() {
_ = s.Serve("localhost:3001")
}()
}
func main() {
ServerTest()
for {
time.Sleep(1 * time.Second)
}
}
from vsoa import Server
from vsoa.server import Client
# Create a server instance
server = Server(info='light_server', passwd='123456')
def onclient(cli: Client, conn: bool):
print('Client link {} address: {}'.format(conn, cli.address()[0]))
server.onclient = onclient
# Server start
server.run(host='localhost', port=3001)
说明:
- 在 Node.js 的环境中,不需要事件循环,即删除
require('iosched').forever();
。- 在 Node.js 的环境中,
socket.AF_INET
应为vsoa.AF_INET
,详情可见 https://www.npmjs.com/package/vsoa 。
注意事项
C/C++ 服务端编译时需链接如下表所示的 VSOA 动态库,在 RealEvo-IDE 中配置时请参考 C/C++ 环境验证,Linux 下开发请参考 搭建 Linux 运行环境 提供的 C 语言范例进行配置。
库名称 | 功能 |
---|---|
libvsoa-json.so | 提供 JSON 功能 |
libvsoa-server.so | 提供服务端功能 |
libvsoa-parser.so | 提供参数解析功能 |