套接字编程2(udp)

服务端

1.创建套接字

    int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sockfd == 0){
        perror("socket error");
        return -1;
    }

2.为套接字绑定地址信息

    //2.为套接字绑定地址信息
    // int bind(套接字描述符, 地址信息, 地址长度)
    struct sockaddr_in addr;//定义IPv4地址结构
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9000);//设置地址端口
    addr.sin_addr.s_addr = inet_addr("192.168.117.135");
    int len = sizeof(addr);
    int ret = bind(sockfd, (struct sockaddr*)&addr, len);
    if(ret < 0){
        perror("bind error");
        return -1;
    }

3.接收数据

        //3.接收数据
        // recvfrom(句柄, 空间, 长度, 标志, 对端地址, 地址长度)
        char buf[1024] = {0};
        struct sockaddr_in paddr;
        int len = sizeof(struct sockaddr_in);
        ret = recvfrom(sockfd, buf, 1023, 0, (struct sockaddr*)&paddr, &len);
        if(ret < 0){
            perror("recvfrom error");
            return -1;
        }
        printf("client say: %s\n", buf);

4.回复数据

        //4.回复数据
        // int sendto(句柄, 数据, 长度, 标志, 对端地址, 地址长度)
        char *data = "热死了~~";
        ret = sendto(sockfd, data, strlen(data), 0, (struct sockaddr*)&paddr, len);
        if(ret < 0){
            perror("sendto error");
            return -1;
        }

5.关闭套接字

    //5.关闭套接字
    close(sockfd);

客户端

  • 封装实现一个udpsocket类
  • 通过实例化的对象调用对应的成员接口可以实现udp客户端或服务端的搭建
class UdpSocket{
    private:
        int _sockfd;
    public:
        UdpSocket()
            :_sockfd(-1){}
        bool Socket(){
            _sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
            if(_sockfd < 0){
                perror("socket error");
                return false;
            }
            return true;
        }
        bool Bind(string &ip, uint16_t port){
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr.s_addr = inet_addr(ip.c_str());
            socklen_t len = sizeof(struct sockaddr_in);
            int ret;
            ret = bind(_sockfd, (struct sockaddr*)&addr, len);
            if(ret < 0){
                perror("bind error");
                return false;
            }
            return true;
        }
        bool Send(string &data, string &ip, int port){
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr.s_addr = inet_addr(ip.c_str());
            socklen_t len = sizeof(struct sockaddr_in);
            int ret = sendto(_sockfd, data.c_str(), data.size(), 0, (struct sockaddr*)&addr, len);
            if(ret < 0){
                perror("sendto error");
                return false;
            }
            return true;
        }
        bool Recv(string *buf, string *ip = NULL, int *port = NULL){
            struct sockaddr_in addr;
            socklen_t len = sizeof(struct sockaddr_in);
            char tmp[4096] = {0};
            int ret = recvfrom(_sockfd, tmp, 4096, 0, (struct sockaddr*)&addr, &len);
            if(ret < 0){
                perror("recvfrom error");
                return false;
            }
            buf->assign(tmp, ret);//自带申请空间拷贝数据
            if(ip != NULL){
                *ip = inet_ntoa(addr.sin_addr);
            }
            if(port != NULL){
                *port = ntohs(addr.sin_port);
            }
            return true;
        }
        bool Close(){
            if(_sockfd != -1){
                close(_sockfd);
            }
            return true;
        }
};

结果演示

此时如果你编译的话就还发现程序报错了!!!
在这里插入图片描述
因为我们这里写的是传入字符串, 但我们实际上传入的"192.168.117.135"属于字符串常量, 不匹配
所以我们只需要给前面加上const修饰就好了.
在这里插入图片描述
这下就没有问题了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
因为我是在同一个主机上同时打开了一个服务端和两个客户端, 所以两个客户端的IP地址都是一样的, 但是你会发现两个客户端的端口是不一样的.
这是因为我们的客户端没有绑定固定的端口, 所以这里的端口是不同的.
此时我们就要思考了, 如果我们在程序里给客户端绑定一个固定的端口会怎么样?
那么, 我们的第二个客户端将运行不起来, 因为第二个客户端要绑定端口的时候, 这个端口已经被第一个客户端给绑定了, 肯定会绑定失败, 程序退出.
所以我们的客户端不推荐绑定地址端口信息, 有要求的情况下才进行绑定

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李憨憨_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值