Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >初识网络 · udp的基本使用

初识网络 · udp的基本使用

作者头像
_lazy
发布于 2025-04-08 00:38:48
发布于 2025-04-08 00:38:48
8000
代码可运行
举报
文章被收录于专栏:Initial programmingInitial programming
运行总次数:0
代码可运行

前言:

在本文的这个系列,会涉及到不同协议的基本使用到背后的原理机制,那么从一开始我们先实操,比如我们先尝试编写一款具有回显功能的Udp服务器,再尝试对它加一点业务,最后,我们甚至可以使用多线程部分进行服务器的一个升级。

用到多线程的部分比如我们要写一个群聊服务器,像微信的群聊那样,每个人都可以收发消息,当然了,这是后话了,这个的基础建立在了多线程的基础之上,所以我们着重点还是在udp协议本身的使用。

那么本文将会尝试编写两款udp服务器,一个是具有回显功能的udp服务器,一个是带一点点业务的udp服务器,比如带翻译功能的那种。

udp_server_v1

正式开始之前,我们如果不知道从哪里开始,那么我们不妨想想C++是一款具有什么特点的语言,它是一门面向对象的语言吧?

那么在udp_server_v1的这个服务器里面,涉及到的对象有谁?

那肯定是:udp服务器本身

所以首当其冲的就是我们直接先来一个udpserver.hpp再说,即我们要封装一个udp服务器的类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class udp
{
};

对于一个服务器来说,当我们通过一个服务器转发消息的时候,这个服务器发生了拷贝会怎么样?是不是会存在消息重复,进而会导致内存的问题等?所以对于一个服务器来说,最重要的一个点就是不能进行拷贝。

那么让这个类不能进行拷贝有很多种做法,一种是我们可以私有它的拷贝,私有它的operator==,另一种是我们可以通过让它继承不能发生拷贝的类,比如nocopy这个类,这个类的拷贝和赋值都被私有了。

那么第一个问题:如果禁止拷贝? 就完美的解决了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once

class nocopy
{
public:
    nocopy(){}
    ~nocopy(){}
    nocopy(const nocopy&) = delete;
    const nocopy& operator=(const nocopy&) = delete;
};

接下来第二个问题是,咱们的udp服务器应该要有哪些成员变量?或者说咱们udp这个对象应该具备哪些属性

首先,对于网络通信来说,就是通过创建了socket套接字,通过socket接口返回了对应的文件fd,我们才得以通信,那么对于服务器来说,知道对应的fd是必不可少的,这是第一个属性了,通信的时候知道了对应的fd,有了fd之后,我们不妨想想什么是真正的socket?

在网络的基础概念中我们提及了网络通信实际上是两个进程在通信,那么我们确认两个进程的唯一标准就是对应的端口号加对应的主机Ip地址。

所以咱们的服务器应该要有的属性还要有port 和 std::string ip,可是事实真的如此吗

实际上咱们的服务器并不需要特定的Ip地址,咱们的服务器填充对应的sockaddr_in的信息的时候,如果我们指定了特定的ip地址,那么也就代表咱们这个服务器它只能接收特定地址的数据,但是如果咱们的本机具有多个ip呢?

那么数据的目的地址不管是A还是B还是C,咱们是不是都可以接收了?所以一般对于服务器的信息填充,咱们一般设置为0,到后面使用的就是对应的宏了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static const int gsockfd = -1;
static const uint16_t gport = 8888;

class udpserver
{

public:
    udpserver(int sockfd = gsockfd,uint16_t port = gport)
        : _isrunning(false),_sockfd(sockfd), _port(port)
    {
    }

    ~udpserver()
    {
        if(_sockfd < 0) ::close(_sockfd);
    }

private:
    uint16_t _port;
    int _sockfd;
    /* std::string _serverip;  server端不需要ip */
    bool _isrunning;
};

到了这里,咱们对于udpserver的大体框架咱们就清楚了。

那么对于一个服务器来说,一般涉及到的就是初始化服务器和启动对应的服务,比如咱们这里的服务就是回显对应的字符串。

那么我们先考虑第一个问题,我们应该如何初始化咱们的服务器

对于初始化服务器来说,咱们可以简单的分为这么几步,首先我们要创建对应的套接字,接着是填充对应的服务器信息,最后是bind套接字和对应的服务器信息,对于udp来说,它本身是比较简单的,所以初始化服务器来说,也是比较简单的。

首先,创建对应的套接字我们使用的是socket:

它涉及到的头文件是sys/types.h sys/socket.h,其中有三个参数,分为是domain type protocol,对于第一个参数来说,它表示我们选择什么协议,我们这里选择IPv4的协议,对应的就是AF_INET。对于第二个参数来说,我们因为使用的是UDP协议,所以我们往下看我们会看到这么一句话:

翻译过来就是无连接的,不可靠传输。这实际上对应上了udp的特点。所以第二个类型参数我们选择这个。第三个参数我们直接传0就行,咱们暂时不管。

到这里咱们的套接字创建就好了,因为实际上返回的是文件描述符,而在底层实现中,文件描述符是没有负数的,所以一旦创建失败,它就会返回-1,我们可以通过返回值来判断是否创建成功了。

接着就是服务器信息的查询,这里我们唯一要注意一个点就是主机转网络以及对于服务器本身结构体信息的先清空再填充。清空的时候如果我们清空错了是有可能导致后面的sin_family出错的等。

这里我们简单认识一下scokaddr_in结构体吧,它就是我们要认识的结构体:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/* Structure describing an Internet socket address.  */
struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;			/* Port number.  */
    struct in_addr sin_addr;		/* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr)
			   - __SOCKADDR_COMMON_SIZE
			   - sizeof (in_port_t)
			   - sizeof (struct in_addr)];
  };

这是它的源文件定义,我们看in_port_t sin_port,这实际上就是对应的端口号,我们再转到in_port_t的定义也没啥用,实际上就是一个16位的整数,sin_addr就比较神奇了,它实际上是一个ip地址,但是这个Ip地址再次被封装了起来,使用的是in_addr:

当我们进到in_addr的里面,会发现这个结构体只有一个内容,就是32位整数的数据,也就是4字节的数据这是。

有了对应的ip和Port,我们还有一个对应的地址簇,当我们转到它的定义里面去的时候,会发现里面这是一个简单的宏定义,其中使用到了我们在C语言阶段学习的连接符##,这里其实就是简单定义了一个sa_family_t类型的sin_family参数,我们不管那么多,用的时候我们直接填充就可以了。

以上是填充的基本认识。

填充完毕,也就是我们具备了对应的socket套接字和服务器对应的结构体,光有那可不行,我们需要把这两个bind起来,就像我们有锤子和钉子,不一起使用怎么能订住东西呢?

对于bind函数的使用是:

可以看到bind对应的参数我们都有了,直接使用之后,判断对应的返回值就可以了,那么到了这里,我们的初始化服务器就完成了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 void Initserver()
    {
        // create sockfd
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 别又int
        if (_sockfd < 0)
        {
            std::cout << "sockfd error" << std::endl;
            exit(SOCKFD_ERROR);
        }
        std::cout << "sockfd success: " << _sockfd << std::endl;

        // server imformation
        struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(_port); // htons
        server.sin_addr.s_addr = INADDR_ANY;

        // bind
        socklen_t len = sizeof(server);
        int n = ::bind(_sockfd, (struct sockaddr *)&server, len);
        if (n < 0)
        {
            std::cout << "Bind error" << std::endl;
            exit(BIND_ERROR);
        }
        std::cout << "Bind success" << std::endl;
    }

这里面的宏参数都是笔者自己定义的,这样看起来更系统化一点。

接下来我们要考虑的问题就是服务器初始化结束之后,我们应该如何启动对应的服务

到这里可能有同学就说了,服务嘛,咱们定义一个函数,客户端访问的时候我们就在服务器这里调用这个函数就可以了。

实际上这样是可以的,只不过这种办法丧失了解耦这个近乎完美的功能

为什么这么说呢?因为在初识协议的部分,协议的一个非常大的作用是可以实现分层的解耦问题,比如人与人通信,协议出错了我们可以到对应的层发现并解决问题,如果我们把所有的都糅合在了一起,那不就太乱了吗?

所以我们开发的时候要遵从的一个非常重要的点是高耦合低内聚

那么在服务器这里,我们要实现的就是,服务器能执行方法,但是这个方法是什么它不知道,它只知道调用就可以了。

不过在回显服务器这里,我们暂时不用考虑这么多,这里叭叭叭这么多是实际上是为了给udp_server_v2打基础。

在这里我们启动的服务就是返回收到的字符串,那么势必要用到两个函数:

一个是recvfrom一个是sendto函数,光从名字咱们也能知道这两个函数是干什么用的。

对于recvfrom函数来说,对应的参数分别是套接字,接收缓冲区,接收字节大小,标志位,接收的机器的结构体和对应的大小。

你别看这么多,简单想清楚了写的十分顺溜,我们从客户端那里接收到了消息,消息存放到哪里?从哪个套接字接收?缓冲区是哪个?缓冲区的大小是多大?

这些问题咱们想清楚了,参数那就太简单了。

对于sendto同理。咱这里就不解释了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    void start()
    {
        _isrunning = true;
        while (_isrunning)
        {
            // recvfrom
            char inbuffer[1024];
            struct sockaddr_in clinet;
            socklen_t len = sizeof(clinet);
            ssize_t n = recvfrom(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr *)&clinet, &len);
            if (n < 0)
            {
                perror("recvfrom");
                exit(RECVFORM_ERROR);
            }
            // send
            else
            {
                std::string info = "[lazy_client say]#";
                info += inbuffer;
                std::cout << info << std::endl;

                std::string ans;
                ans += inbuffer;
                ssize_t n = sendto(_sockfd, ans.c_str(), ans.size(), 0, (struct sockaddr*)&clinet, len);
                if(n < 0)
                {
                    std::cout << "sendto error" << std::endl;
                    exit(SENDTO_ERROR);
                }
            }
        }
        _isrunning = false;
    }

那么在消息回显的这个功能这里,咱们只需要做两件事,先收消息,然后发消息就可以了。

对于udpserver.hpp咱们也就基本完成了

接下来就是客户端的编写和服务端的编写

对于服务端来说:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include "udpserver.hpp"
#include <memory>


int main(int args, char* argv[])
{
    if(args != 2)
    {
        std::cout << "parameter num error!!!" << std::endl;
        exit(SERVER_PARAMETER_ERROR);
    }
    
    int _serverport = std::stoi(argv[1]);

    std::unique_ptr<udpserver> usvr = std::make_unique<udpserver>(_serverport); // C++14
    usvr->Initserver();
    usvr->start();

    return 0;
}

老实说,没有什么特别要注意的,不过是我们可以通过智能指针new一个udpserver的实例化出来,然后初始化,启动服务就行。

不过,有意思的是服务器虽然说不需要IP地址,但是它需要自己的端口号,咱们可以自己指定,但是指定的端口号不能特殊了,像什么80端口号,就不是我们能用的了。

而端口号的传入,我们可以使用命令行参数进行参数,同理,客户端是需要的,所以我们在客户端也是都可以这么干的。

对于客户端来说:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

先短暂的打个插曲,这几个头文件,在网络中基本是刚需,所以我们可以简单的记忆一下。

好了,步入整题,对于客户端来说,也就是发个消息而已,不过和服务器一样,它们都有一个共同的点是服务一旦启动了,如果不主动退出就一直运行,所以我们一般来说都是使用while(true)来循环走这个过程。

这里有一个问题,对于服务器来说,服务器需要bind自己的socket和sockaddr_in的信息,换句话说,服务器需要bind套接字和端口号ip那些的关系,客户端是否需要bind呢

答案是肯定的,但是,客户端并不需要显示的bind对应的端口号ip,因为这些都让操作系统给它做了,所以对于客户端要考虑的事儿就是怎么收发消息,那就简单了,用前面的函数就可以了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main(int args, char* argv[])
{
    if(args != 3)
    {
        std::cout << "client parameter error!!!" << std::endl;
        exit(-1);
    }

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd < 0) exit(-2);

    while(true)
    {
        // sendto
        struct sockaddr_in server;
        memset(&server,0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = inet_addr(argv[1]);
        server.sin_port = htons(std::stoi(argv[2]));

        std::string information;
        std::getline(std::cin, information);
        ssize_t n = ::sendto(sockfd, information.c_str(), sizeof(n), 0, (struct sockaddr*)&server, sizeof(server));
        if(n < 0)
        {
            perror("sendto");
            exit(-3);
        }
        // recvfrom
        char inbuffer[1024];
        struct sockaddr_in temp;
        socklen_t len = sizeof(temp);
        ssize_t m = ::recvfrom(sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr*)&temp, &len);
        inbuffer[m] = 0;
        if(m < 0)
        {
            perror("recvfrom");
            exit(-4);
        }
        std::cout << "[lazy_server say]#" << inbuffer;
    }
    return 0;
}

虽然这里比较草率,详细的主要还是在服务器介绍的比较多,这里其实类比一下就可以了。


udp_server_v2

对于v2版本,咱这里就把相关的文件传上来,因为这个版本要注意的也就只有解耦和一点std::bind的使用,所以笔者这里选择上传对应的代码了:

Common.h:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once

enum
{
    SOCKFD_ERROR = 1,
    BIND_ERROR,
    RECVFORM_ERROR,
    SENDTO_ERROR,
    SERVER_PARAMETER_ERROR,
    CLIENT_PARA_ERRROR,
    FSTREAM_ERROR
};

dict.hpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once

#include <unordered_map>
#include <iostream>
#include <fstream>
#include "Common.hpp"

static const std::string sep = ":";

class Dict
{
private:
    void Dict_init()
    {
        // open profiles 
        std::fstream in(_path);
        if(!in.is_open())
        {
            perror("is_open");
            exit(FSTREAM_ERROR);
        }

        // open success
        std::string info;
        while(std::getline(in, info))
        {
            // 定位
            size_t pos = info.find(sep);
            if(pos == std::string::npos) continue; // empty line
            
            // 分割
            std::string key = info.substr(0, pos);
            if(key.empty()) continue; // not complete
            std::string value = info.substr(pos+sep.size());
            if(value.empty()) continue; // not complete

            // 插入
            _dict.insert(std::make_pair(key,value));

        }
        in.close();
    }

public:
    Dict(std::string path = "./dict.txt")
        :_path(path)
    {
        Dict_init();
    }

    std::string Translate(const std::string& word)
    {
        auto iter = _dict.find(word);
        if(iter == _dict.end()) return "Not exist";
        return iter->second;
    }

private:
    std::unordered_map<std::string, std::string> _dict;
    std::string _path;

};

dict.txt

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
apple:苹果
banana:香蕉
cat:dog:book:pen:happy:快乐的
sad:悲伤的
run:jump:teacher:老师
student:学生
car:汽车
bus:公交车
love:hate:hello:你好
goodbye:再见
summer:夏天
winter:冬天

InetAddr.hpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <iostream>


class InetAddr
{
private:
    void ToHost(struct sockaddr_in addr)
    {
        _port = htons(addr.sin_port);    
        _ip = inet_ntoa(addr.sin_addr);
    }

public:
    InetAddr(struct sockaddr_in addr)
        :_addr(addr)
    {
        ToHost(_addr);
    }

    uint16_t Port()
    {
        return _port;
    }

    std::string IP()  
    {
        return _ip;
    }

private:
    struct sockaddr_in _addr;
    uint16_t _port;
    std::string _ip;
};

clientMain.cc

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <unistd.h>
#include <cstring>
#include "Common.hpp"


int main(int args, char* argv[])
{
    if(args != 3)
    {
        std::cout << "client parameter error!!!" << std::endl;
        exit(CLIENT_PARA_ERRROR);
    }

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd < 0) exit(-2);

    while(true)
    {
        // sendto
        struct sockaddr_in server;
        memset(&server,0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = inet_addr(argv[1]);
        server.sin_port = htons(std::stoi(argv[2]));

        std::cout << "[lazy_find]#";
        std::string information;
        std::getline(std::cin, information);
        ssize_t n = ::sendto(sockfd, information.c_str(), sizeof(n), 0, (struct sockaddr*)&server, sizeof(server));
        if(n < 0)
        {
            perror("sendto");
            exit(SENDTO_ERROR);
        }
        // recvfrom
        char inbuffer[1024];
        struct sockaddr_in temp;
        socklen_t len = sizeof(temp);
        ssize_t m = ::recvfrom(sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr*)&temp, &len);
        inbuffer[m] = 0;
        if(m < 0)
        {
            perror("recvfrom");
            exit(RECVFORM_ERROR);
        }
        std::cout << "[lazy_result]#" << inbuffer << std::endl;
        

    }


    return 0;
}

udpserver.hpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <functional>
#include "InetAddr.hpp"
#include "Common.hpp"



static const int gsockfd = -1;
static const uint16_t gport = 8888;

using func_t = std::function<std::string(const std::string&)>;


class udpserver
{

public:
    udpserver(func_t func,int sockfd = gsockfd,uint16_t port = gport)
        : _isrunning(false),_sockfd(sockfd), _port(port),_func(func)
    {
    }

    void Initserver()
    {
        // create sockfd
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 别又int
        if (_sockfd < 0)
        {
            std::cout << "sockfd error" << std::endl;
            exit(SOCKFD_ERROR);
        }
        std::cout << "sockfd success: " << _sockfd << std::endl;

        // server imformation
        struct sockaddr_in server;
        memset(&server, 9, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(_port); // htons
        server.sin_addr.s_addr = INADDR_ANY;

        // bind
        socklen_t len = sizeof(server);
        int n = ::bind(_sockfd, (struct sockaddr *)&server, len);
        if (n < 0)
        {
            std::cout << "Bind error" << std::endl;
            exit(BIND_ERROR);
        }
        std::cout << "Bind success" << std::endl;
    }

    void start()
    {
        _isrunning = true;
        while (_isrunning)
        {
            // recvfrom
            char inbuffer[1024];
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            ssize_t n = recvfrom(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr *)&client, &len);
            if (n < 0)
            {
                perror("recvfrom");
                exit(RECVFORM_ERROR);
            }
            // send
            else
            {
                InetAddr addr(client);

                std::string client_info = addr.IP() + std::to_string(addr.Port());
                
                // std::string info = "[lazy_client find]#";
                printf("[%s:%s]find#", addr.IP().c_str(), std::to_string(addr.Port()).c_str());
                std::cout << inbuffer << std::endl;
                // info += inbuffer;
                // std::cout << info << std::endl;

                // 处理业务
                std::string ans = _func(inbuffer);
                
                ssize_t n = sendto(_sockfd, ans.c_str(), ans.size(), 0, (struct sockaddr*)&client, len);
                if(n < 0)
                {
                    std::cout << "sendto error" << std::endl;
                    exit(SENDTO_ERROR);
                }
            }
        }
        _isrunning = false;
    }

    ~udpserver()
    {
        if(_sockfd < 0) ::close(_sockfd);
    }

private:
    uint16_t _port;
    int _sockfd;
    func_t _func;
    /* std::string _serverip;  server端不需要ip */
    bool _isrunning;
};

serverMain.cc

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include "udpserver.hpp"
#include <memory>
#include <functional>
#include "dict.hpp"

int main(int args, char* argv[])
{
    if(args != 2)
    {
        std::cout << "parameter num error!!!" << std::endl;
        exit(SERVER_PARAMETER_ERROR);
    }
    
    int _serverport = std::stoi(argv[1]);

    Dict dict;
    func_t func = std::bind(&Dict::Translate, dict, std::placeholders::_1);

    std::unique_ptr<udpserver> usvr = std::make_unique<udpserver>(func,_serverport); // C++14
    usvr->Initserver();
    usvr->start();

    return 0;
}

感谢阅读!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-04-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
说出来你可能不相信,云开发 Copilot 一行代码都不写,就能拥有自己的小程序。
你是否曾经设想过,有一天只需简单描述需求,就能生成一个完整的小程序或 Web 应用,甚至连一行代码都无需编写?在如今快速发展的技术浪潮中,低代码开发正在重新定义开发效率,而腾讯云的云开发 Copilot 正是其中的佼佼者。借助 AI 技术,它不仅能够迅速生成应用和页面,还能优化样式、构建复杂组件,大幅降低开发门槛,为开发者带来前所未有的高效体验。今天,让我们一起深入体验云开发 Copilot 的强大功能,见证从灵感到实现的无缝衔接。
不惑
2024/11/27
7556
说出来你可能不相信,云开发 Copilot 一行代码都不写,就能拥有自己的小程序。
云开发 Copilot | 如何借助AI,零代码生成一个内置混元的小程序
对于我这个后端开发来说,一直都有着学习前端的梦想,确实也一直在努力着。奈何前端技术这几年发展太快。后来在去年底,终于抓住了前端技术的小尾巴,学完了vue3、Element Plus、Pinia、vue-router等一系列前端技术。
叫我阿柒啊
2024/12/05
7547
云开发 Copilot | 如何借助AI,零代码生成一个内置混元的小程序
云开发 Copilot |快速玩转AI 开发辅助工具
云开发 Copilot是云开发推出的一款 AI 开发辅助工具,可以帮助用户快速生成多种类型的应用功能,包括低代码应用、页面、组件、数据模型、CMS 内容等,帮助开发者快速构建自己的小程序、web 等云开发应用。 可以帮助用户加快开发效率,提升开发体验。
六月暴雪飞梨花
2024/12/09
84713
云开发 Copilot |快速玩转AI 开发辅助工具
AI智能体应用发布篇(公众号/小程序)
之前在《教你 3 分钟搭建 AI 助手,超 Easy!》让大家快速搭建了微信云开发的AI智能体Web版和H5版。
腾讯云开发TCB
2024/06/24
7930
AI智能体应用发布篇(公众号/小程序)
用三行代码将DeepSeek 接入小程序| 腾讯云开发官方指南
随着 DeepSeek 近期的爆火,有越来越多的小程序开发者也想将自己的小程序接入 DeepSeek,实现智能对话、文本生成等功能,这篇文章就教大家如何通过腾讯云开发这个平台来快速接入 DeepSeek。
腾讯云开发TCB
2025/02/13
8.1K8
用三行代码将DeepSeek 接入小程序| 腾讯云开发官方指南
🚀「云开发与 AI」应用实战:如何快速打造一款AI小程序?
嘿,大家好!🌞今天我们来聊聊一个特别有趣又实用的话题——如何用云开发来快速开发一款AI小程序!如果你也对AI感兴趣,又想动手实践一下,来一场技术与创意的碰撞,那这篇文章一定能带你一步步实现。我们将从技术选型开始,一路带你走到项目上线,让你快速拥有一款属于自己的AI小程序。快让大脑飞速运转起来,直奔主题吧!🤖
bug菌
2024/11/13
4170
​云开发 X 涂鸦:当小程序遇见物联网IoT,几行代码搞定智能插座控制
在 5G 热潮的推动下,与其紧密结合的物联网(IoT)正日益成为个人和企业工作生活中的重要组成部分,它为企业和个人带来了操作流程的改进和更好的生活体验,随着人工智能(AI)技术的日趋成熟,IoT 与 AI 的结合愈发紧密,IoT 也被赋予了越来越多的能力和价值。
腾讯云开发TCB
2020/07/20
1.1K0
​云开发 X 涂鸦:当小程序遇见物联网IoT,几行代码搞定智能插座控制
云开发 Copilot实战教程:手把手教你高效开发应用
在当今科技迅猛发展的时代,人工智能(AI)已深度融入我们的工作、学习与生活,为我们带来了诸多便利,其中,云开发 Copilot 作为一款极具创新性的工具,更是备受瞩目。一个很现实的问题也随之而来,如果我们不能学会很好的利用AI进行工作、学习和生活,非常有可能被科技滚滚向前的车轮无情的碾压,基于此本文将对云开发 Copilot 的功能与特点展开详细阐述,并通过手把手的教学方式,引领您深入体验与实践云开发 Copilot,帮助您快速学会如何借助云开发 Copilot 强大的功能,迅速将创意转化为实际的开发成果,满足各类开发需求,进行高效开发,进而提升核心竞争力。
池央
2024/11/23
8272
云开发 Copilot实战教程:手把手教你高效开发应用
云开发 Copilot ——让开发变得更简单
在云开发AI+中,腾讯云提供一系列与 AI 相关的功能,如大模型接入、 Agent 等,帮助开发者为自己的小程序、web 或者应用快速接入 AI 能力,同时也提供了云开发 Copilot,来加速用户的开发,帮助用户更快构建自己的应用。下面博主将会为大家实战使用云开发 Copilot来助力开发。
摆烂小白敲代码
2024/12/01
1.4K2
云开发 Copilot ——让开发变得更简单
手把手教你快速打通微信小店跟小程序
通过自12月19日微信小店开始内测“送礼物”功能以来,业界对微信电商市场的关注度急剧上升。品牌和商家不仅关注如何入驻和运营,还特别关注如何与小程序实现深度融合,为了解决这一需求,云开发也推出微信小店小程序解决方案。
腾讯云开发TCB
2024/12/31
9550
手把手教你快速打通微信小店跟小程序
云开发 AI 实战—基于腾讯云云开发 Copilot快速开发陕西家乡小程序实战
随着云计算技术的快速发展,云开发平台逐渐成为开发者实现快速应用构建和部署的重要工具。云开发平台不仅降低了开发门槛,还通过提供丰富的 API 和服务支持,使得开发者可以更加专注于业务逻辑的实现,而无需过多关注底层基础设施的管理。在这些云开发平台中,腾讯云开发凭借其高效的开发环境和集成的开发工具,成为了众多开发者的首选。
一键难忘
2024/12/19
2130
云开发 AI 实战—基于腾讯云云开发 Copilot快速开发陕西家乡小程序实战
几行代码搞定智能插座控制丨云开发 × 涂鸦
在 5G 热潮的推动下,与其紧密结合的物联网(IoT)正日益成为个人和企业工作生活中的重要组成部分,它为企业和个人带来了操作流程的改进和更好的生活体验,随着人工智能(AI)技术的日趋成熟,IoT 与 AI 的结合愈发紧密,IoT 也被赋予了越来越多的能力和价值。
腾讯云开发TCB
2020/07/21
2.2K0
几行代码搞定智能插座控制丨云开发 × 涂鸦
云端微光,AI启航:低代码开发的智造未来
此前,我的开发体验更多依赖传统手写代码的模式,从搭建环境到构建功能,每一步都耗费大量时间。尽管这个过程对技术提升有帮助,但面对复杂功能需求时,也常感力不从心。
半截诗
2024/11/22
2090
云端微光,AI启航:低代码开发的智造未来
云开发开箱挑战赛
获奖名单公布 S级·最佳作品奖 作者昵称 作者UID 文章标题 评语 陈宇明 2689659 如何快速搭建AI小程序? 内容写的很不错,利用AI agent搭建
腾讯云开发者社区
2024/10/15
22.5K9
不懂代码,你也可以利用AI 开发一个培训网站
作为一个普通人,你可能并不懂得如何编程,写代码。但是你也有点小追求,就想要自己搭建一个网站,怎么办呢?今天我就来教你如何利用云开发 Copilot 来生成一个属于你自己的官网,全程无需编码,你只需要提需求就行。啊?这么牛吗?快来试试吧。
六月的雨在Tencent
2024/12/01
1.2K0
如何快速开发一款AI小程序?
在这个AI时代,结合AI做新的产品或基于你先有的业务加入AI能力,这个是趋势所在,那么如何更快的接入AI能力?接下给大家分享下云开发AI+的集成方式
腾讯云开发TCB
2024/11/07
2290
如何快速开发一款AI小程序?
腾讯云开发实践 | 新手轻松快速构建Web应用
江湖有缘
2024/11/18
2880
腾讯云开发实践 |  新手轻松快速构建Web应用
云开发 Copilot | AI代码生成器
云开发 Copilot 可以解答用户使用过程中的问题,也可以帮助用户开发应用/页面/区块/组件等
小草飞上天
2024/12/12
6231
云开发 Copilot | AI代码生成器
用云开发内容管理 CMS,几步实现一个简易商城
(1)在更新到最新的 微信开发工具 Nightly 版本中,点击云开发控制台,在顶部 Tab 栏中,点击「更多」-「内容管理」。
腾讯云开发TCB
2021/01/05
2.3K6
用云开发内容管理 CMS,几步实现一个简易商城
绝了超简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程序,新手也能快速上手!
今天,我们将为大家带来一个超级简单的教程,教你如何在短短3分钟内,利用腾讯微搭平台,将满血 DeepSeek R1接入到微信、公众号、小程序,打造属于自己的 AI 智能客服,哪怕你是新手也能轻松上手!
测试开发技术
2025/02/28
5721
绝了超简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程序,新手也能快速上手!
推荐阅读
相关推荐
说出来你可能不相信,云开发 Copilot 一行代码都不写,就能拥有自己的小程序。
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验