Linux应用编程---14.UDP服务器、客户端编程

Linux应用编程—14.UDP服务器、客户端编程

​ 之前有介绍过UDP是一种无连接、尽最大努力交付、面向报文的协议。应用层交给UDP多长的报文,UDP就照样发送。Linux下UDP属于数据报socket。数据报socket流程图如图1所示:

在这里插入图片描述

图1 数据报socket流程图

​ 新引入的函数recvfrom()作用是在一个数据报socket上接收数据。函数原型为ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);函数调用需要包含头文件sys/socket.h。参数1是之前的socket()返回的sockfd文件描述符;参数2buffer是接收数据缓存地址;参数3len是缓存地址大小;参数4flags是一个位掩码,决定了socket特定的I\O特性,可以写入默认值0;参数5src_addr和addrlen是用来获取或指定和它通讯的socket的地址。如果不关心发送者的地址,可以写入NULL。

​ 函数sendto()作用是在一个数据报上发送数据。函数原型为ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen);该函数的dest_addr与addrlen参数指定了数据要发送到的目标socket。

14.1 UDP编程实战

​ 基于UDP编写客户端与服务器的代码,服务器在while(1)中调用recvfrom()函数接收来自客户端的数据报并且打印。客户端在运行后,发送一条字符串“Hi, I’m client!”。

​ 服务器代码如下所示:

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

#define FAILE -1
#define SUCCESS 0
#define PORT 8800
#define SIZE 100

int main(void)
{
        int ret = 0;
        int sock_fd, client_sockfd = 0;
        int addr_len = sizeof(struct sockaddr);
        char str[SIZE];
        struct sockaddr_in my_sockaddr, client_addr;

        my_sockaddr.sin_family = AF_INET;
        my_sockaddr.sin_port = htons(PORT);
        my_sockaddr.sin_addr.s_addr = INADDR_ANY;

        sock_fd = socket(AF_INET, SOCK_DGRAM, 0);

        if(sock_fd == FAILE)
                perror("socket.");

        ret = bind(sock_fd, (struct sockaddr *)&my_sockaddr, addr_len);

        if(ret == FAILE)
                perror("bind.");

        while(1)
        {
                printf("Server is waiting for client to connect:\n");
                ret = recvfrom(sock_fd, str, SIZE, 0, (struct sockaddr *)&client_addr, &addr_len);
                if(ret == FAILE)
                        perror("recvfrom.");
                printf("Server receive from client: %s\n", str);
        }

        close(sock_fd);
 
        return 0; 
}

​ 编译出可执行文件SERVER,如果没有收到客户端的数据报,则阻塞获取。

​ 客户端代码如下所示:

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

#define FAILE -1
#define SUCCESS 0
#define PORT 8800
#define SIZE 100

int main(int argc, char * argv[])
{
        int ret = 0;
        int sock_fd = 0;
        struct sockaddr_in server_addr;
        char buff[SIZE];
        char *str = "Hi, I'm Client!";

        if(argc < 2)
        {
                printf("Usage: ./client [server IP address.\n]");
        }

        sock_fd = socket(AF_INET, SOCK_DGRAM, 0);

        if(sock_fd == FAILE)
                perror("socket.");

        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(PORT);
        server_addr.sin_addr.s_addr = inet_addr(argv[1]);

        strcpy(buff, str);

        printf("Client sends to server %s\n", buff);

        ret = sendto(sock_fd, buff, SIZE, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));

        close(sock_fd);

        return 0;
}

​ 编译出可执行文件 CLIENT。运行SERVER后,通过指令ifconfig查看虚拟机IP,然后运行./CLIENT 192.168.20.129。运行结果如下:

image-20221221154722157

图2 运行结果

14.2 总结

​ UDP是无连接、尽最大努力交付、面向报文的通讯协议。UDP编程时,相对TCP简单,少了几个步骤。UDP编程使用socket 数据报,在建立socket时需要将流socket—SOCK_STREAM改为数据报socket—SOCK_DGRAM。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值