echo客户端的工作原理也很简单:

       1、向服务器端发送一个字符串;

       2、接收服务器的返回信息(如果是echo服务器就会返回发送出去的字符串本身)。

       3、在标准输出中回显服务器返回的信息。

       与ehco服务器类似,我们的echo客户端类也可以从TCPClientSock中派生出来:

C++代码
  1. //Filename AppSock.hpp  
  2.   
  3. #ifndef APP_SOCK_HPP  
  4. #define APP_SOCK_HPP  
  5.   
  6. #include <string>  
  7. #include "SockClass.hpp"  
  8.   
  9. class TCPEchoClient: public TCPClientSock{  
  10. public:  
  11.     TCPEchoClient(  
  12.         const char* server_IP,  
  13.         unsigned short server_port,  
  14.         int pre_buffer_size = 32);  
  15.     ~TCPEchoClient();  
  16.     bool doEcho(const std::string& echo_message) const;  
  17. };  
  18.   
  19. #endif //AppSock.hpp  

       我们的doEcho()接收一个C++风格的字符串(std::string),将返回值设计成bool是出于以下考虑:我们希望与服务器断开连接的信息能反馈到主程序中,并且在断开连接后终止echo客户端的程序。所以,返回true表示仍然与服务器保持连接,否则则已经断开(或者异常)。

C++代码
  1. #include "AppSock.hpp"  
  2.   
  3. TCPEchoClient::TCPEchoClient(  
  4.                 const char* server_IP,  
  5.                 unsigned short server_port,  
  6.                 int pre_buffer_size):  
  7. TCPClientSock(server_IP, server_port, pre_buffer_size)  
  8. {}  
  9.   
  10. TCPEchoClient::~TCPEchoClient()  
  11. {}  
  12.   
  13. bool TCPEchoClient::doEcho(const std::string& echo_message) const  
  14. {  
  15.     if (TCPSend(echo_message.data(), echo_message.size()) < 0) {  
  16.         return false;  
  17.     }  
  18.     size_t total_received_length = 0;  
  19.     while (total_received_length < echo_message.size()) {  
  20.         if (TCPReceive() <= 0) {  
  21.             return false;  
  22.         }  
  23.         std::cout.write(preBuffer, preReceivedLength);  
  24.         total_received_length += preReceivedLength;  
  25.     }  
  26.     std::cout << std::endl;  
  27.     return true;  
  28. }  

       因为我们是先发再收,我们接收前是知道应该收到多少字节的信息的。由于TCP协议对边缘的无保障,我们应该假定是是最不利的情况,也就是一次recv()不能接收完我们需要的数据,所以,如果接收到的字节数小于我们的预期,就再次接收,直到跟我们发送的字符串长度一样。虽然事实上在这种小数据的传输中很难遇到以上所描述的那种情况,但是在网络程序的设计中,应该坚持这样一个基本假设:你永远不知道远程的主机会出什么状况,所以永远以最坏的可能性来设计程序。

       最后是主程序。主程序在标准输入中阻塞等待用于echo的信息,为了避免无限循环,我们也设计一个可以关闭服务器端的命令/exit。这样,输入/exit或者服务器断开都可以导致客户端终止。

C++代码
  1. #include "SockClass.hpp"  
  2. #include "AppSock.hpp"  
  3.   
  4. int main(int argc, char* argv[])  
  5. {  
  6.     unsigned short server_port = 5000;  
  7.     if (argc == 3 && atoi(argv[2]) > 0) {  
  8.         server_port = atoi(argv[2]);  
  9.     }  
  10.       
  11.     WinsockAPI winsockInfo;  
  12.     winsockInfo.showVersion();  
  13.   
  14.     TCPEchoClient echo_client(argv[1], server_port);  
  15.     std::string msg;  
  16.     bool go_on = true;  
  17.     while (msg != "/exit" && go_on == true) {  
  18.         std::cout << "Echo: ";  
  19.         std::getline(std::cin, msg);  
  20.         go_on = echo_client.doEcho(msg);  
  21.     }  
  22.   
  23.     return 0;  
  24. }  
除非特别注明,鸡啄米文章均为原创
转载请标明本文地址:http://www.teaching4real.com/software/456.html
2015年11月4日
作者:鸡啄米 分类:软件开发 浏览: 注册送白菜网:0