文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

使用UDP协议实现—翻译服务器

2023-08-31 09:56

关注

目录

前言

1.设计思路:

2.词库设计

3.设计客户端

4.设计服务端

5.编译客户端和服务端

6.测试结果

7.总结


前言

        上一篇文章中,我们使用UDP协议编码完成了一个简单的服务器,实现数据通信,服务器设计出来后目的不仅仅只是实现数据通信,而是根据客户端发过来的请求,实现一定的需求,今天我们要介绍的是当客户端给服务端发送英文单词,然后服务端获取客户端的请求,将翻译结果返回给客户端,通过这样的方式,实现了一款英文翻译服务器。下面我们就一起具体来看看是如何编码完成。

1.设计思路:

如图所示

第一步:启动服务器,然后服务器加载词库

第二步:客户端向服务器,发送请求

第三步:服务器处理请求查找单词,将查找结果返回给客户端

第四步:客户端获取查询结果

2.词库设计

说明:在这里只是简单模拟实现一个词库,主要是实现业务逻辑

dict.txt:

aunt:姨母brother:兄弟cousin:堂兄弟couple:夫妇dad:爸爸daughter:女儿family:家father:爸爸grandchild:孙子granddaughger:孙女grandfather:祖父grandma:外婆grandpa:外公granny老奶奶

3.设计客户端

udpClient.hpp

#pragma once#include #include #include #include #include #include #include #include #include #include #include #include namespace Client{    using namespace std;    class udpClient    {    public:        udpClient(const string &serverIp, const uint16_t serverPort)            : _serverIp(serverIp), _serverPort(serverPort), _sockfd(-1) {}        void initClient()        {            _sockfd = socket(AF_INET, SOCK_DGRAM, 0);            if (_sockfd == -1)            {                cerr << "socket error:" << errno << strerror(errno) << endl;                exit(2);            }        }        void run()        {            struct sockaddr_in server;            memset(&server, 0, sizeof(server));            server.sin_family = AF_INET;            server.sin_addr.s_addr = inet_addr(_serverIp.c_str());            server.sin_port = htons(_serverPort);            while (1)            {                string message;                cout << "请输入你想要翻译的单词:";                getline(cin,message);                //发送请求                sendto(_sockfd, message.c_str(), message.size(), 0, (const struct sockaddr *)&server, sizeof(server));                char buffer[1024];                struct sockaddr_in temp;                socklen_t len = sizeof(temp);                //接受查询翻译结果                size_t n = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&temp, &len);                if (n >= 0)                    buffer[n] = 0;                cout << "翻译的结果为: " << buffer << endl;            }        }    private:        string _serverIp;        int _sockfd;        uint16_t _serverPort;    };}

udpClient.cc:启动客户端

#include"udpClient.hpp"#includeusing namespace Client;static void Usage(string proc){    cout << "\nUsage:\n\t" << proc << " server_ip server_port\n\n";}int main(int argc,char* argv[]){    if(argc != 3)    {        Usage(argv[0]);        exit(1);    }    string serverip = argv[1];    uint16_t serverport = atoi(argv[2]);    unique_ptr uct(new udpClient(serverip,serverport));    uct->initClient();    uct->run();    return 0;}

4.设计服务端

udpServer.hpp

#pragma once#include #include #include #include #include #include #include #include #include #include #include #include namespace Server{    using namespace std;    const static string defaultIP = "0.0.0.0";    enum {USAGE_ERR = 1, SOCKET_ERR, BIND_ERR,OPEN_ERR};    typedef function func_t;    class udpServer    {    public:        udpServer(const func_t& cb,uint16_t port, const string &ip = defaultIP)         :_callback(cb),_port(port),_ip(ip),_sockfd(-1)        {}        void initServer()        {            _sockfd = socket(AF_INET,SOCK_DGRAM,0);            if(_sockfd == -1)            {                cerr<<"socket error:" << errno << strerror(errno) << endl;                exit(SOCKET_ERR);            }            struct sockaddr_in local;            bzero(&local,sizeof(local));            local.sin_family = AF_INET;            local.sin_port = htons(_port);            local.sin_addr.s_addr = htonl(INADDR_ANY);            int n = bind(_sockfd,(struct sockaddr*)&local,sizeof(local));            if(n == -1)            {                cerr<<"bind error:" << errno << strerror(errno) << endl;                exit(BIND_ERR);            }        }        void startServer()        {            char buffer[1024];            for(;;)            {                struct sockaddr_in peer;                socklen_t len = sizeof(peer);                ssize_t s = recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);                if(s)                {                    buffer[s] = { 0 };                    string clientIp = inet_ntoa(peer.sin_addr);                    uint16_t clientPort = ntohs(peer.sin_port);                    string message = buffer;                    cout << clientIp << "[" << clientPort << "]" << message << endl;                    //服务器只负责接受数据,处理方法采用回调的方式交给上层处理                    _callback(_sockfd,clientIp,clientPort,message);                }            }        }        ~udpServer()        {}    private:        uint16_t _port;        string _ip;        int _sockfd;        func_t _callback;    };}

udpServer.cc:启动服务端

#include "udpServer.hpp"#include #include #include using namespace Server;static void Usage(string proc){    cout << "\nUsage:\n\t" << proc << " local_port\n\n";}const string DictTxt = "./dict.txt";unordered_map dict;static bool cutString(string& str,string& s1,string& s2,const string& sep){    auto pos = str.find(sep);    if(pos == string::npos)        return false;    s1 = str.substr(0,pos);    s2 = str.substr(pos + sep.size());    return true;}static void initDict(){    ifstream in(DictTxt,ios::binary);    if(!in.is_open())    {        cerr << "open fail:" << DictTxt << "error" << endl;        exit(OPEN_ERR);    }    string line;    string key,value;    while(getline(in,line))    {        if(cutString(line,key,value,":"))        {            dict.insert(make_pair(key,value));        }    }    in.close();    cout << "load dict success" << endl;}//翻译:void TranslationWord(int sockfd,string clientIp,uint16_t clientPort,string message){    string response_message;    auto iter = dict.find(message);    if(iter == dict.end())         response_message = "unknown";    else         response_message = iter->second;    struct sockaddr_in client;    bzero(&client, sizeof(client));    client.sin_family = AF_INET;    client.sin_port = htons(clientPort);    client.sin_addr.s_addr = inet_addr(clientIp.c_str());    sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr*)&client, sizeof(client));}int main(int argc, char *argv[]){    if (argc != 2)    {        Usage(argv[0]);        exit(USAGE_ERR);    }    //加载词库    initDict();    uint16_t port = atoi(argv[1]);    unique_ptr usvr(new udpServer(TranslationWord,port));    usvr->initServer();    usvr->startServer();    return 0;}

5.编译客户端和服务端

makefile:

.PHONY:allall:udpServer udpClientudpServer:udpServer.ccg++ -o $@ $^ -std=c++11udpClient:udpClient.ccg++ -o $@ $^ -std=c++11.PHONY:cleanclean:rm -f udpServer udpClient

6.测试结果

如图所示:服务端能够准确处理客户端的请求,将翻译查询结果返回给客户端

7.总结

         以上就是使用UDP协议实现的一款翻译服务器,细心的小伙伴也已经发现了,在上面的代码中服务器的任务只是接受请求,然后将请求的数据回调处理,让上层处理业务逻辑,这样的实现方式实现了服务器与业务逻辑代码之间的解耦,如果以后想实现一款别的需求的服务器,只需要更改上层的业务逻辑就可以了。

来源地址:https://blog.csdn.net/qq_65307907/article/details/132164347

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-服务器
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯