Linux网络编程——基于UDP协议的简易聊天室

0.关注博主有更多知识

操作系统入门知识合集

目录

1.UDP服务端

1.1消息转发的实现

2.UDP客户端

3.效果展示

1.UDP服务端

使用C、C++混编的方式在Linux环境下实现一个简单的UDP服务端。那么我们先看代码,然后逐步分析:

// udpServer.hpp
#pragma once

#include <string>
#include <iostream>
#include <strings.h>
#include <functional>
/*网络必要的头文件*/
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

/*其他操作系统接口*/
#include <unistd.h>

namespace server
{
    using namespace std;
    enum {SOCKET_ERROR = 1,START_ERROR,BIND_ERROR};
    typedef function<void(int,struct sockaddr_in &,string &)> func_t;
    class udpServer
    {
    public:
        /*服务器不需要绑定任何IP!
         *绑定默认的0.0.0.0即可
         *绑定了一个指定的IP之后,只能接收到指定IP的客户端的数据*/
        udpServer(const func_t &func,const uint16_t &port,const string &ip = defaultIp)
            :_func(func),_port(port),_ip(ip),_socketFd(-1)
        {
            /*以IP协议、数据报的形式打开文件
             *也就是以UDP协议打开网络文件
             *如果打开失败,说明无法进行网络通信,程序退出*/
            _socketFd = socket(AF_INET,SOCK_DGRAM,0);
            if(_socketFd == -1)
            {
                cerr << "socket fail" << endl;
                exit(SOCKET_ERROR);
            }
            cout << "socket success: " << _socketFd << endl; 

            /*以后对网络的I/O的操作就是对网络文件操作
             *但是还没有将该文件绑定IP和端口号,也就是还没有绑定套接字
             *所以现在要绑定套接字*/
            struct sockaddr_in local = getSockaddr_in();
            int n = bind(_socketFd,(struct sockaddr *)&local,sizeof(local));
            if(n == -1)
            {
                cerr << "bind fail" << endl;
                exit(BIND_ERROR);
            }
            /*至此套接字创建工作完成*/
        }
        ~udpServer()
        {}

        void start()
        {
            while(true)
            {
                /*读取客户端发送的数据
                 *并打印出来,相当于服务器后台日志*/
                char buffer[buffer_num];

                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                int n = recvfrom(_socketFd,buffer,sizeof(buffer)-1,0,(struct sockaddr *)&client,&len);
                if(n > 0)
                {
                    buffer[n] = 0;
                    string message = buffer;
                    string clinetIp = inet_ntoa(client.sin_addr);
                    uint16_t clinetPort = ntohs(client.sin_port);

                    cout << clinetIp << "[" << clinetPort << "]# " << message << endl;

                    /*回调*/
                    _func(_socketFd,client,message);
                }
            }
        }
    private:
        /*参与网络通信需要端口号和ip地址
         *端口号是一个2字节的整数
         *ip地址用点分十进制的字符串表示*/
        uint16_t _port;
        string _ip;

        /*以文件的形式打开一个网络文件
         *即使用socket()打开一个网络文件*/
        int _socketFd;

        /*所有对象共享一个默认的IP*/
        static const string defaultIp;
        static const int buffer_num = 1024;

        /*回调函数:服务器要处理的业务逻辑*/
        func_t _func;

        /*获取struct sockaddr结构体*/
        struct sockaddr_in getSockaddr_in()
        {
             struct sockaddr_in local;
            /*初始化sockaddr_in对象
             *并且将端口号、IP地址设置进去
             *我们使用的IP地址是字符串,所以需要转换成整数
             *使用inet_addr()接口,里面自动转换成整数,并且自动大小端字节序*/
            bzero((void *)&local,sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            //local.sin_addr.s_addr = inet_addr(_ip.c_str());
            local.sin_addr.s_addr = INADDR_ANY;
            return local;
        }
    };
    const string udpServer::defaultIp = "0.0.0.0";
} /*namespace server ends here*/

首先我们介绍一下scoket()接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小龙向钱进

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

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

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

打赏作者

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

抵扣说明:

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

余额充值