以udp协议创建通信服务器

这篇具有很好参考价值的文章主要介绍了以udp协议创建通信服务器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概念图

以udp协议创建通信服务器,udp,服务器,网络协议

 创建服务器让A,B主机完成通信。

认识接口

socket

以udp协议创建通信服务器,udp,服务器,网络协议

 返回值:套接字,你可以认为类似fd

参数:

  1. domain->:哪种套接字,常用AF_INET(网络套接字)、AF_LOCAL(本地套接字)
  2. type->:发送数据类型,常用 SOCK_DGRAM(以数据报式发送)
  3. protocol->:一般填0,自动推导类型或者IPPROTO_UDP、IPPROTO_TCP。

创建一个套接字,类似创建一个文件标识符fd。

先介绍些结构体类型

struct sockaddr
struct sockaddr_in
struct sockaddr_un

_in结构体中保存的是ip\port数据,而_un中保存的则是本地的数据

以udp协议创建通信服务器,udp,服务器,网络协议

udp协议为了本地通信与网络通信同一套接口兼容,所以先将sockaddr_in/_un强转成sockaddr类型传入各个函数,在函数中判断前2个字节类型,来做本地通信或者网络通信。

bind

以udp协议创建通信服务器,udp,服务器,网络协议

将套接字绑定,一般来说套接字绑定都是服务器才会绑定的,客户端一般给操作系统自动分配ip与端口的。

返回值:成功0,失败-1.设置错误码

参数:

  1. sockfd 需要绑定的套接字
  2. sockaddr包含了需要与套接字绑定的ip和端口号。
  3. addrlen该结构体长度。

recvfrom

用来接收数据的接收

以udp协议创建通信服务器,udp,服务器,网络协议

返回值:实际接收数据的长度,-1失败

参数

  1. sockfd:将从该套接字的端口和ip中取得数据
  2. buff:输出型参数,将数据存放到buff中。
  3. len:buff的长度
  4. flags:以状态等待数据,一般填0,阻塞等待数据
  5. src_addr:发送方ip+port结构体数据,输出型参数
  6. 结构体数据长度

sendto

发送数据给某个主机

以udp协议创建通信服务器,udp,服务器,网络协议

返回值:实际发送数据的个数,-1失败

参数

  1. sockfd:将发送方的ip+port发送给对方
  2. buff:输入型参数,将buff中数据发送给对方。
  3. len:buff的长度;
  4. flags:默认发送方式发送
  5. 接收方ip+port结构体数据,根据该参数寻找对于主机
  6. 结构体数据长度

sockaddr_in结构体配套函数

以udp协议创建通信服务器,udp,服务器,网络协议

机器大小端的转换函数。h本地to转

以太网规定,网络传输数据一定是大端方式传输,所以我们的机器无论是大端还是小端,在网络中都会成为大端序列。

以udp协议创建通信服务器,udp,服务器,网络协议

 当是为了人能看的明白,我们的ip地址一般都是以字符串的方式呈现,这样的方式我们称为点分十进制的方式。而且传入为了的ip地址可能需要改序列,所以一批接口出现了。

以udp协议创建通信服务器,udp,服务器,网络协议

这些接口将字符串转为uint32_t或者将uint32_t转为字符串

代码

一份2个主机通过服务器可以聊天的代码

以udp协议创建通信服务器,udp,服务器,网络协议

服务器代码:

server.hpp

#pragma once
#include <cstdio>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include <unordered_map>
using std::cin;
using std::cout;
using std::endl;

class udp_server
{
    typedef int socket_t;
    void ip_type()
    {
        cout << "ip:" << _ip << endl;
        if (_ip == "127.0.0.1")
        {
            cout << "#####本地测试#####" << endl;
        }
        else if (_ip.empty())
        {
            cout << "#####开放全部ip地址#####" << endl;
        }
        else
        {
            cout << "#####指定ip地址#####" << endl;
        }
    }
    void init_server()
    {
        _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (_socket < 0)
        {
            Log(FATAL, "socket get fail!!![%d][%s]\n", __LINE__, __TIME__);
            exit(1);
        }
        struct sockaddr_in ip_port;
        bzero(&ip_port, sizeof(ip_port));
        ip_port.sin_family = AF_INET;
        ip_port.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str());
        ip_port.sin_port = htons(_port);
        if (bind(_socket, (struct sockaddr *)&ip_port, sizeof(ip_port)) < 0)
        {
            Log(FATAL, "bind  fail!!![%d][%s]\n", __LINE__, __TIME__);
            exit(2);
        }
        Log(NORMAL, "udp init success!!![%d][%s]\n", __LINE__, __TIME__);
    }

public:
    udp_server(uint16_t port, std::string ip = "") : _ip(ip), _port(port) {}
    udp_server() {}

    void activate()
    {
        init_server();
        ip_type();
        while (1)
        {
            char buff[1024] = {0};
            // cout<<"buff size: "<<strlen(buff)<<endl;
            struct sockaddr_in client_ip_port;
            socklen_t len = sizeof(client_ip_port);
            //开始等待客户端

            ssize_t end = recvfrom(_socket, buff, sizeof(buff) - 1, 0, (struct sockaddr *)&client_ip_port, &len);
            char retbuff[1024]={0};
            // cout<<"buff size: "<<strlen(buff)<<endl;
            if (end >= 0)
            {
                buff[end] = '\0';
                printf("[%s:%d]clint say# %s\n", inet_ntoa(client_ip_port.sin_addr), ntohs(client_ip_port.sin_port), buff);
                sprintf(retbuff,"[%s:%d]clint say# %s", inet_ntoa(client_ip_port.sin_addr), ntohs(client_ip_port.sin_port), buff);
            }
            else
            {
                Log(WARINNG, "recvfrom Message have fail [%d][%s]\n", __LINE__, __TIME__);
            }
            //处理数据。
            char key[64];
            snprintf(key,sizeof(key),"%s-%u",inet_ntoa(client_ip_port.sin_addr),client_ip_port.sin_port);
            auto it = _users.find(key);
            if(it==_users.end())
            {
                cout<<key<<endl;
                cout<<key<<" :放入客户端"<<endl;
                _users.insert({key,client_ip_port});
            }

            // cout<<"end : "<<end<<endl;
            //反馈
            for(auto&it:_users)
            {
                if(client_ip_port.sin_addr.s_addr==it.second.sin_addr.s_addr)
                {
                    continue;
                }
                sendto(_socket, retbuff, sizeof retbuff, 0, (struct sockaddr *)&(it.second), sizeof(it.second));
            }
            Log(Debug, "sendto Message have fail [%d][%s]\n", __LINE__, __TIME__);
        }
    }

private:
    socket_t _socket;
    std::string _ip;
    uint16_t _port;
    std::unordered_map<std::string, struct sockaddr_in> _users;
};

server.cpp

#include "server.hpp"
#include <memory>
using std::shared_ptr;
void SERVERUER()
{
    std::cout<<"./server + ip + port"<<std::endl;
}


int main(int argc,char*argv[])
{
    if(argc==2||argc==3)
    {
        cout<<"argc:"<<argc<<endl;
        if(argc==2)
        {
            in_port_t port=atoi(argv[1]);
            shared_ptr<udp_server> server_ptr(new udp_server(port));
            server_ptr->activate();
        }
        else
        {
            
            in_port_t port=atoi(argv[2]);
            std::string ip=argv[1];
            shared_ptr<udp_server> server_ptr(new udp_server(port,ip));
            server_ptr->activate();
        }
    }
    else
    {
        SERVERUER();
    }
    return 0;
}

客户端代码

client.cpp文章来源地址https://www.toymoban.com/news/detail-688940.html

#include <cstdio>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include <pthread.h>
using std::cin;
using std::cout;
using std::endl;
typedef int socket_t;

void CLIENTUER()
{
    std::cout << "./client + ip + port" << std::endl;
}

void *thread_func(void *ages)
{
    socket_t *_socket = (socket_t*)ages;
    char get_messages[102];
    struct sockaddr_in temp;
    bzero((void *)&temp, sizeof(temp));
    socklen_t len(sizeof temp);
    while (1)
    {
        ssize_t end = recvfrom(*_socket, get_messages, sizeof(get_messages) - 1, 0, (struct sockaddr *)&temp, &len);
        if (end >= 0)
        {
            get_messages[end] = 0;
            std::cout<< get_messages << std::endl;
        }
    }
    return nullptr;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        CLIENTUER();
        exit(1);
    }
    socket_t _socket = socket(AF_INET, SOCK_DGRAM, 0);
    pthread_t tid;
    pthread_create(&tid,nullptr,thread_func,(void*)&_socket);
    std::string messages;
    struct sockaddr_in server_ip_port;
    bzero(&server_ip_port, sizeof(server_ip_port));
    server_ip_port.sin_family = AF_INET;
    server_ip_port.sin_addr.s_addr = inet_addr(argv[1]);
    server_ip_port.sin_port = htons(atoi(argv[2]));
    socklen_t len = sizeof(server_ip_port);

    while (1)
    {
        fflush(stdout);
        std::getline(std::cin, messages);
        sendto(_socket, messages.c_str(), messages.size(), 0, (struct sockaddr *)&server_ip_port, len);
    }
    return 0;
}

到了这里,关于以udp协议创建通信服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • LoRaWAN网关与网络服务器(NS)的通信CUPS 协议介绍

    LoRa Basics™ Station 定期查询 CUPS 服务器以获取更新。该协议是 HTTP/REST,使用Credentials中描述的客户端/服务器身份验证方法。对于每个查询,工作站都会提供有关其当前状态的信息,并接收包含其 LNS 和 CUPS 凭证更新的二进制 blob,以及具有任意更新的通用数据段。 通用数据段

    2024年02月13日
    浏览(48)
  • 为什么说 QUIC 协议是现代化网络通信的未来之路及如何实现QUIC服务器

    😄作者简介: 小曾同学.com,一个致力于测试开发的博主⛽️,主要职责:测试开发、CI/CD 如果文章知识点有错误的地方,还请大家指正,让我们一起学习,一起进步。😊 座右铭:不想当开发的测试,不是一个好测试✌️。 如果感觉博主的文章还不错的话,还请点赞、收藏哦

    2024年04月23日
    浏览(49)
  • UDP服务器—实现数据通信

    目录 前言 1.接口介绍 2.编写服务器 3.编写客户端 4.测试 总结         在这篇文章中为大家介绍如何通过编码实现数据通信,实现思路是根据前面介绍的网络编程函数编写一个服务端和客户端,实现客户端和服务端双方通信 创建套接字 domain:网络通信采用 AF_INET type:提供的

    2024年02月13日
    浏览(43)
  • 使用UDP协议实现—翻译服务器

    目录 前言 1.设计思路: 2.词库设计 3.设计客户端 4.设计服务端 5.编译客户端和服务端 6.测试结果 7.总结         上一篇文章中,我们使用UDP协议编码完成了一个简单的服务器,实现数据通信,服务器设计出来后目的不仅仅只是实现数据通信,而是根据客户端发过来的请求,

    2024年02月13日
    浏览(44)
  • 【Linux后端服务器开发】UDP协议

    目录 一、端口号 二、UDP报头格式 三、UDP的特点 四、UDP协议实现网络聊天群 端口号port标识了一个主机上进行通信的不同的应用程序。 0 ~ 1023:系统端口号,HTTP、FTP、SSH等这些广为使用的应用层协议,它们的端口号都是固定的系统端口号(知名端口号) 1024 ~ 65535:操作系统

    2024年02月16日
    浏览(40)
  • UDP服务器和客户端的创建步骤

    一、创建用户数据报套接字(socket函数): 通信域选择 IPV4网络协议 、套接字类型选择 数据报式 ; 二、填充服务器的网络信息结构体: 1.定义网络信息结构体变量; 2.求出结构体变量的内存空间大小; 3.结构体清零; 4.使用IPV4网络协议; 5.预留给在终端输入的网络字节序

    2024年01月19日
    浏览(42)
  • Unity-UDP-客户端/服务器通信功能

    这里简单实现客户端和服务器,复杂的实现需要和前几篇文章的TCP一样,管理多个链接过来的客户端,这里只有一个。需要自己封装类似listener来管理多个链接过来的设备,每次都缓存ReceiveAsync收到消息的中的RemoteEndPoint地址端口,统一管理发送接收消息。 https://zhidao.baidu.c

    2024年02月11日
    浏览(66)
  • 【网络】UDP网络服务器

    代码的整体逻辑: UDP服务端 :udpServer.cc(服务端的调用),udpServer.hpp(服务端的实现) UDP客户端 :udpClient.cc(客户端的调用),udpClient.hpp(客户端的实现) 服务端:1.初始化服务器 2.启动服务器  作为一款服务器:要有自己的服务端口号uint16_t _port,同时网络服务器需要有对应

    2024年02月08日
    浏览(43)
  • 【网络】UDP网络服务器简单模拟实现

    【网络】UDP网络服务器简单模拟实现 UDP的封装 : UDP网络服务器模拟实现:主要分为makefile文件进行编译 UDP客户端 :udpClient.cc(客户端的调用),udpClient.hpp(客户端的实现) UDP服务端 :udpServer.cc(服务端的调用),udpServer.hpp(服务端的实现) 创建makefile文件: makefile里可以定义变

    2024年02月08日
    浏览(49)
  • 集群服务器通信协议:TIPC简介

    1.TIPC协议简介    TIPC是爱立信公司提出的一种透明进程间通信协议(Transparent Interprocess Communication), 主要适用于高可用(HAL)和动态集群环境. 该软件当前主要由风河(windriver)公司在维护, 主要支持Linux, Solaris 和 VxWorks三种操作系统, 从Linux内核2.6.34开始支持TIPC的最新版本2.0, 不过还

    2024年02月08日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包