client: 傳送一個 message ("filename","varname")
server: 將 filename 檔案內的 varname 的數值減一,減到零時回傳 YES, 否則回傳 NO
eq. hello.txt
==================
fab = 100
Oxford = 99
==================
client 傳送 ("hello.txt","Oxford"),server便會將Oxford的值減一 => 98。
這樣的程式,可以用網路 http REST 來做,或是包成網路 API Service 來做(這我不會)
但這種簡單的需求,用 socket 就綽綽有餘了。
寫 socket 程式就需要自己定義 protocol,貪圖方便,我就拿了 boost/asio 的聊天室範例程式來修改 (chat):
http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/examples.html
以下是其 protocol: |size|string|
class chat_message { public: enum { header_length = 4 }; enum { max_body_length = 512 }; chat_message() : body_length_(0) { } const char* data() const { return data_; } char* data() { return data_; } size_t length() const { return header_length + body_length_; } const char* body() const { return data_ + header_length; } char* body() { return data_ + header_length; } size_t body_length() const { return body_length_; } void body_length(size_t length) { body_length_ = length; if (body_length_ > max_body_length) body_length_ = max_body_length; } bool decode_header() { using namespace std; // For strncat and atoi. char header[header_length + 1] = ""; strncat(header, data_, header_length); body_length_ = atoi(header); if (body_length_ > max_body_length) { body_length_ = 0; return false; } return true; } void encode_header() { using namespace std; // For sprintf and memcpy. char header[header_length + 1] = ""; sprintf(header, "%4d", body_length_); memcpy(data_, header, header_length); } private: char data_[header_length + max_body_length]; size_t body_length_; };
既然,protocol 都用此範例了,client & server 當然也用這個範例修改了。
比較麻煩的是,這個範例程式 client & server 都是非同步的方式,非同步在 server 是沒甚麼問題,但 client 使用非同步會很麻煩。需要再 while 迴圈前 Sleep 一秒左右,讓 ioservice 建立連線。
Note:
因為實際使用時,是把 while 中的使用者輸入 cin.getline 部分改成,用參數傳遞的 string,while 迴圈也要拿掉,因此若是非同步的方式,程式馬上就到 c.close(),修改這段程式花了我很大的時間除錯 = ="
boost::asio::io_service io_service; tcp::resolver resolver(io_service); tcp::resolver::query query(argv[1], argv[2]); tcp::resolver::iterator iterator = resolver.resolve(query); chat_client c(io_service, iterator); boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service)); char line[chat_message::max_body_length + 1]; while (std::cin.getline(line, chat_message::max_body_length + 1)) { using namespace std; // For strlen and memcpy. chat_message msg; msg.body_length(strlen(line)); memcpy(msg.body(), line, msg.body_length()); msg.encode_header(); c.write(msg); } c.close(); t.join();
因此我將 client 程式改成同步的方式來執行 (舒服)
boost::asio::io_service io_service; tcp::resolver resolver(io_service); tcp::resolver::query query(argv[1], argv[2]); tcp::resolver::iterator iterator = resolver.resolve(query); tcp::resolver::iterator end; tcp::socket s(io_service); boost::system::error_code error = boost::asio::error::host_not_found; while (error && iterator != end) { s.close(); s.connect(*iterator++, error); } if (error) throw boost::system::system_error(error); char line[chat_message::max_body_length + 1]; strcpy(line,"hello.txt Seg "); chat_message write_msgs_; write_msgs_.body_length(strlen(line)); memcpy(write_msgs_.body(), line, write_msgs_.body_length()); write_msgs_.encode_header(); boost::asio::write(s, boost::asio::buffer(write_msgs_.data(), write_msgs_.length())); chat_message read_msg_; //boost::asio::read(sread_msg_.body(), read_msg_.body_length()), size_t reply_length_header = boost::asio::read(s, boost::asio::buffer(read_msg_.data(), chat_message::header_length)); std::cout << "reply_length_header = " << reply_length_header << std::endl; read_msg_.decode_header(); size_t reply_length_body = boost::asio::read(s, boost::asio::buffer(read_msg_.body(), read_msg_.body_length())); std::cout << read_msg_.body() << std::endl; s.close();
等待時間的問題解決了,接下來要包成 library。
包成 static library 還有些 issue
1. boost library 的 BOOST_ALL_NO_LIB 問題:
我包成 foo.lib 給 test.exe 用但在編譯的時候 linker 竟然還會有問題
LINK : fatal error LNK1104: cannot open file 'libboost_thread-vc100-mt-1_45.lib'
參考下文:
http://stackoverflow.com/questions/4736877/how-to-link-boost-in-a-dependant-static-library
2. VS2010 的 Static Library 無法給 VC6 用
於是我就包成 DLL 的版本
修改下面的 code 包成的 (用 vs2010 建立的 dll wizard 我包失敗 = =)
http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855
於是我的情人節就給了這支程式了! e04!!
補充幾篇參考的文章
回覆刪除將 Lib 打包:
http://stackoverflow.com/questions/2157629/linking-static-libraries-to-other-static-libraries
Linking Error:
http://dev.firnow.com/course/4_webprogram/asp.net/netjs/20090412/164875.html