## Linux UDP编程
udp是用户传输协议,无连接的传输协议,提供不可靠的信息传送服务
UDP(user datagram protocol)的中文叫用户数据报协议,属于传输层。UDP是面向非连接的协议,它不与对方建立连接,而是直接把我要发的数据报发给对方。所以UDP适用于一次传输数据量很少、对可靠性要求不高的或对实时性要求高的应用场景。正因为UDP无需建立类如三次握手的连接,而使得通信效率很高。
一张图来看看TCP和UDP的通信过程以及区别所在
我们来说一说UDP通信的过程:
服务端:
(1)建立套接字文件描述符,使用函数socket(),生成套接字文件描述符。
(2)设置服务器地址和侦听端口,初始化要绑定的网络地址结构。
(3)绑定侦听端口,使用bind()函数,将套接字文件描述符和一个地址类型变量进行绑定。
(4)接收客户端的数据,使用recvfrom()函数接收客户端的网络数据。
(5)向客户端发送数据,使用sendto()函数向服务器主机发送数据。
(6)关闭套接字,使用close()函数释放资源。UDP协议的客户端流程
客户端:
(1)建立套接字文件描述符,socket();
(2)设置服务器地址和端口,struct sockaddr;
(3)向服务器发送数据,sendto();
(4)接收服务器的数据,recvfrom();
(5)关闭套接字,close()。
常用UDP函数介绍
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
domain:我们一般就用对参数AF_INET和AF_INET6
type :
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams. //用于TCP
SOCK_DGRAM Supports datagrams (connectionless, unreliable messages ). //用于UDP
SOCK_RAW Provides raw network protocol access. //RAW类型,用于提供原始网络访问
protocol:置0即可
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr* my_addr, socklen_t addrlen);
- sockfd :正在监听端口的套接口文件描述符,通过socket获得
- my_addr :绑定的IP和端口
- addrlen :my_addr的结构体的大小 ,一般使用:sizeof(my_addr)
#include <unistd.h>
int close(int fd);
- fd:socket产生的fd
UDP编程用到了两个函数,和我们前面TCP编程有一定的区别:
#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 :正在监听端口的套接口文件描述符,通过socket获得
buf:发送缓冲区,自定义的数组,该数组装有要发送的数据
len:发送缓冲区的大小,单位是字节
flags:填0即可
dest_addr:指向接收数据的主机地址信息的结构体
addrlen:表示第五个参数所指向内容的长度
返回值:成功:返回发送成功的数据长度;
失败: -1
#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:正在监听端口的套接口文件描述符,通过socket获得
buf:接收缓冲区,往往是使用者定义的数组,该数组装有接收到的数据
len:接收缓冲区的大小,单位是字节
flags:填0即可
src_addr:指向发送数据的主机地址信息的结构体,也就是我们可以从该参数获取到数据是谁发出的
addrlen:表示第五个参数所指向内容的长度
返回值:成功:返回接收成功的数据长度;
失败: -1
程序实例:
util.h
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<netinet/in.h>
#define SERVER_PORT 8818
#define BUFFSIZE 1024
ser.c
#include"util.h"
int main()
{
int rec,len;
int timep;
int sockfd;
struct sockaddr_in server,client;
char recvbuf[BUFFSIZE];
char sendbuf[BUFFSIZE];
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd < 0)
printf("sockfd error\n");
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
len = sizeof(struct sockaddr);
if(bind(sockfd,(struct sockaddr*)&server,len)<0)
printf("bind error\n");
while(1)
{
rec = recvfrom(sockfd,recvbuf,BUFFSIZE,0,(struct sockaddr*)&client,&len);
if(rec < 0)
printf("recv error\n");
printf("BUFFER:%s\n",recvbuf);
timep = time(NULL);
snprintf(sendbuf,sizeof(sendbuf),"%s",ctime(&timep));
sendto(sockfd,sendbuf,sizeof(sendbuf),0,(struct sockaddr*)&client,len);
}
close(sockfd);
return 0;
}
cli.c
#include"util.h"
int main()
{
int rec,len;
int timep;
int sockfd;
struct sockaddr_in server,client;
char recvbuf[BUFFSIZE];
char sendbuf[BUFFSIZE];
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd < 0)
printf("sockfd error\n");
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
len = sizeof(struct sockaddr);
if(bind(sockfd,(struct sockaddr*)&server,len)<0)
printf("bind error\n");
while(1)
{
rec = recvfrom(sockfd,recvbuf,BUFFSIZE,0,(struct sockaddr*)&client,&len);
if(rec < 0)
printf("recv error\n");
printf("BUFFER:%s\n",recvbuf);
timep = time(NULL);
snprintf(sendbuf,sizeof(sendbuf),"%s",ctime(&timep));
sendto(sockfd,sendbuf,sizeof(sendbuf),0,(struct sockaddr*)&client,len);
}
return 0;
}