HarmonyOS没有提供HTTP服务端的实现接口,但是因为HTTP协议是基于TCP的,可以通过TCPSocketServer类用API接口,加上HTTP协议的格式,打造一个简单的HTTP服务端。
用TCPSocket在服务端开启TCP监听,启动服务器来监听指定端口,接收客户端连接。当客户端发送消息时,服务器接收并返回响应。停止服务器时关闭连接监听,释放资源。
import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { util } from '@kit.ArkTS';
// 全局变量
let tcpServer: socket.TCPSocketServer = socket.constructTCPSocketServerInstance();
@Entry
@Component
struct Index {
@State port: number = 8080;
@State running: boolean = false;
@State msgHistory: string = '';
// 监听的ip地址,此处地址实际使用过程中替换为真实地址
@State webUrl: string = 'xx.xx.xx';
scroller: Scroller = new Scroller();
build() {
Column() {
Text('HTTP服务器')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin(10);
Row() {
Text('端口:')
.fontSize(16)
.margin(5);
TextInput({ text: this.port.toString() })
.onChange((value) => {
this.port = parseInt(value) || 8080;
this.webUrl = `${this.webUrl}:${this.port}`;
})
.type(InputType.Number)
.width(80)
.height(40)
.margin(5);
};
Button(this.running ? '停止服务器' : '启动服务器')
.onClick(() => {
this.running = !this.running;
if (this.running) {
this.startServer();
} else {
this.stopServer();
}
})
.width(200)
.margin(10);
Text('访问地址:')
.fontSize(16)
.margin(5);
Text(this.webUrl)
.fontSize(14)
.textAlign(TextAlign.Start)
.margin(5);
Scroll(this.scroller) {
Text(this.msgHistory)
.textAlign(TextAlign.Start)
.fontSize(12);
}
.height(300)
.width('100%')
.padding(10)
.border({ width: 1, color: Color.Gray })
.margin(10);
}
.width('100%')
.height('100%')
.padding(10);
}
// 开启服务
startServer() {
let listenAddr: socket.NetAddress = {
address: '0.0.0.0',
port: this.port,
family: 1
};
tcpServer.listen(listenAddr, (err: BusinessError) => {
if (err) {
this.msgHistory += 'listen fail \r\n';
return;
}
this.msgHistory += 'listen success \r\n';
});
// 连接后得到了clientSocket对象,然后继续订阅clientSocket对象的收到客户端消息事件
tcpServer.on('connect', (clientSocket: socket.TCPSocketConnection) => {
clientSocket.on('message', (msgInfo: socket.SocketMessageInfo) => {
let requestMsg = buf2String(msgInfo.message);
this.msgHistory += requestMsg + '\r\n';
let resp = buildRespString(requestMsg);
clientSocket.send({ data: resp });
});
});
}
stopServer() {
tcpServer.off('connect');
}
}
// 构造给客户端的应答内容
function buildRespString(content: string) {
let result: string = '';
let bodyContent = '<html>';
bodyContent += '<head>';
bodyContent += '<title>';
bodyContent += 'HTTP服务器模拟';
bodyContent += '</title>';
bodyContent += '</head>';
bodyContent += '<body>';
bodyContent += '<h1>';
bodyContent += '浏览器发送的请求信息';
bodyContent += '</h1>';
bodyContent += '<pre><h2>';
bodyContent += content;
bodyContent += '</h2></pre>';
bodyContent += '</body>';
bodyContent += '</html>';
let textEncoder = new util.TextEncoder();
let contentBuf = textEncoder.encodeInto(bodyContent);
result += 'HTTP/1.1 200 OK \r\n';
result += 'Content-Type: text/html; charset=utf-8 \r\n';
result += `Content-Length: ${contentBuf.length} \r\n`;
result += '\r\n';
result += bodyContent;
return result;
}
// ArrayBuffer转字符串
function buf2String(buf: ArrayBuffer): string {
const msgArray = new Uint8Array(buf);
const textDecoder = util.TextDecoder.create('utf-8');
return textDecoder.decodeToString(msgArray);
} HarmonyOS API10提供了TCPSocketServer类,包含了如下几个关键接口:
listen(address: NetAddress): Promise<void>
on(type: 'connect', callback: Callback<TCPSocketConnection>): void
TCPSocketConnection是服务端和客户端通讯的基础。
send(options: TCPSendOptions): Promise<void>
on(type: 'message', callback: Callback<SocketMessageInfo>): void
在这个事件的callback回调里,包含了SocketMessageInfo参数,该参数的属性message就是客户端发送过来的消息。