mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-02 11:57:43 +08:00
test websocket demo for Android
This commit is contained in:
parent
2bd1024971
commit
3250875984
@ -36,16 +36,16 @@
|
|||||||
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
|
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debug/compileDebugRenderscript/out" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debug/compileDebugAidl/out" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debug/compileDebugAidl/out" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debug/compileDebugRenderscript/out" isTestSource="false" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debugAndroidTest/compileDebugAndroidTestAidl/out" isTestSource="true" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debugAndroidTest/compileDebugAndroidTestRenderscript/out" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debugAndroidTest/compileDebugAndroidTestRenderscript/out" isTestSource="true" generated="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debugAndroidTest/compileDebugAndroidTestAidl/out" isTestSource="true" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" generated="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
|
||||||
|
@ -121,8 +121,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Android")
|
|||||||
set(lib_all ${lib_acl_cpp} ${lib_protocol} ${lib_acl} -lz)
|
set(lib_all ${lib_acl_cpp} ${lib_protocol} ${lib_acl} -lz)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(native-lib SHARED ${lib_src})
|
add_library(ws SHARED ${lib_src})
|
||||||
target_link_libraries(native-lib ${lib_all} ${log-lib})
|
target_link_libraries(ws ${lib_all} ${log-lib})
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by shuxin zheng on 2020-03-29.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "websocket.h"
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
|
||||||
Java_com_example_http_HttpClient_WebsocketStart(
|
|
||||||
JNIEnv*,
|
|
||||||
jobject)
|
|
||||||
{
|
|
||||||
log_info("START!\r\n");
|
|
||||||
websocket_run();
|
|
||||||
log_info("FINISH!\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
|
||||||
Java_com_example_http_HttpClient_HttpGet(
|
|
||||||
JNIEnv* env,
|
|
||||||
jobject me,
|
|
||||||
jstring addr,
|
|
||||||
jstring host,
|
|
||||||
jstring url)
|
|
||||||
{
|
|
||||||
std::string server_addr, server_host, server_url;
|
|
||||||
JString2String(env, addr, server_addr);
|
|
||||||
JString2String(env, host, server_host);
|
|
||||||
JString2String(env, url, server_url);
|
|
||||||
|
|
||||||
acl::http_request request(server_addr.c_str());
|
|
||||||
acl::http_header& header = request.request_header();
|
|
||||||
header.set_url(server_url.c_str())
|
|
||||||
.set_host(server_host.c_str())
|
|
||||||
.accept_gzip(true)
|
|
||||||
.set_keep_alive(false);
|
|
||||||
|
|
||||||
log_info("addr=%s, host=%s, url=%s", server_addr.c_str(),
|
|
||||||
server_host.c_str(), server_url.c_str());
|
|
||||||
|
|
||||||
if (!request.request(NULL, 0)) {
|
|
||||||
log_error("send http request error=%s", acl::last_serror());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
acl::string body;
|
|
||||||
if (!request.get_body(body)) {
|
|
||||||
log_error("get body error: %s", acl::last_serror());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return String2JString(env, body);
|
|
||||||
}
|
|
37
android/samples/websocket/websocket/src/main/cpp/jni.cpp
Normal file
37
android/samples/websocket/websocket/src/main/cpp/jni.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Created by shuxin zheng on 2020-03-29.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "websocket.h"
|
||||||
|
|
||||||
|
static void websocket_callback(void* env_ctx, void* obj_ctx, const char* msg)
|
||||||
|
{
|
||||||
|
JNIEnv* env = (JNIEnv*) env_ctx;
|
||||||
|
jobject obj = (jobject) obj_ctx;
|
||||||
|
|
||||||
|
jclass clz = env->GetObjectClass(obj);
|
||||||
|
if (clz) {
|
||||||
|
jmethodID mID = env->GetMethodID(clz, "onMessage", "(Ljava/lang/String;)V");
|
||||||
|
if (mID) {
|
||||||
|
jstring s = String2JString(env, msg);
|
||||||
|
env->CallVoidMethod(obj, mID, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_com_example_http_HttpClient_WebsocketStart(
|
||||||
|
JNIEnv* env,
|
||||||
|
jobject obj,
|
||||||
|
jstring addr)
|
||||||
|
{
|
||||||
|
log_open();
|
||||||
|
log_info("START!\r\n");
|
||||||
|
|
||||||
|
std::string server_addr;
|
||||||
|
JString2String(env, addr, server_addr);
|
||||||
|
websocket_run(server_addr.c_str(), websocket_callback, env, obj);
|
||||||
|
log_info("FINISH!\r\n");
|
||||||
|
}
|
@ -30,4 +30,56 @@ void log_error(const char* fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void write_callback(void*, const char* fmt, va_list ap)
|
||||||
|
{
|
||||||
|
char buf[512];
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "dns-debug", "%s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __opened = false;
|
||||||
|
|
||||||
|
static int open_callback(const char*, void*)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void logger_hook(void (*write_callback)(void*, const char* fmt, va_list ap))
|
||||||
|
{
|
||||||
|
if (__opened) {
|
||||||
|
return;;
|
||||||
|
}
|
||||||
|
__opened = true;
|
||||||
|
acl_msg_register(open_callback, NULL, write_callback, NULL);
|
||||||
|
acl_msg_open("dummy.txt", "dummy");
|
||||||
|
logger("acl lib init ok!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void logger_unhook(void)
|
||||||
|
{
|
||||||
|
if (!__opened) {
|
||||||
|
return;;
|
||||||
|
}
|
||||||
|
__opened = false;
|
||||||
|
acl_msg_unregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_open(void)
|
||||||
|
{
|
||||||
|
if (__opened) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
__opened = true;
|
||||||
|
|
||||||
|
log_info("call logger_hook\r\n");
|
||||||
|
logger_hook(write_callback);
|
||||||
|
log_info("call logger_hook ok\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_close(void)
|
||||||
|
{
|
||||||
|
if (__opened) {
|
||||||
|
logger_unhook();
|
||||||
|
__opened = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,5 +2,8 @@
|
|||||||
|
|
||||||
void JString2String(JNIEnv *env, jstring js, std::string &out);
|
void JString2String(JNIEnv *env, jstring js, std::string &out);
|
||||||
jstring String2JString(JNIEnv *env, const char *s);
|
jstring String2JString(JNIEnv *env, const char *s);
|
||||||
|
|
||||||
|
void log_open(void);
|
||||||
|
void log_close(void);
|
||||||
void log_info(const char* fmt, ...);
|
void log_info(const char* fmt, ...);
|
||||||
void log_error(const char* fmt, ...);
|
void log_error(const char* fmt, ...);
|
||||||
|
@ -9,9 +9,13 @@ static acl::atomic_long __aio_refer = 0;
|
|||||||
class websocket_client : public acl::http_aclient
|
class websocket_client : public acl::http_aclient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
websocket_client(acl::aio_handle& handle, const char* host)
|
websocket_client(acl::aio_handle& handle, const char* host,
|
||||||
|
void (*callback)(void*, void*, const char*), void* env, void* obj)
|
||||||
: http_aclient(handle, NULL)
|
: http_aclient(handle, NULL)
|
||||||
, host_(host)
|
, host_(host)
|
||||||
|
, callback_(callback)
|
||||||
|
, env_(env)
|
||||||
|
, obj_(obj)
|
||||||
, debug_(false)
|
, debug_(false)
|
||||||
, compressed_(false)
|
, compressed_(false)
|
||||||
{
|
{
|
||||||
@ -50,6 +54,7 @@ protected:
|
|||||||
{
|
{
|
||||||
log_info("%s(%d): websocket_client will be deleted!\r\n",
|
log_info("%s(%d): websocket_client will be deleted!\r\n",
|
||||||
__FUNCTION__, __LINE__);
|
__FUNCTION__, __LINE__);
|
||||||
|
on_message("websocket will be deleted");
|
||||||
|
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
@ -58,8 +63,10 @@ protected:
|
|||||||
bool on_connect(void)
|
bool on_connect(void)
|
||||||
{
|
{
|
||||||
log_info("--------------- connect server ok ------------\r\n");
|
log_info("--------------- connect server ok ------------\r\n");
|
||||||
|
on_message("connect server ok");
|
||||||
show_ns_addr();
|
show_ns_addr();
|
||||||
log_info(">>> begin ws_handshake\r\n");
|
log_info(">>> begin ws_handshake\r\n");
|
||||||
|
on_message("begin ws handshake");
|
||||||
|
|
||||||
this->ws_handshake();
|
this->ws_handshake();
|
||||||
return true;
|
return true;
|
||||||
@ -72,6 +79,8 @@ protected:
|
|||||||
reqhdr.build_request(buf);
|
reqhdr.build_request(buf);
|
||||||
log_info("---------------websocket request header---------\r\n");
|
log_info("---------------websocket request header---------\r\n");
|
||||||
log_info("[%s]\r\n", buf.c_str());
|
log_info("[%s]\r\n", buf.c_str());
|
||||||
|
on_message("ws request header");
|
||||||
|
on_message(buf.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
@ -79,18 +88,21 @@ protected:
|
|||||||
{
|
{
|
||||||
log_info("%s(%d): disconnect from server\r\n",
|
log_info("%s(%d): disconnect from server\r\n",
|
||||||
__FUNCTION__, __LINE__);
|
__FUNCTION__, __LINE__);
|
||||||
|
on_message("disconnect from server");
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
void on_ns_failed(void)
|
void on_ns_failed(void)
|
||||||
{
|
{
|
||||||
log_info("dns lookup failed\r\n");
|
log_info("dns lookup failed\r\n");
|
||||||
|
on_message("dns lookup failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
void on_connect_timeout(void)
|
void on_connect_timeout(void)
|
||||||
{
|
{
|
||||||
log_info("connect timeout\r\n");
|
log_info("connect timeout\r\n");
|
||||||
|
on_message("connect timeout");
|
||||||
show_ns_addr();
|
show_ns_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +110,7 @@ protected:
|
|||||||
void on_connect_failed(void)
|
void on_connect_failed(void)
|
||||||
{
|
{
|
||||||
log_info("connect failed\r\n");
|
log_info("connect failed\r\n");
|
||||||
|
on_message("connect failed");
|
||||||
show_ns_addr();
|
show_ns_addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +118,7 @@ protected:
|
|||||||
bool on_read_timeout(void)
|
bool on_read_timeout(void)
|
||||||
{
|
{
|
||||||
log_info("read timeout\r\n");
|
log_info("read timeout\r\n");
|
||||||
|
on_message("read timeout");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +133,8 @@ protected:
|
|||||||
|
|
||||||
log_info("-----------%s: response header----\r\n", __FUNCTION__);
|
log_info("-----------%s: response header----\r\n", __FUNCTION__);
|
||||||
log_info("[%s]\r\n", buf.c_str());
|
log_info("[%s]\r\n", buf.c_str());
|
||||||
|
on_message("response header");
|
||||||
|
on_message(buf.c_str());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -153,6 +169,7 @@ protected:
|
|||||||
bool on_ws_handshake(void)
|
bool on_ws_handshake(void)
|
||||||
{
|
{
|
||||||
log_info(">>> websocket handshake ok\r\n");
|
log_info(">>> websocket handshake ok\r\n");
|
||||||
|
on_message("websocket handshake ok");
|
||||||
|
|
||||||
char buf[128];
|
char buf[128];
|
||||||
snprintf(buf, sizeof(buf), "hello, myname is zsx\r\n");
|
snprintf(buf, sizeof(buf), "hello, myname is zsx\r\n");
|
||||||
@ -162,6 +179,8 @@ protected:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_info("send ok\r\n");
|
||||||
|
on_message("send ok");
|
||||||
// 开始进入 websocket 异步读过程
|
// 开始进入 websocket 异步读过程
|
||||||
this->ws_read_wait(5);
|
this->ws_read_wait(5);
|
||||||
return true;
|
return true;
|
||||||
@ -171,26 +190,30 @@ protected:
|
|||||||
void on_ws_handshake_failed(int status)
|
void on_ws_handshake_failed(int status)
|
||||||
{
|
{
|
||||||
log_info(">>> websocket handshake failed, status=%d\r\n", status);
|
log_info(">>> websocket handshake failed, status=%d\r\n", status);
|
||||||
|
on_message("websocket handshake failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
bool on_ws_frame_text(void)
|
bool on_ws_frame_text(void)
|
||||||
{
|
{
|
||||||
log_info(">>> got frame text type\r\n");
|
log_info(">>> got frame text\r\n");
|
||||||
|
on_message("got fame text");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
bool on_ws_frame_binary(void)
|
bool on_ws_frame_binary(void)
|
||||||
{
|
{
|
||||||
log_info(">>> got frame binaray type\r\n");
|
log_info(">>> got frame binaray\r\n");
|
||||||
|
on_message("got frame binary");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
void on_ws_frame_closed(void)
|
void on_ws_frame_closed(void)
|
||||||
{
|
{
|
||||||
log_info(">>> got frame closed type\r\n");
|
log_info(">>> got frame closed\r\n");
|
||||||
|
on_message("got frame closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
@ -199,6 +222,7 @@ protected:
|
|||||||
acl::string buf;
|
acl::string buf;
|
||||||
buf.copy(data, dlen);
|
buf.copy(data, dlen);
|
||||||
log_info("%s", buf.c_str());
|
log_info("%s", buf.c_str());
|
||||||
|
on_message(buf.c_str());
|
||||||
|
|
||||||
//(void) write(1, data, dlen);
|
//(void) write(1, data, dlen);
|
||||||
return true;
|
return true;
|
||||||
@ -208,20 +232,35 @@ protected:
|
|||||||
bool on_ws_frame_finish(void)
|
bool on_ws_frame_finish(void)
|
||||||
{
|
{
|
||||||
log_info(">>> frame finish\r\n");
|
log_info(">>> frame finish\r\n");
|
||||||
|
on_message("frame finished");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
acl::string host_;
|
acl::string host_;
|
||||||
|
void (*callback_)(void*, void*, const char*);
|
||||||
|
void* env_;
|
||||||
|
void* obj_;
|
||||||
bool debug_;
|
bool debug_;
|
||||||
bool compressed_;
|
bool compressed_;
|
||||||
|
|
||||||
|
void on_message(const char* fmt, ...)
|
||||||
|
{
|
||||||
|
acl::string buf;
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
buf.vformat(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
callback_(env_, obj_, buf.c_str());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool websocket_run(void)
|
bool websocket_run(const char* addr, void (*callback)(void*, void*, const char*),
|
||||||
|
void* env, void* obj)
|
||||||
{
|
{
|
||||||
int conn_timeout = 5, rw_timeout = 5;
|
int conn_timeout = 5, rw_timeout = 5;
|
||||||
acl::string addr("10.110.28.210:8885");
|
acl::string host("www.test.com");
|
||||||
acl::string host("www.baidu.com");
|
|
||||||
std::vector<acl::string> name_servers;
|
std::vector<acl::string> name_servers;
|
||||||
bool debug = false;
|
bool debug = false;
|
||||||
|
|
||||||
@ -243,9 +282,9 @@ bool websocket_run(void)
|
|||||||
|
|
||||||
|
|
||||||
// 开始异步连接远程 WEB 服务器
|
// 开始异步连接远程 WEB 服务器
|
||||||
websocket_client* conn = new websocket_client(handle, host);
|
websocket_client* conn = new websocket_client(handle, host, callback, env, obj);
|
||||||
if (!conn->open(addr, conn_timeout, rw_timeout)) {
|
if (!conn->open(addr, conn_timeout, rw_timeout)) {
|
||||||
log_info("connect %s error\r\n", addr.c_str());
|
log_info("connect %s error\r\n", addr);
|
||||||
|
|
||||||
delete conn;
|
delete conn;
|
||||||
return false;
|
return false;
|
||||||
@ -279,6 +318,7 @@ bool websocket_run(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 再检测一次,以便于将可能漏掉的非阻塞连接对象释放
|
||||||
handle.check();
|
handle.check();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
bool websocket_run(void);
|
/**
|
||||||
|
* 启动 Websocket 非阻塞客户端
|
||||||
|
* @param addr {const char*} Websocket 服务端地址
|
||||||
|
* @param callback {void (*)(void*, void*, const char*)} 读到服务端信息后的回调
|
||||||
|
* @param env {void*}
|
||||||
|
* @param obj {void*}
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool websocket_run(const char* addr, void (*callback)(void*, void*, const char*),
|
||||||
|
void* env, void* obj);
|
||||||
|
@ -1,28 +1,31 @@
|
|||||||
package com.example.http;
|
package com.example.http;
|
||||||
|
|
||||||
public final class HttpClient {
|
public final class HttpClient {
|
||||||
|
private HttpHandler handler;
|
||||||
private String serverAddr;
|
private String serverAddr;
|
||||||
|
|
||||||
public HttpClient(String addr) {
|
public HttpClient(HttpHandler handler, String addr) {
|
||||||
|
this.handler = handler;
|
||||||
this.serverAddr = addr;
|
this.serverAddr = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String get(String host, String url) {
|
/**
|
||||||
try {
|
* 启动并测试 Websocket 客户端
|
||||||
String body = HttpGet(serverAddr, host, url);
|
*/
|
||||||
return body;
|
public void websocketStart() {
|
||||||
} catch (UnsatisfiedLinkError e) {
|
WebsocketStart(serverAddr);
|
||||||
System.out.println("HttpGet error=" + e.toString());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void websocketStart() {
|
/**
|
||||||
WebsocketStart();
|
* 在 jni 中回调此方法
|
||||||
|
* @param msg {String}
|
||||||
|
*/
|
||||||
|
public void onMessage(String msg) {
|
||||||
|
handler.onData(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Jni Native method
|
// Jni Native method
|
||||||
private native String HttpGet(String serverAddr, String host, String url);
|
private native void WebsocketStart(String addr);
|
||||||
private native void WebsocketStart();
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ import android.os.Handler;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
|
||||||
public final class HttpHandler extends Handler {
|
public final class HttpHandler extends Handler {
|
||||||
final public static int BODY_OK = 0;
|
final public static int DATA_OK = 0;
|
||||||
final public static int BODY_ERR = 1;
|
|
||||||
private final MainActivity mainActivity;
|
private final MainActivity mainActivity;
|
||||||
|
|
||||||
public HttpHandler(MainActivity mainActivity) {
|
public HttpHandler(MainActivity mainActivity) {
|
||||||
@ -15,11 +14,8 @@ public final class HttpHandler extends Handler {
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message message) {
|
public void handleMessage(Message message) {
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
case BODY_OK:
|
case DATA_OK:
|
||||||
mainActivity.onBody((String) message.obj);
|
mainActivity.onData((String) message.obj);
|
||||||
break;
|
|
||||||
case BODY_ERR:
|
|
||||||
mainActivity.onError((String) message.obj);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -27,26 +23,13 @@ public final class HttpHandler extends Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 成功获得 HTTP 数据体的回调方法
|
* 在 Websocket 线程空间中的回调方法,用来传递消息
|
||||||
* @param body {String} 响应的 HTTP 数据体
|
* @param data {String} 响应的 HTTP 数据体
|
||||||
*/
|
*/
|
||||||
public void onBody(String body) {
|
public void onData(String data) {
|
||||||
Message message = new Message();
|
Message message = new Message();
|
||||||
message.what = BODY_OK;
|
message.what = DATA_OK;
|
||||||
message.obj = body;
|
message.obj = data;
|
||||||
this.sendMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 HTTP 结果失败时的回调方法
|
|
||||||
* @param domain {String} 请求的域名
|
|
||||||
* @param url {String} 请求的 URL
|
|
||||||
*/
|
|
||||||
public void onError(String domain, String url) {
|
|
||||||
String error = "Domain: domain, " + "url: url";
|
|
||||||
Message message = new Message();
|
|
||||||
message.what = BODY_ERR;
|
|
||||||
message.obj = error;
|
|
||||||
this.sendMessage(message);
|
this.sendMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,15 @@ package com.example.http;
|
|||||||
public final class HttpThread extends Thread {
|
public final class HttpThread extends Thread {
|
||||||
private HttpHandler handler;
|
private HttpHandler handler;
|
||||||
private String serverAddr;
|
private String serverAddr;
|
||||||
private String host;
|
|
||||||
private String url;
|
|
||||||
|
|
||||||
public HttpThread(HttpHandler handler, String serverAddr,
|
public HttpThread(HttpHandler handler, String serverAddr) {
|
||||||
String host, String url) {
|
this.handler = handler;
|
||||||
this.handler = handler;
|
|
||||||
this.serverAddr = serverAddr;
|
this.serverAddr = serverAddr;
|
||||||
this.host = host;
|
|
||||||
this.url = url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
HttpClient httpClient = new HttpClient(serverAddr);
|
HttpClient httpClient = new HttpClient(handler, serverAddr);
|
||||||
httpClient.websocketStart();
|
httpClient.websocketStart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.example.http;
|
|||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.method.ScrollingMovementMethod;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
@ -11,10 +12,11 @@ import android.widget.TextView;
|
|||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
private EditText domain;
|
private EditText domain;
|
||||||
private TextView result;
|
private TextView result;
|
||||||
|
StringBuffer text = new StringBuffer();
|
||||||
|
|
||||||
// Used to load the 'native-lib' library on application startup.
|
// Used to load the 'native-lib' library on application startup.
|
||||||
static {
|
static {
|
||||||
System.loadLibrary("native-lib");
|
System.loadLibrary("ws");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,7 +24,6 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
* @param info
|
* @param info
|
||||||
*/
|
*/
|
||||||
public void onError(String info) {
|
public void onError(String info) {
|
||||||
StringBuffer text = new StringBuffer();
|
|
||||||
text.append("httpGet error\r\n");
|
text.append("httpGet error\r\n");
|
||||||
text.append(info + "\r\n");
|
text.append(info + "\r\n");
|
||||||
result.setText(text);
|
result.setText(text);
|
||||||
@ -30,30 +31,34 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得 HTTP 数据体成功的回调方法
|
* 获得 HTTP 数据体成功的回调方法
|
||||||
* @param body
|
* @param data
|
||||||
*/
|
*/
|
||||||
public void onBody(String body) {
|
public void onData(String data) {
|
||||||
result.setText(body);
|
result.append(data);
|
||||||
|
result.append("\r\n");
|
||||||
|
int offset = result.getLineCount() * result.getLineHeight();
|
||||||
|
if (offset > result.getHeight()){
|
||||||
|
result.scrollTo(0,offset - result.getHeight());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从 HTTP 服务器获得数据
|
* 从 HTTP Websocket 服务器获得数据
|
||||||
*/
|
*/
|
||||||
private void httpGet() {
|
private void websocketStart() {
|
||||||
String host = domain.getText().toString().trim();
|
String addr = domain.getText().toString().trim();
|
||||||
if (host.isEmpty()) {
|
if (addr.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("host is " + host);
|
System.out.println("addr is " + addr);
|
||||||
try {
|
try {
|
||||||
HttpHandler handler = new HttpHandler(this);
|
HttpHandler handler = new HttpHandler(this);
|
||||||
String addr = host + ":80", url = "/";
|
HttpThread httpThread = new HttpThread(handler, addr);
|
||||||
HttpThread httpThread = new HttpThread(handler, addr, host, url);
|
|
||||||
httpThread.start();
|
httpThread.start();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
onError(host);
|
onError(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,13 +69,15 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
domain = (EditText) findViewById(R.id.domain);
|
domain = (EditText) findViewById(R.id.domain);
|
||||||
result = findViewById(R.id.result);
|
result = findViewById(R.id.result);
|
||||||
|
result.setMovementMethod(ScrollingMovementMethod.getInstance());
|
||||||
|
result.setScrollbarFadingEnabled(false);
|
||||||
|
|
||||||
// 绑定 HTTP 请求事件
|
// 绑定 HTTP 请求事件
|
||||||
Button get = (Button) findViewById(R.id.http_get);
|
Button get = (Button) findViewById(R.id.http_get);
|
||||||
get.setOnClickListener(new View.OnClickListener() {
|
get.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
httpGet();
|
websocketStart();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,15 +23,16 @@
|
|||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:text="域名:"
|
android:text="域名:"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/domain"
|
android:id="@+id/domain"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_toRightOf="@+id/domain_lable"
|
||||||
android:ems="10"
|
android:ems="10"
|
||||||
android:inputType="textPersonName"
|
android:inputType="textPersonName"
|
||||||
android:layout_toRightOf="@+id/domain_lable"
|
android:text="10.110.28.210|8885"
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:text="www.baidu.com"
|
|
||||||
android:verticalScrollbarPosition="defaultPosition"
|
android:verticalScrollbarPosition="defaultPosition"
|
||||||
tools:layout_editor_absoluteX="88dp"
|
tools:layout_editor_absoluteX="88dp"
|
||||||
tools:layout_editor_absoluteY="97dp" />
|
tools:layout_editor_absoluteY="97dp" />
|
||||||
@ -76,6 +77,7 @@
|
|||||||
android:paddingBottom="40dp"
|
android:paddingBottom="40dp"
|
||||||
android:scrollbarStyle="outsideInset"
|
android:scrollbarStyle="outsideInset"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="vertical"
|
||||||
|
android:fillViewport="true"
|
||||||
android:scrollHorizontally="true"
|
android:scrollHorizontally="true"
|
||||||
android:text="TextView"
|
android:text="TextView"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
|
@ -381,26 +381,25 @@ bool http_aclient::handle_websocket(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在 SSL 握手阶段,该方法会多次调用,直至 SSL 握手成功或失败
|
// SSL 握手和读 Websocket 数据帧阶段,该方法都会被多次调用。
|
||||||
|
// 当启用 SSL 模式时,在 SSL 握手阶段,该方法会被多次调用,直至 SSL 握手成功
|
||||||
|
// 或失败;在读取 Websocket 数据帧阶段,该方法也会被多次调用,用来一直读取数据帧
|
||||||
bool http_aclient::read_wakeup(void)
|
bool http_aclient::read_wakeup(void)
|
||||||
{
|
{
|
||||||
#if defined(HAS_POLARSSL_DLL) || defined(HAS_POLARSSL)
|
|
||||||
// 如果 websocket 非 NULL,则说明进入到 websocket 通信方式,
|
// 如果 websocket 非 NULL,则说明进入到 websocket 通信方式,
|
||||||
// 该触发条件在 http_res_hdr_cllback 中注册
|
// 该触发条件在 http_res_hdr_cllback 中注册
|
||||||
switch (status_) {
|
switch (status_) {
|
||||||
case HTTP_ACLIENT_STATUS_WS_READING:
|
case HTTP_ACLIENT_STATUS_WS_READING:
|
||||||
acl_assert(ws_in_);
|
acl_assert(ws_in_);
|
||||||
return handle_websocket();
|
return handle_websocket();
|
||||||
|
#if defined(HAS_POLARSSL_DLL) || defined(HAS_POLARSSL)
|
||||||
case HTTP_ACLIENT_STATUS_SSL_HANDSHAKE:
|
case HTTP_ACLIENT_STATUS_SSL_HANDSHAKE:
|
||||||
return handle_ssl_handshake();
|
return handle_ssl_handshake();
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
logger_error("invalid status=%u", status_);
|
logger_error("invalid status=%u", status_);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
logger_error("shouldn't come here in no SSL mode!");
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool http_aclient::handle_ssl_handshake(void)
|
bool http_aclient::handle_ssl_handshake(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user