栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux 套接字编程--UDP 通信

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux 套接字编程--UDP 通信

IP 地址和端口号

IP 地址可以确定网络中的一台主机,端口号可以确定一台主机中的进程。端口号和进程 PID 不同的是,并不是所有进程都要对外提供网络请求,端口号是网络级别的概念,PID 是系统概念。

网络字节序

发送主机通常将发送缓冲区的数据按照从低到高的顺序发出,而接收主机把从网络上接收到的字节依次保存在接收缓冲区中,也是按照从低到高的顺序保存。但是不同主机的字节序可能不同,这就造成数据读取错误。为了解决这个问题,网络协议对网络数据流的字节序做了统一规定。但是在发送 IP 地址和端口号时,仍需要手动转换。

套接字 API

创建套接字 int socket(int domain, int type, int protocol)

所需头文件:


  • 参数说明:
  • domain 协议,如 IPV4,IPV6,本地通信
  • type 传输层提供服务类型:TCP、UDP
  • protocol 如果为 0,将自动推导

本质上,创建套接字和创建文件相同,因此还需要将文件和网络进行关联(绑定)。

绑定套接字 int bind(int fd, const sockaddr* addr, socklen_t len)

所需头文件:


  • 参数说明:
  • fd 文件描述符
  • addr 网络相关信息数据,包含 16 位端口号,32 位 IP 地址
  • len a网络相关信息的长度
    绑定套接字本质上就是将网络相关信息填充到套接字,将文件与网络 IP 和端口号相关联。

服务器程序绑定端口的原因:服务器程序是为了提供服务,需要其他人知道服务的 IP 和端口,并且 bind 之后,不能轻易改变。

发送数据 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)

所需头文件:


  • 函数功能为往接收端发送大小为 len 的消息 buf,函数返回实际发送的数据大小。发送时,需要设置接收方的 IP 和端口。

接收数据 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)

所需头文件:

函数功能为接收大小为 len 的消息并存储到 buf,函数返回实际接收到数据的大小。接收时,无需设置发送方的 IP 和端口。

实现 UDP 通信
// Server
lass UdpServer
{
private:
    std::string ip;
    int port;
    int sockfd;
public:
    UdpServer(std::string _ip, int _port = DEFAULT):ip(_ip),port(_port),sockfd(-1)
    {}
    bool InitUdpServer()
    {
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0) 
        {
            std::cerr << "socket error" << std::endl;
            return false;
        }
        std::cout << "socket create success, sockfd: " << sockfd << std::endl;

        struct sockaddr_in local;
        memset(&local, '', sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port);
        // local.sin_addr.s_addr = INADDR_ANY;
        local.sin_addr.s_addr = inet_addr(ip.c_str());
        

        if (bind(sockfd, (struct sockaddr*)&local, sizeof(local)) < 0)
        {
            std::cerr << "bind error" << std::endl;
            return false;
        }
        std::cout << "bind suceess" <
        for (;;)
        {
    # define SIZE 128
            char buf[SIZE] = {0};
            struct sockaddr_in peer;
            socklen_t len;
            ssize_t size = recvfrom(sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr*)&peer, &len);
            if (size > 0)
            {
                buf[size] = 0;
                int port = ntohs(peer.sin_port);
                std::string _ip = inet_ntoa(peer.sin_addr);
                std::cout <<_ip << ":" << port << "#" << buf << std::endl;

                std::string echo_msg = "server get!->";
                echo_msg += buf;
                sendto(sockfd, echo_msg.c_str(), echo_msg.size(), 0, (struct sockaddr*)&peer, len);
            }
            else
            {
                std::cerr << "recvfrom error" << std::endl;
            }
        }
    }
    ~UdpServer()
    {
        if (sockfd >= 0) close(sockfd);
    }
};
// Client
class UdpClient
{
private:
    int sockfd;
    std::string server_ip;
    int server_port;
public:
    UdpClient(std::string _ip, int _port)
        :server_ip(_ip), server_port(_port)
    {}
    bool InitClient()
    {
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0)
        {
            std::cerr << "socket error" << std::endl;
            return false;
        }
        return true;
    }
    void Start()
    {
        std::string msg;
        struct sockaddr_in peer;
        memset(&peer, 0, sizeof(peer));
        peer.sin_family = AF_INET;
        peer.sin_addr.s_addr = inet_addr(server_ip.c_str());
        peer.sin_port = htons(server_port);

        for(;;)
        {
            std::cout << "Please enter#";
            std::cin >> msg;
            sendto(sockfd, msg.c_str(), msg.size(), 0, (struct sockaddr*)&peer, sizeof(peer));

            char buf[128];
            struct sockaddr_in temp;
            socklen_t len = sizeof(temp);
            ssize_t size = recvfrom(sockfd, buf, sizeof(buf)-1, 0, (struct sockaddr*)&temp, &len);
            if (size > 0)
            {
                buf[size] = '';
                std::cout << buf << std::endl;
            }
        }
    }

    ~UdpClient()
    {
        if (sockfd >= 0) close(sockfd);
    }
};
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/973326.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号