如何创建基于udp的客户端和服务端

1.先创建好udpServer.hpp、udpServer.cc、udpClient.hpp、udpClient.cc的框架。

#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <functional>
#include"userManager"
#include<pthread.h>
using namespace std;
const static string defaultip = "0.0.0.0";
// typedef function<void(int,string,uint16_t,string)> func_t;
typedef void (*func_t)(int,string,uint16_t,string);
class udpServer
{
public:
    udpServer(uint16_t port,func_t callback) : _port(port),_callback(callback)
    {}
    void init()
    {}
    void start()
    {}
    ~udpServer() {}

private:
    int _fd;
    uint16_t _port;
    string _ip;
    func_t _callback;
};
#include "udpServer.hpp"
#include <memory>
#include<fstream>
using namespace std;
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        cout << "输入错误,请重新输入" << endl;
    }
    uint16_t port = atoi(argv[1]);
   
    unique_ptr<udpServer> server(new udpServer(port, callback));
    server->init();
    server->start();
    return 0;
}
#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <pthread.h>
using namespace std;
class udpClient
{
    public:
    udpClient(string serverip,uint16_t serverport):_serverip(serverip),_serverport(serverport),_fd(-1)
    {}
    void init()
    {}
    void start()
    {}
    ~udpClient(){}
    private:
    int _fd;
    string _serverip;
    uint16_t _serverport;
    pthread_t reader;//这是后期需要的,看不懂接着往下看就可以
};
#include"udpClient.hpp"
#include<memory>
using namespace std;


 int main(int argc,char* argv[])
 {
    if(argc!=3)
    {
        cout<<"输入错误,请重新输入"<<endl;
    }
    uint16_t port = atoi(argv[2]);
    string ip = argv[1];
    unique_ptr<udpClient> client(new udpClient(ip,port));
    client->init();
    client->start();
}

2.init初始化。

 //udpServer.hpp
void init()
    {
        // 创建套接字返回fd
        _fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_fd == -1)
        {
            cerr << "socket error:" << errno << ":" << strerror(errno) << endl;
            exit(1);
        }
        // 将fd和ip,port进行绑定
        struct sockaddr_in sock;
        sock.sin_family = AF_INET;
        sock.sin_port = htons(_port);
        sock.sin_addr.s_addr = INADDR_ANY;
        int n = bind(_fd, (struct sockaddr *)&sock, sizeof(sock));
        if (n == -1)
        {
            cerr << "bind error:" << errno << ":" << strerror(errno) << endl;
            exit(2);
        }
    }
//udpClient.hpp 
void init()
    {
        _fd = socket(AF_INET,SOCK_DGRAM,0);
        if(_fd == -1)
        {
            cout<<"socket err:"<<errno<<":"<<strerror(errno)<<endl;
            exit(1);
        }
    }

3.start发送、接收数据。

 //udpServer.cc
void callback(int fd, string ip, uint16_t port, string messages)
{
    sockaddr_in client;
    socklen_t len = sizeof(client);
    client.sin_family = AF_INET;
    client.sin_port = htons(port);
    client.sin_addr.s_addr = inet_addr(ip.c_str());
    messages = "服务端的输出结果:"+messages;
    sendto(fd, messages.c_str(), messages.size(), 0,(struct sockaddr *)&client, len);
   
}

//udpServer.hpp
void start()
    {
        char buffer[1024];
        size_t len = sizeof(buffer);
        char writer[1024];
        struct sockaddr_in clientsock;
        socklen_t clientlen = sizeof(clientsock);
        while (1)//服务器的本质就是一个死循环
        {
            size_t n = recvfrom(_fd, buffer, len-1, 0, (struct sockaddr *)&clientsock, &clientlen);
            if (n > 0)
            {
                buffer[n]=0;
                string ip = inet_ntoa(clientsock.sin_addr); // uint32_t->string
                uint16_t port = ntohs(clientsock.sin_port);
                string messages = buffer;
                cout << ip << "[" << port << "]" << "#" << messages << endl;
                 _callback(_fd,ip,port,messages);
            }
           
        }
    }
 //udpCLient.hpp
static void* readroutine(void* args)
    {
        pthread_detach(pthread_self());
        udpClient* c = static_cast<udpClient*>(args);
        sockaddr_in server;
        socklen_t serverlen = sizeof(server);
        while(1)
        {
            char buffer[1024];
            int len = sizeof(buffer);
            size_t n = recvfrom(c->_fd, buffer, len-1, 0, (struct sockaddr *)&server, &serverlen);
            if (n > 0)
            {
                buffer[n]=0;
                cout <<buffer << endl;
            }
        }
    }
    void start(){
        pthread_create(&reader,NULL,readroutine,(void*)this);
        char buffer[1024];
        struct sockaddr_in serveraddr;
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_port = htons(_serverport);
        serveraddr.sin_addr.s_addr = inet_addr(_serverip.c_str());
        while(1)
        {
            cin>>buffer;
            ssize_t n = sendto(_fd,buffer,sizeof(buffer),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
            if(n == -1)
            {
                cout<<"sendto err:"<<errno<<":"<<strerror(errno)<<endl;
            }
        }
    }

完整代码:

udpClient.cc

#include"udpClient.hpp"
#include<memory>
using namespace std;


 int main(int argc,char* argv[])
 {
    if(argc!=3)
    {
        cout<<"输入错误,请重新输入"<<endl;
    }
    uint16_t port = atoi(argv[2]);
    string ip = argv[1];
    unique_ptr<udpClient> client(new udpClient(ip,port));
    client->init();
    client->start();
}

 udpClient.hpp

#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <pthread.h>
using namespace std;
class udpClient
{
    public:
    udpClient(string serverip,uint16_t serverport):_serverip(serverip),_serverport(serverport),_fd(-1)
    {}
    void init()
    {
        _fd = socket(AF_INET,SOCK_DGRAM,0);
        if(_fd == -1)
        {
            cout<<"socket err:"<<errno<<":"<<strerror(errno)<<endl;
            exit(1);
        }
    }
    static void* readroutine(void* args)
    {
        pthread_detach(pthread_self());
        udpClient* c = static_cast<udpClient*>(args);
        sockaddr_in server;
        socklen_t serverlen = sizeof(server);
        while(1)
        {
            char buffer[1024];
            int len = sizeof(buffer);
            size_t n = recvfrom(c->_fd, buffer, len-1, 0, (struct sockaddr *)&server, &serverlen);
            if (n > 0)
            {
                buffer[n]=0;
                cout <<buffer << endl;
            }
        }
    }
    void start(){
        pthread_create(&reader,NULL,readroutine,(void*)this);
        char buffer[1024];
        struct sockaddr_in serveraddr;
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_port = htons(_serverport);
        serveraddr.sin_addr.s_addr = inet_addr(_serverip.c_str());
        while(1)
        {
            cin>>buffer;
            ssize_t n = sendto(_fd,buffer,sizeof(buffer),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
            if(n == -1)
            {
                cout<<"sendto err:"<<errno<<":"<<strerror(errno)<<endl;
            }
        }
    }
    ~udpClient(){}
    private:
    int _fd;
    string _serverip;
    uint16_t _serverport;
    pthread_t reader;
};

 udpServer.cc

#include "udpServer.hpp"
#include <memory>
#include<fstream>
using namespace std;
// 处理方式1:翻译软件
unordered_map<string, string> dictmap;
void to_map(string messages);
// 1.打开文件,按行读取
void openfile()
{
    ifstream in;
    in.open("dict.txt",std::ios::binary);
    if(in.is_open())
    {
        std::string line;
        while(getline(in,line))
        {
            to_map(line);
        }
    }
}
// 2.按行存到map中
void to_map(string messages)
{
    size_t pos = messages.find(":");
    dictmap.insert(make_pair(messages.substr(0, pos), messages.substr(pos + 1)));
}
// 3.接收传来的message并通过map查询
void translate(int fd, string ip, uint16_t port, string messages)
{
    sockaddr_in client;
    socklen_t len = sizeof(client);
    client.sin_family = AF_INET;
    client.sin_port = htons(port);
    client.sin_addr.s_addr = inet_addr(ip.c_str());
    if (dictmap.find(messages) != dictmap.end())
    {
        cout<<"messages:"<<dictmap[messages].c_str()<<endl;
        sendto(fd, dictmap[messages].c_str(), dictmap[messages].size(), 0,(struct sockaddr *)&client, len);
    }
    else
    {
        string mes = "无结果";
        sendto(fd, mes.c_str(), mes.size(),0, (struct sockaddr *)&client, len);
    }
}
// 4.test测试文件有没有加载成功
void printdict()
{
    for (auto e : dictmap)
    {
        cout << e.first << ":" << e.second << endl;
    }
}
// 处理方式2:群聊
onlineUser onlineuser;
void group_chat(int fd, string ip, uint16_t port, string messages)
{
    // 将客户端的信息传进来
    onlineuser.addOnlineUser(ip, port);
    onlineuser.broadcastMessage(fd, ip, port, messages);
}
// 处理方式3:最简单版本收到什么原样返回
void callback(int fd, string ip, uint16_t port, string messages)
{
    sockaddr_in client;
    socklen_t len = sizeof(client);
    client.sin_family = AF_INET;
    client.sin_port = htons(port);
    client.sin_addr.s_addr = inet_addr(ip.c_str());
    messages = "服务端的输出结果:"+messages;
    sendto(fd, messages.c_str(), messages.size(), 0,(struct sockaddr *)&client, len);
   
}
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        cout << "输入错误,请重新输入" << endl;
    }
    uint16_t port = atoi(argv[1]);
    //openfile();
    //printdict();
    unique_ptr<udpServer> server(new udpServer(port, callback));
    server->init();
    server->start();
    return 0;
}

 udpServer.hpp

#pragma once
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <functional>
#include"userManager"
#include<pthread.h>
using namespace std;


const static string defaultip = "0.0.0.0";
// typedef function<void(int,string,uint16_t,string)> func_t;
typedef void (*func_t)(int,string,uint16_t,string);
class udpServer
{
public:
    udpServer(uint16_t port,func_t callback) : _port(port),_callback(callback)
    {
    }
    void init()
    {
        // 创建套接字返回fd
        _fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_fd == -1)
        {
            cerr << "socket error:" << errno << ":" << strerror(errno) << endl;
            exit(1);
        }
        // 将fd和ip,port进行绑定
        struct sockaddr_in sock;
        sock.sin_family = AF_INET;
        sock.sin_port = htons(_port);
        sock.sin_addr.s_addr = INADDR_ANY;
        int n = bind(_fd, (struct sockaddr *)&sock, sizeof(sock));
        if (n == -1)
        {
            cerr << "bind error:" << errno << ":" << strerror(errno) << endl;
            exit(2);
        }
    }

    void start()
    {
        char buffer[1024];
        size_t len = sizeof(buffer);
        char writer[1024];
        struct sockaddr_in clientsock;
        socklen_t clientlen = sizeof(clientsock);
        while (1)
        {
            size_t n = recvfrom(_fd, buffer, len-1, 0, (struct sockaddr *)&clientsock, &clientlen);
            if (n > 0)
            {
                buffer[n]=0;
                string ip = inet_ntoa(clientsock.sin_addr); // uint32_t->string
                uint16_t port = ntohs(clientsock.sin_port);
                string messages = buffer;
                cout << ip << "[" << port << "]" << "#" << messages << endl;
                 _callback(_fd,ip,port,messages);
            }
           
        }
    }
    ~udpServer() {}

private:
    int _fd;
    uint16_t _port;
    string _ip;
    pthread_t writer;
    func_t _callback;
};

 makefile

cc=g++
.PHONY:all
all:udpClient udpServer

udpClient:udpClient.cc
	$(cc) -o $@ $^ -std=c++11 -lpthread
udpServer:udpServer.cc
	$(cc) -o $@ $^ -std=c++11 -lpthread
.PHONY:clean
clean:
	rm -f udpClient udpServer

以下是拓展的代码:

群聊:userManager

#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <strings.h>
#include <netinet/in.h>
#include <functional>
using namespace std;
class User
{
public:
    User(std::string ip, uint16_t port) : _ip(ip), _port(port)
    {
    }
    ~User()
    {
    }

    std::string _ip;
    int16_t _port;
};
class onlineUser
{
public:
    onlineUser() {}
    ~onlineUser() {}
    void addOnlineUser(std::string ip, uint16_t port)
    {
        string id = ip + "[" + std::to_string(port) + "]#";
        onUser.insert(make_pair(id, User(ip, port)));
    }
    void offOnlineUser(std::string ip, uint16_t port)
    {
        string id = ip + "[" + std::to_string(port) + "]#";
        onUser.erase(id);
    }
    void broadcastMessage(int sockfd, const string &ip, const int16_t &port, const string &messages)
    {
        string id = ip + "[" + std::to_string(port) + "]#";
        for (auto &user : onUser)
        {
            if (user.first != id)
            {
                sockaddr_in usersock;
                usersock.sin_family = AF_INET;
                usersock.sin_port = htons(user.second._port);
                usersock.sin_addr.s_addr = inet_addr(user.second._ip.c_str());
                string sendmessage = id + messages;
                sendto(sockfd, sendmessage.c_str(), sendmessage.size(), 0, (struct sockaddr *)&usersock, sizeof(usersock));
            }
        }
    }

private:
    unordered_map<string, User> onUser;
};

 字典:dict.txt

hello:你好
why:为什么
so:所以
then:然后

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/934403.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TCP 2

文章目录 Tcp状态三次握手四次挥手理解TIME WAIT状态 如上就是TCP连接管理部分 流量控制滑动窗口快重传 延迟应答原理 捎带应答总结TCP拥塞控制拥塞控制的策略 -- 每台识别主机拥塞的机器都要做 面向字节流和粘包问题tcp连接异常进程终止机器重启机器掉电/网线断开 Tcp状态 建…

ChatGPT Pro是什么

ChatGPT Pro 和 ChatGPT Plus 的区别主要体现在功能范围、适用场景和目标用户上。 ChatGPT Plus 功能 • 价格&#xff1a;20美元/月。 • 目标用户&#xff1a;针对个人用户设计。 • 主要特点&#xff1a; • 在高峰期响应速度更快。 • 使用高级模型&#xff08;如 GPT-4…

【开源免费】基于Vue和SpringBoot的桂林旅游景点导游平台(附论文)

博主说明&#xff1a;本文项目编号 T 079 &#xff0c;文末自助获取源码 \color{red}{T079&#xff0c;文末自助获取源码} T079&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

C++ day3——C++核心

作业&#xff1a; 整理思维导图 2、整理课上代码 3、把课上类的三个练习题的构造函数写出来 1、定义一个矩形类Rec #include <iostream>using namespace std; class Rec {const int length;int width; public:Rec(int length,int width):length(length),width(width)…

目前Java后端就业前景到底怎么样?

很多人都说今年对于IT行业根本没有所谓的“金三银四”“金九银十”。在各大招聘网站或者软件上不管是大厂还是中小公司大多都是挂个招聘需求&#xff0c;实际并不招人&#xff1b;在行业内的程序员基本都已经感受到了任老前段时间口中所谓的“寒气”。 虽然事实确实是如此&…

倚光科技助力自由曲面设计与加工

近年来&#xff0c;自由曲面因其在光学、汽车、航空航天等领域的广泛应用&#xff0c;受到设计师和工程师的高度关注。自由曲面作为一种具有更高自由度的非球面透镜&#xff0c;能够在光学系统中实现更加精确的光线控制&#xff0c;优化像差校正&#xff0c;并且在满足功能需求…

算法论文/半监督1——2024最新半监督目标检测综述(CNN和Transformer)全文1.5W字

Semi-Supervised Object Detection: A Survey on Progress from CNN to Transformer 摘要 半监督学习的惊人进步促使研究人员探索其在计算机视觉领域内目标检测任务中的潜力。半监督对象检测 &#xff08;SSOD&#xff09; 利用小型标记数据集和较大的未标记数据集的组合。这…

在Windows 10中使用SSH远程连接服务器(附花生壳操作方法)

SSH 在 linux 中是一种重要的系统组件&#xff0c;用户可以使用 SSH 来远程连接 linux 系统的计算机&#xff0c;或者传输文件。不过在 win10 以前&#xff0c;windows 并不原生支持 SSH&#xff0c;需要借助第三方工具来使用 SSH 功能。而实际上&#xff0c;微软在 2015 年就曾…

自动秒收录程序与自动秒收录网站源码论坛版本下载

自动秒收录程序与自动秒收录网站源码论坛版本下载 随着互联网的快速发展&#xff0c;网站优化已成为众多企业和个人博主提升在线影响力的关键手段。其中&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;作为提升网站排名的核心策略&#xff0c;备受关注。而SEO优化的一个…

在Goland中对goroutine协程断点调试

在Goland中对goroutine协程断点调试 环境: Goland 参考了 chatgpt 的回复 进行断点调试的代码 package mainimport ("fmt""sync""time" )// worker 模拟处理任务 func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // 确保任务完成后…

Sublime Text 64位:前端及全栈开发利器

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;Sublime Text作为一款高效的文本编辑器&#xff0c;在前端网页开发领域受到广泛青睐&#xff0c;特别是其64位版本在处理大型项目和高内存需求的场景下表现出色。编辑器内置Emmet插件&#xff0c;提供代码高亮、…

css矩形样式,两边圆形

废话不多说&#xff0c;代码如下&#xff0c;直接拷贝即可使用&#xff1a; index.vue文件 <template><view class"wrap"><view class"tabs"><view class"tab active"><view class"name">标签</view…

Spring Boot 3 中Bean的配置和实例化详解

一、引言 在Java企业级开发领域&#xff0c;Spring Boot凭借其简洁、快速、高效的特点&#xff0c;迅速成为了众多开发者的首选框架。Spring Boot通过自动配置、起步依赖等特性&#xff0c;极大地简化了Spring应用的搭建和开发过程。而在Spring Boot的众多核心特性中&#xff…

C# MVVM 牛牛的实现依赖注入和MVVM绑定(DependencyInjection+CommunityToolkit)

这段时间在网上发现搜索MVVM数据绑定时&#xff0c;发现很多都是最基本的数据绑定&#xff0c;完全没有考虑依赖注入的问题&#xff0c;这里实现一下我们的方法&#xff0c;让我们的数据绑定和依赖注入都变得简单起来。 安装资源包 首先我们要下载一下资源包DependencyInject…

最小二乘法拟合出二阶响应面近似模型

背景&#xff1a;根据样本试验数据拟合出二阶响应面近似模型&#xff08;正交二次型&#xff09;&#xff0c;并使用决定系数R和调整的决定系数R_adj来判断二阶响应面模型的拟合精度。 1、样本数据&#xff08;来源&#xff1a;硕士论文《航空发动机用W形金属密封环密封性能分析…

05-标准库开发-STM32-IIC协议

七、STM32中IIC协议 概述 Inter-Integrated Circuit (IIC)&#xff0c;也常称为I2C&#xff08;I squared C&#xff09;&#xff0c;是一种同步、串行、半双工通信总线协议。它主要用于连接低速外围设备到处理器或微控制器上&#xff0c;如MPU6050姿态传感器、OLED显示屏、存…

Java版-图论-最小生成树-Prim算法

实现描述 如图&#xff1a; Prim算法的基本思想是从一个顶点开始&#xff0c;逐步构建最小生成树。具体步骤如下&#xff1a; 随机选取一个顶点作为起始点&#xff0c;并将其加入最小生成树的集合中。从该顶点出发&#xff0c;选择一条边连接到其他未被访问的顶点中的最小权…

CSS学习记录09

CSS字体 通用字体族 在CSS中&#xff0c;有5个通用字体族&#xff1a; 衬线字体&#xff08;Serif&#xff09;- 在每个字母的边缘都有一个小的笔触。它们营造出一种形式感和优雅感。无衬线字体&#xff08;Sans-serif&#xff09;- 字体线条简洁&#xff08;没有小笔画&…

GB28181系列一:GB28181协议介绍

我的音视频/流媒体开源项目(github) GB28181系列目录 目录 一、GB28181协议介绍 二、GB28181交互流程 1、注册 2、观看视频 3、控制 4、SDP 5、媒体保活&#xff1a; 6、RTP 7、SIP URL 一、GB28181协议介绍 GB28181使用SIP协议&#xff0c;SIP协议参考我的SIP系列&a…

算法-字符串-3.无重复字符的最长子串

一、思路&#xff1a; 无重复针对唯一的元素首选哈希表方法 在字符串中找出最长字串——动态数组 二、使用的一些常见方法 1.HashMap a.声明 HashMap<Character,Integer> mapnew HashMap(); b.添加元素 map.put(s.charAt(i),i); c.查询是否有对应的元素存在并获取 m…