acl/lib_acl_cpp/samples/websocket/upload_client/main.cpp

189 lines
3.7 KiB
C++

#include "stdafx.h"
static bool handshake(acl::socket_stream& conn)
{
acl::http_request req(&conn);
acl::http_header& hdr = req.request_header();
hdr.set_ws_key("123456789")
.set_ws_version(13)
.set_upgrade("websocket")
.set_keep_alive(true);
if (req.request(NULL, 0) == false)
{
printf("request error\r\n");
return false;
}
int status = req.http_status();
if (status != 101)
{
printf("invalid http status: %d\r\n", status);
return false;
}
return true;
}
static bool send_file(acl::websocket& ws, const char* filepath)
{
acl::ifstream in;
if (in.open_read(filepath) == false)
{
printf("open %s error %s\r\n", filepath, acl::last_serror());
return false;
}
long long size = in.fsize();
if (size <= 0)
{
printf("filename: %s, invalid size: %lld\r\n", filepath, size);
return false;
}
acl::string buf;
buf.basename(filepath);
ws.set_frame_fin(true)
.set_frame_opcode(acl::FRAME_TEXT)
.set_frame_payload_len(buf.size());
if (ws.send_frame_data(buf, buf.size()) == false)
{
printf("send filenam error %s\r\n", acl::last_serror());
return false;
}
buf.format("%lld", size);
ws.reset().set_frame_fin(true)
.set_frame_opcode(acl::FRAME_TEXT)
.set_frame_payload_len(buf.size());
if (ws.send_frame_data(buf, buf.size()) == false)
{
printf("send file size error %s\r\n", acl::last_serror());
return false;
}
long long total = 0;
char cbuf[128000];
while (!in.eof())
{
int ret = in.read(cbuf, sizeof(cbuf), false);
if (ret == -1)
break;
printf(">>send %d\r\n", ret);
ws.reset().set_frame_fin(true)
.set_frame_opcode(acl::FRAME_BINARY)
.set_frame_payload_len(ret);
if (ws.send_frame_data(cbuf, ret) == false)
{
printf("send data error %s\r\n", acl::last_serror());
return false;
}
total += ret;
if (total % 10240000 == 0)
sleep(1);
}
printf(">>total send: %lld\r\n", total);
return true;
}
static bool read_reply(acl::websocket& ws)
{
if (ws.read_frame_head() == false)
{
printf("read_frame_head error %s\r\n", acl::last_serror());
return false;
}
char cbuf[1024];
unsigned char opcode = ws.get_frame_opcode();
switch (opcode)
{
case acl::FRAME_TEXT:
case acl::FRAME_BINARY:
break;
default:
printf("invalid opcode: 0x%x\r\n", opcode);
return false;
}
int ret = ws.read_frame_data(cbuf, sizeof(cbuf) - 1);
if (ret <= 0)
{
printf("read_frame_data error\r\n");
return false;
}
cbuf[ret] = 0;
printf("reply from server: %s, len: %d\r\n", cbuf, ret);
return true;
}
static bool upload(const char* addr, const char* filepath)
{
acl::socket_stream conn;
if (conn.open(addr, 30, 30) == false)
{
printf("connect %s error %s\r\n", addr, acl::last_serror());
return false;
}
if (handshake(conn) == false)
return false;
acl::websocket ws(conn);
if (send_file(ws, filepath) == false)
return false;
if (read_reply(ws) == false)
return false;
return true;
}
static void usage(const char* proc)
{
printf("usage: %s -h [help] -s server_addr -f filename\r\n", proc);
}
int main(int argc, char* argv[])
{
// 初始化 acl 库
acl::acl_cpp_init();
acl::log::stdout_open(true); // 日志输出至标准输出
int ch;
acl::string addr, filename;
while ((ch = getopt(argc, argv, "hf:s:")) > 0)
{
switch (ch)
{
case 'h':
usage(argv[0]);
return 0;
case 'f':
filename = optarg;
break;
case 's':
addr = optarg;
break;
default:
break;
}
}
if (addr.empty() || filename.empty())
{
usage(argv[0]);
return 1;
}
upload(addr, filename);
return 0;
}