[linux C]UDP服务器、客户端程序实现(本地)

1、UDP简介

UDP(User Datagram Protocol)用户数据报协议是一种非面向连接的协议,这种协议并不能保证
我们的网络程序的连接是可靠的,而TCP是面向连接的协议,提供可靠服务。但是相对于TCP而言,UDP实时性较好,适用于高速传输和实时性要求较高的通信中。

2、实现过程

UDP服务器端实现步骤:
1、创建socket,选用SOCK_DGRAM(UDP)
2、bind绑定ip地址和socket
3、使用recvfrom()函数接收客户端数据
(4、使用sendto函数发送数据)
UDP客户端实现步骤:
1、创建socket,选用SOCK_DGRAM(UDP)
2、定义sockaddr_in 结构体变量并初始化
3、使用recvfrom()函数接收客户端数据
相关函数API介绍

int socket(int domain, int type, int protocol);
参数:
	domain:域。
	AF_INET/PF_INET: 网际协议
	AF_UNIX/PF_UNIX:本地协议,可写成AF_LOCAL/PF_LOCAL
	type:类型
		SOCK_STREAM:流式套接字
		SOCK_DGRAM:数据报套接字
	protocol:协议
		一般为0
返回值:
	成功:待连接套接字; 
	失败:-1
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
	sockfd:待连接套接字
	addr:包含本地地址(IP+PORT)的通用地址结构体的指针
	addrlen:地址结构体大小
返回值:
	成功:0;
	失败:-1
备注,通用地址结构体的定义:
struct sockaddr
{
	sa_family_t  sa_family;
	char         sa_data[14];
};

特殊地址结构体 —— IPv4地址结构体:
struct sockaddr_in
{
    u_short sin_family;	// 地址族
    u_short sin_port;	// 端口
    struct in_addr sin_addr;	// IPV4地址
    char sin_zero[8];
};
struct in_addr
{
	in_addr_t s_addr;	// 无符号32位网络地址
};

特殊地址结构体 —— IPv6地址结构体:
struct sockaddr_in6
{
	u_short sin6_family;    	// 地址族
	__be16 sin6_port;     		// 端口
	__be32 sin6_flowinfo;		// 流信息
	struct in6_addr sin6_addr;  // IPv6地址
	__u32 sin6_scope_id;
};

特殊地址结构体 ——UNIX域地址结构体:
struct sockaddr_un
{           
	u_short sun_family;	// 地址族
	char sun_path[108];	// 套接字文件路径
};

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);
接口声明:从UDP套接字接收数据
参数:
	sockfd:UDP套接字
	buf:储存数据缓冲区
	len:缓冲区大小
	flags:接收标志,与函数send的flags完全一致
	src_addr:对端网络地址
	addrlen:地址长度
返回值:
	成功:已接收字节数
	失败:-1

2.1服务器代码

/*
    基于UDP实现的服务器
author:zx
date:2023-3-10
创建服务步骤:
    1、创建socket,选用SOCK_DGRAM(UDP)
    2、bind绑定ip地址和socket
    3、使用recvfrom()函数接收客户端数据
*/
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
int main()
{
    int sockfd;
    int retval;
    if(sockfd == -1)
    {
        printf("sock error\n");
        return -1;
    }
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr =htonl(INADDR_ANY);//任意地址
    serverAddr.sin_port = htons(6565);
    retval = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
    if(retval < 0)
    {
        printf("bind error\n");
        return -1;
    }
        {
            printf("[UDP server]recv form client:%s\n", buf);
        }
        else
        {
            printf("[UDP server] recv error!\n");
            break;
		}
    }
    close(sockfd);
    return 0;
}

2.2客户端代码

/*
    基于UDP实现的客户端
author:zx
date:2023-3-10



创建服务步骤:
    1、创建socket,选用SOCK_DGRAM(UDP)
    2、定义sockaddr_in 结构体变量并初始化
    3、使用recvfrom()函数接收客户端数据
*/

#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
int main()
{
    int sockfd;
    int retval;
    struct sockaddr_in clientAddr;
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);//UDP   
    if(sockfd == -1)
    {
        printf("sock error\n");
        return -1;
    }
    clientAddr.sin_family = AF_INET;
    clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    clientAddr.sin_port = htons(6565);
    char buf[1024] = "hello udp server";
    socklen_t len = sizeof(clientAddr);
    int count = 0;
    while(1)
    {
        sprintf(buf, "hello udp server,count:%d", count++);
        retval = sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&clientAddr, len);
        if(retval > 0)
        {
            printf("[UDP client]send to server:%s\n", buf);
        }
        else
        {
            printf("[UDP client] send error!\n");
            break;
        }
        sleep(2);
    }
    close(sockfd);
    return 0;

}

3、运行结果

客户端
在这里插入图片描述
服务器端
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值