#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; }