UDP服务器—实现数据通信

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

目录

前言

1.接口介绍

2.编写服务器

3.编写客户端

4.测试

总结


前言

        在这篇文章中为大家介绍如何通过编码实现数据通信,实现思路是根据前面介绍的网络编程函数编写一个服务端和客户端,实现客户端和服务端双方通信

1.接口介绍

创建套接字

 #include <sys/types.h>         
 #include <sys/socket.h>

 int socket(int domain, int type, int protocol);

domain:网络通信采用AF_INET

type:提供的服务类型,包含TCP流式服务和UDP数据包服务

实现UDP服务器参数设置为SOCK_DGRAM

protocol:采用的协议,一般设置为0,前面的两个参数决定了第三个参数

创建套接字的本质是告诉操作系统要进行网络通信,然后由操作系统在底层维护一个文件缓冲区,创建成功返回该文件描述符,后续数据通信,上层选择将数据放到该文件缓冲区中或者从文件缓冲区中去读数据

返回值:打开的文件描述符

绑定端口号

  #include <sys/types.h>        
  #include <sys/socket.h>

  int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

sockfd : 创建套接字的返回值

struct sockaddr* addr:使用时填充该结构体的字段

a.协议字段

b.端口号

端口号在进行填充的时候需要先进行转换为网络字节序


#include <arpa/inet.h>

uint16_t htons(uint16_t hostshort);

获取对方传输过来的端口号时需要将网络字节序转化为本机

#include <arpa/inet.h>

uint16_t ntohs(uint16_t netshort);

c.IP地址

一般在服务器的实现中IP地址是不需要绑定的

在客户端中发送数据需要填充服务端的IP地址,因为在用户层IP地址是字符串类型,在网络上传输时IP地址是整型数据,所以需要进行转换

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

in_addr_t inet_addr(const char *cp);

需要获取对方网络中传输过来的IP地址需要将整型转换为字符串类型

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

char *inet_ntoa(struct in_addr in);

注:因为是网络通信,所以在填充好字段之后需要在传参的时候强转为sockaddr_in

addrlen:结构体的大小

接受数据

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

sockfd:文件描述符

buf:用户缓冲区

len:用户缓冲区的大小

flags:设置为0表示阻塞式调用

src_addr:输出型参数,用来获取对方的IP地址和port

addrlen:结构体的大小

发送数据

 #include <sys/types.h>
 #include <sys/socket.h>
 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

sockfd:文件描述符

buf:用户缓冲区

len:用户缓冲区的大小

flags:设置为0表示阻塞式调用

dest_addr:填充需要发送对端主机的信息,包含IP地址和port端口号

addrlen:结构体的大小

有了上面这些的这些接口,下面我们就可以正式编写一个客户端和一个服务端了

2.编写服务器

形成makefile

.PHONY:all
all:udpServer udpClient

udpServer:udpServer.cc
	g++ -o $@ $^ -std=c++11
udpClient:udpClient.cc
	g++ -o $@ $^ -std=c++11

.PHONY:clean
clean:
	rm -rf udpServer udpClient

编写服务器:udpServer.hpp

#pragma once
#include <iostream>
#include <string>
#include <strings.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

namespace Server
{
    using namespace std;
    const static string defaultIP = "0.0.0.0";
    enum {USAGE_ERR = 1, SOCKET_ERR, BIND_ERR};
    class udpServer
    {
    public:
        udpServer(uint16_t port, const string &ip = defaultIP) 
        :_port(port),_ip(ip),_sockfd(-1)
        {}
        void initServer()
        {
            //1.创建socket
            _sockfd = socket(AF_INET,SOCK_DGRAM,0);
            if(_sockfd == -1)
            {
                cerr<<"socket error:" << errno << strerror(errno) << endl;
                exit(SOCKET_ERR);
            }
            //2.绑定port和ip
            struct sockaddr_in local;
            bzero(&local,sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = htonl(INADDR_ANY);
            int n = bind(_sockfd,(struct sockaddr*)&local,sizeof(local));
            if(n == -1)
            {
                cerr<<"bind error:" << errno << strerror(errno) << endl;
                exit(BIND_ERR);
            }
        }
        void startServer()
        {
            char buffer[1024];
            for(;;)
            {
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                //peer len:输入,输出型参数:用来保存客户端的ip和port
                ssize_t s = recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
                //打印发送来的数据
                if(s)
                {
                    buffer[s] = { 0 };
                    //inet_ntoa:网络字节序->int  int->点分十进制
                    string clientIp = inet_ntoa(peer.sin_addr);
                    //ntohl:网络字节序->int
                    uint16_t clientPort = ntohs(peer.sin_port);
                    string message = buffer;
                    cout << clientIp << "[" << clientPort << "]" << message << endl;
                }
            }
        }
        ~udpServer()
        {}
    private:
        uint16_t _port;
        string _ip;
        int _sockfd;
    };
}

启动服务器:udpServer.cc

#include "udpServer.hpp"
#include <memory>
using namespace Server;
static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " local_port\n\n";
}
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);
    unique_ptr<udpServer> usvr(new udpServer(port));
    usvr->initServer();
    usvr->startServer();
    return 0;
}

3.编写客户端

编写客户端:udpClient.hpp

#pragma once
#include <iostream>
#include <string>
#include <strings.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

namespace Client
{
    using namespace std;   
    class udpClient
    {
    public:
        udpClient(const string& serverIp,const uint16_t serverPort)
        :_serverIp(serverIp),_serverPort(serverPort),_sockfd(-1) {}
        void initClient()
        {
            //1.创建socket
            _sockfd = socket(AF_INET,SOCK_DGRAM,0);
            if(_sockfd == -1)
            {
                cerr<<"socket error:" << errno << strerror(errno) << endl;
                exit(2);
            }
            //client一定需要bind,服务器只有一个,但是客户端有许多个,所以服务端需要显示的绑定端口号
            //客户端一般不需要自己显示的绑定,而是由os自动形成端口号进行绑定
        }
        void run()
        {
            struct sockaddr_in server;
            memset(&server,0,sizeof(server));
            server.sin_family = AF_INET;
            server.sin_addr.s_addr = inet_addr(_serverIp.c_str());
            server.sin_port = htons(_serverPort);
            string message;
            while(1)
            {
                cout << "请输入:";
                cin >> message;
                //发送数据到客户端
                sendto(_sockfd,message.c_str(),message.size(),0,(const struct sockaddr*)&server,
                sizeof(server));
            }
        }
    private:
        string _serverIp;
        int _sockfd;
        uint16_t _serverPort;
    };
}

启动客户端:udpClient.cc

#include"udpClient.hpp"
#include<memory>
using namespace Client;
static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " server_ip server_port\n\n";
}
int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }
    string serverip = argv[1];
    uint16_t serverport = atoi(argv[2]);
    unique_ptr<udpClient> uct(new udpClient(serverip,serverport));
    uct->initClient();
    uct->run();
    return 0;
}

4.测试

说明:因为本次是在一台主机上,所以为了做测试将IP地址绑定为"127.0.0.1",该IP地址的特点是专门用来在本主机上做测试,称为本地环回,后续在不同主机上通信的时候只需要将IP地址改为对方主机的IP地址即可。

UDP服务器—实现数据通信,udp,服务器,网络协议

 此时我们就可以看到当客户端向服务器发送数据时,服务器收到了数据,并且将数据回显出来

总结

通过上面的编码,使用UDP协议简单实现了一个服务器,可以用来进行数据通信了,是不是感觉很神奇呀,看到这里你就会发现,原来网络通信也并不复杂,和系统内部进程间通信有异曲同工之妙关于网络通信的更多细节,后面再一一为大家介绍,我们下次再见!文章来源地址https://www.toymoban.com/news/detail-649094.html

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

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

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

相关文章

  • 【网络原理】使用Java基于UDP实现简单客户端与服务器通信

    我们用Java实现UDP数据报套接字编程,需要借用以下API来实现 网络编程, 本质上是要操作网卡. 但是网卡不方便直接操作. 在操作系统内核中, 使用了一种特殊的叫做 “socket” 这样的文件来抽象表示网卡. 因此进行网络通信, 势必需要先有一个 socket 对象. DatagramSocket 是UDP Socket,

    2024年03月11日
    浏览(58)
  • 【Java网络编程】基于UDP-Socket 实现客户端、服务器通信

    ​ 哈喽,大家好~我是你们的老朋友: 保护小周ღ   本期为大家带来的是网络编程的 UDP Socket 套接字,基于 UDP协议的 Socket 实现客户端服务器通信 ,Socket 套接字可以理解为是,传输层给应用层提供的一组 API,如此程序,确定不来看看嘛~~ 本期收录于博主的专栏 : JavaEE_保

    2024年02月02日
    浏览(64)
  • C# Socket通信从入门到精通(16)——单个同步UDP服务器监听多个客户端C#代码实现

    我们在开发UDP通信程序时,有时候我们也需要开发UDP服务器程序,这个服务器只需要和一个客户端实现通信,比如这篇博文C# Socket通信从入门到精通(15)——单个同步UDP服务器监听一个客户端C#代码实现,但是在实际项目中有的时候需要和多个客户端进行通信,这时和一个客

    2024年01月22日
    浏览(58)
  • C# Socket通信从入门到精通(15)——单个同步UDP服务器监听一个客户端C#代码实现

    我们在开发UDP通信程序时,除了开发UDP客户端程序,有时候我们也需要开发UDP服务器程序,这在实际项目中是经常会遇到的,所以说掌握UDP服务器程序的开发是一项必备的技能,尤其在上位机软件开发领域,掌握UDP服务器程序的开发是走向高级工程师的必经之路,也是面试必

    2024年02月03日
    浏览(54)
  • 以udp协议创建通信服务器

     创建服务器让A,B主机完成通信。  返回值:套接字,你可以认为类似fd 参数: domain-:哪种套接字,常用AF_INET(网络套接字)、AF_LOCAL(本地套接字) type-:发送数据类型,常用 SOCK_DGRAM(以数据报式发送) protocol-:一般填0,自动推导类型或者IPPROTO_UDP、IPPROTO_TCP。 创建一个套接字

    2024年02月10日
    浏览(35)
  • Unity-UDP-客户端/服务器通信功能

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

    2024年02月11日
    浏览(64)
  • 数据通信——传输层(UDP)

    我们上网观看比赛的时候,一旦网络信号出现问题,那可就太难受了,这意味着卡顿的时间内,你会错过这段时间内的内容。这种特性要归功于UDP(User Datagram Protocol)用户数据报协议。     一般的,数据在通过应用层后会到达传输层,如果传输层使用UDP作为封装手段,那么

    2024年02月11日
    浏览(33)
  • 【云服务器】关于UDP/TCP跨平台网络通信服务器无响应的情况及解决办法

    本篇文章仅为了记录我在跨平台进行udp通信的时候遇到的问题及解决办法 进行udp网络通信的时候,我用腾讯云服务器作服务端,windows本机作客户端,在进行连接的时候,当我在客户端向服务端发送消息的时候,服务器端接收不到消息(安全组已经配置) 当执行上述命令出现

    2024年02月10日
    浏览(43)
  • UDP数据报网络编程(实现简单的回显服务器,客户端)

           回显服务器表示客户端发的是啥,服务器就返回啥,主要是为了熟悉UDP数据报网络编程的基本步骤         对于程序的所有分析都写到了代码上 当我们用idea实现了上面的代码后可以通过idea如何开启多个客户端(一个代码开启多个客户端运行)来检验多个客户端向

    2024年02月13日
    浏览(58)
  • 【网络编程】基于UDP数据报实现回显服务器/客户端程序

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得,欢迎大家在评论区交流讨论💌 前言 我们如果想让应用程序进行网络通信的话,就需要调用传

    2024年02月04日
    浏览(51)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包