在前面几篇博客实现了简单的TCP服务器,最开始我们实现的是单执行流的TCP服务器,之后通过代码测试发现单执行流的TCP服务器无法同时为多个客户端提供服务,于是又转而实现了多执行流的TCP服务器。
在实现多执行流的TCP服务器时,分别演示了多进程和多线程的实现方式,为了进一步优化基于多线程的TCP服务器,最终还将线程池接入到了TCP服务器当中。此时访问TCP服务器的各个客户端,分别由不同的执行流为其提供服务,因此这些客户端能够同时享受服务器提供的服务。
当时我们说过,如果想要让这里的TCP服务器处理其他任务,只需要修改对应的处理函数即可。对应到最终实现的线程池版本的TCP服务器,我们要修改的其实就只是任务类当中的handler方法。下面我们以实现简单的TCP英译汉服务器为例,看看更改后我们的TCP服务器能否正常为客户端提供英译汉服务。
英译汉TCP服务器要做的就是,根据客户端发来的英文单词找到其对应的中文意思,然后将该中文意思作为响应数据发给客户端。
之前我们是以回调的方式处理任务的,当线程池当中的线程从任务队列中拿出一个任务后,会调用该任务对应的Run方法处理该任务,而实际在这个Run方法当中会以仿函数的方式调用handler方法,因此我们只需更改Handler类当中对()的重载函数即可,而其他与通信相关的代码我们一律不用更改。
英译汉时需要根据英文单词找到其对应的中文意思,因此我们需要建立一张映射表,其中英文单词作为映射表中的键值key,而中文意思作为与键值相对应的value,这里可以直接使用C++STL容器当中的unordered_map容器。需要看完整代码的可以关注这个系列的博客。
- class Handler
- {
- public:
- Handler()
- {}
- ~Handler()
- {}
- void operator()(int sock, std::string client_ip, int client_port)
- {
- //only for test
- std::unordered_map
dict; - dict.insert(std::make_pair("blog", "博客"));
- dict.insert(std::make_pair("socket", "套接字"));
-
- char buffer[1024];
- std::string value;
- while (true){
- ssize_t size = read(sock, buffer, sizeof(buffer)-1);
- if (size > 0){ //读取成功
- buffer[size] = '\0';
- std::cout << client_ip << ":" << client_port << "# " << buffer << std::endl;
-
- std::string key = buffer;
- auto it = dict.find(key);
- if (it != dict.end()){
- value = it->second;
- }
- else{
- value = key;
- }
- write(sock, value.c_str(), value.size());
- }
- else if (size == 0){ //对端关闭连接
- std::cout << client_ip << ":" << client_port << " close!" << std::endl;
- break;
- }
- else{ //读取失败
- std::cerr << sock << " read error!" << std::endl;
- break;
- }
- }
- close(sock); //归还文件描述符
- std::cout << client_ip << ":" << client_port << " service done!" << std::endl;
- }
- };
说明一下:
()重载函数当中。代码测试
现在这个TCP服务器就能够给客户端提供英译汉的服务了,客户端发来的单词如果能够在映射表当中找到,那么服务端会将该单词对应发中文意思响应给客户端,否则会将客户端发来的单词原封不动的响应给客户端。
注意: 这里只是想告诉大家,我们可以通过改变这里的handler方法来改变服务器处理任务的逻辑。如果你还想对当前这个英译汉服务器进行完善,可以在网上找一找牛津词典对应的文件,将其中单词和中文的翻译做出kv的映射关系,当服务器启动的时候就可以加载这个文件,建立对应的映射关系,此时就完成了一个网络版的英译汉服务器。