UDP
UDP传输协议UDP的概念
*UDP协议提供面向事务的简单不可靠信息传送服务*,因为无法保证数据包的交付以及当数据包出现丢包之后不具备对丢失的数据包重传的功能。对于UDP协议而言,还存在其他特性,比如UDP协议提供的是*面向无连接*的服务,也就是说双方在通信之前不需要建立连接,接收方收到数据之后也无需进行回复确认送达,所以UDP协议无法知道报文发送之后是否安全完整到达,体现出“不可靠”的特性。
注意:UDP协议也不保证数据包可以有序到达,以及不提供数据包进行分组和组装的服务。
包长度指的是UDP报首长度 + 数据内容长度之和,而包长度占16bit,也就是包长度的最大值是65535字节,可以看到UDP数据报报首的长度是8字节,而UDP协议接收到的网络层转发过来的数据包中还存在IP协议的报首,而IP协议的报首固定为20字节(不使用可选选项的情况下),所以UDP携带的数据内容的最大值是65507字节
通过手册发现想要指定UDP协议进行通信,需要先调用socket函数创建UDP套接字,如果只打算向对方主机发送数据包,则可以调用sendto()函数或者sendmsg()函数,注意要把对方主机的有效IP地址作为参数。
如果打算接收对方主机发送的数据包,则需要提前调用bind()函数把UDP套接字和本地主机地址进行绑定,然后调用recvfrom()函数来接收数据包。
(1) socket()函数
Linux系统的思想是“一切皆文件”,所以Linux系统把文件分为7类、其中有一种文件是为了实现在不同主机的进程间进行通信而设计出来的,也被称为套接字文件(标识符是s,指的是socket的缩写)。
如果双方主机打算通信,则双发都需要在本地创建套接字文件,Linux系统中提供了一个名称叫做socket()的函数接口,使用规则如下:
函数参数
第一个参数:domain指的是要使用的协议族,因为协议族决定了通信地址类型,常用的是AF_INET协议族,这样就采用IPV4地址进行通信。
第二个参数:type指的是套接字类型,一般常用的类型有SOCK_STREAM 和 SOCK_DGRAM。
SOCK_STREAM类型 :提供有序、可靠、双向、基于连接的字节流,也就是基于TCP协议。
SOCK_DGRAM类型 :提供不可靠、无连接、固定长度数据的数据报,是基于UDP协议。
第三个参数:protocol指的是和套接字类型相关的协议,一般设置为0即可,这样系统会自动根据套接字类型选择合适协议。
返回结果:socket函数创建套接字成功,则会返回对应的文件描述符,如果套接字创建失败,则返回-1。
客户端和服务器端进行通信
客户端
#include <sys/socket.h>
#include <netinet/in.h>
#include
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char *argv[])
{
//检查参数有效性
if(argc!=3)
{
fprintf(stderr, "udp socket error,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//1.创建udp套接字
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if(udp_socket==-1)
{
fprintf(stderr, "udp socket error,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//2.UDP协议使用下面的数据类型来存储目标IP和目标端口
struct sockaddr_indest_addr;
dest_addr.sin_family=AF_INET;
dest_addr.sin_port=htons(atoi(argv));
dest_addr.sin_addr.s_addr=inet_addr(argv);
//3.循环用sendto发送消息
char buf={0};
while(1);
{
scanf("%s",buf);
sendto(udp_socket,buf,strlen(buf),0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
bzero(buf,sizeof(buf));
}
return 0;
}服务器端
#include <sys/socket.h>
#include <netinet/in.h>
#include
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char *argv[])
{
//检查参数有效性
if(argc!=3)
{
fprintf(stderr, "udp socket error,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//1.创建udp套接字
int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if(udp_socket==-1)
{
fprintf(stderr, "udp socket error,errno:%d,%s\n",errno,strerror(errno));
exit(1);
}
//2.把创建的套接字和本地地址以及端口进行绑定
// struct sockaddr_in {
// sa_family_t sin_family; /* address family: AF_INET */
// in_port_t sin_port; /* port in network byte order */
// struct in_addr sin_addr; /* internet address */
// };
// /* Internet address. */
// struct in_addr {
// uint32_t s_addr; /* address in network byte order */
// };
struct sockaddr_in host_addr;
host_addr.sin_family=AF_INET;
host_addr.sin_port=htons(atoi(argv));
host_addr.sin_addr.s_addr=inet_addr(argv);
bind(udp_socket,(struct sockaddr *)&host_addr,sizeof(host_addr));//绑定
//3.循环用recvfrom接收消息
char buf={0};
while(1);
{
recvfrom(udp_socket,buf,sizeof(buf), 0 ,NULL,NULL);
printf("recv data is [%s]\n",buf);
bzero(buf,sizeof(buf));
}
return 0;
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]