我是靠谱客的博主 微笑鸡翅,最近开发中收集的这篇文章主要介绍网络编程(6)UDP套接字编程(3)UDP echo服务1、UDP echo服务1.2 服务端代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前面概念中简单提到,UDP是无连接的不可靠的数据报协议,非常不同于TCP面向连接的可靠字节流。然而,相比TCP有些场合更适合使用UDP,例如常见的应用程序有:DNS(域名系统)、NFS(网络文件系统)和SNMP(简单网络文件管理系统)等。

根据应用场景,给出不同的UDP服务端代码、客户端代码:
(1)服务端、客户端都接受、发送一次数据
(2)服务端可不断接收客户端的,并能区分多客户端
(3)服务端echo服务,客户端发送并回显

本文讲解第三篇。

1、UDP echo服务

在上一节的基础上,服务端接收来自个客户端的消息,并将接收到的消息发给客户端。客户端仅处理一次对客户端发送、接收消息。

1.1 流程图

echo的服务流程如下:
先启动服务端,服务端创建socket、绑定地址之后,调用recvfrom阻塞等待客户端数据到来。客户端创建socket,直接使用sendto向服务端发送数据,客户端调用recvfrom阻塞等待接收数据。服务端收到数据,打印输出,调用sendto将接收的数据发送到客户端,再次进入等待接收数据循环。客户端收到服务端的回复数据,打印输出,关闭退出。
在这里插入图片描述

1.2 服务端代码

在上一博文"网络编程(6)UDP套接字编程(2)UDP服务端
"基础上,服务端recvfrom之后增加sendto代码。

#include <stdio.h>

#include <sys/socket.h>
#include <arpa/inet.h> // sockaddr_in, inet_addr
#include <unistd.h>    // close
#include <cstring>     

#include <errno.h>

const char *SRV_ADDR = "127.0.0.1";
int SRV_PORT = 8080;

int main()
{
    /// 1、创建socket
    int socket_fd = ::socket(AF_INET, SOCK_DGRAM, 0); // udp
    if (socket_fd == -1){
        printf("%s: create socket failed. %sn", __func__, strerror(errno));
        return 1;
    }
    else{
        printf("%s: create socket (fd = %d) success.n", __func__, socket_fd);
    }

    /// 2、绑定到本地端口
    sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;                                 // IPv4
    //servaddr.sin_addr.s_addr = inet_addr(SRV_ADDR);              //仅支持IPv4
    inet_pton(servaddr.sin_family, SRV_ADDR, &servaddr.sin_addr);  // 新函数,通用IPv4/6
    servaddr.sin_port = htons(SRV_PORT);

    int ret = ::bind(socket_fd, (const sockaddr *)&servaddr, sizeof(servaddr));
    if (ret == -1){
        printf("%s: bind %s:%d failed. %s n", __func__, SRV_ADDR, SRV_PORT,strerror(errno));
        return 1;
    }
    else{
        printf("%s: bind %s:%d success.n", __func__, SRV_ADDR, SRV_PORT);
    }

    /// 3、等待接收和响应
    char buf[1024]; // 发送
             
    sockaddr_in clientaddr;
    socklen_t   socklen = sizeof(clientaddr);
    
    while (1)
    {
        // 接收客户端数据
        int len = ::recvfrom(socket_fd, buf, sizeof(buf), 0, (struct sockaddr *)&clientaddr, &socklen);

        if (len < 0){
            printf("%s: recv failed. err %s n", __func__, strerror(errno));
            break;    
        }
        else{
            // 获取客户端的ip、和port
            char ip[INET6_ADDRSTRLEN];   
            inet_ntop(clientaddr.sin_family, &clientaddr.sin_addr, ip, socklen);
            
            int port = ntohs(clientaddr.sin_port);

            printf("%s: client [%s:%d] recv %2d: %sn", __func__, ip, port, len, buf);
        }

        // 接收到的数据发送给客户端
        len = ::sendto(socket_fd, buf, sizeof(buf), 0, (struct sockaddr *)&clientaddr, socklen);
        if (len < 0){
            printf("%s: send failed. err %s n", __func__, strerror(errno));
            break;
        }
    }

    /// 4、关闭连接
    ::close(socket_fd);
}

1.3 客户端代码

客户端的代码略做修改,增加出错处理,已经在sendto后调用recvfrom接收服务端返回数据。

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>  // sockaddr_in, inet_addr
#include <unistd.h>     // close
#include <cstring>

#include <errno.h>

const char *SRV_ADDR = "127.0.0.1";
int SRV_PORT = 8080;

int main()
{
    /// 1、创建socket
    int socket_fd = ::socket(AF_INET, SOCK_DGRAM, 0); // udp
    if(socket_fd == -1){
        printf("%s: create socket failed.n", __func__);
        return -1;
    }else{
         printf("%s: create socket (fd = %d) success.n", __func__, socket_fd);
    }

    // 2、 发送到服务端
    sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr(SRV_ADDR);
    servaddr.sin_port = htons(SRV_PORT);

    int len ;
    char buf[1024] = "hello sockte!";

    // 发送
    len = ::sendto(socket_fd, buf, strlen(buf), 0, (sockaddr*)&servaddr, sizeof(servaddr));
    if(len < 0){
        printf("%s: send failed. %s n", __func__, strerror(errno));
        return 1;
    }

    // 接收
    //len = ::read(socket_fd, buf, strlen(buf));
    //len = ::recv(socket_fd, buf, strlen(buf), 0);
    len = ::recvfrom(socket_fd, buf, strlen(buf), 0,NULL, NULL); // 同上
    if(len < 0){
        printf("%s: recv failed. %s n", __func__, strerror(errno));
        return 1;
    }
    else{
        printf("recv %2d: %sn", len, buf);
    }

   // 3、关闭退出
   ::close(socket_fd);

1.4 测试

打开服务端后,多次打开客户端,可以看到服务端能够正常工作,结果如下
在这里插入图片描述

最后

以上就是微笑鸡翅为你收集整理的网络编程(6)UDP套接字编程(3)UDP echo服务1、UDP echo服务1.2 服务端代码的全部内容,希望文章能够帮你解决网络编程(6)UDP套接字编程(3)UDP echo服务1、UDP echo服务1.2 服务端代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部