前言
1、UDP通信协议,服务器端和客户端无需建立连接,只需要知道对方套接字的地址信息就可以发送数据
2、UDP通信流程图:
一、udp编程相关函数
1、socket函数
功能:创建套接字并返回套接字描述符
头文件:
#include<sys/socket.h>
函数原型:
int socket(int family,int type,int protocol)
参数:
family:协议族
AF_INET:IPv4协议
AF_INET6:IPv6协议
type:套接字类型
SOCK_STREAM:流式套接字(tcp)
SOCK_DGRAM:数据报套接字(udp)
protocol:0
返回值:
非负套接字描述符
2、bind函数
功能:将套接字与IP地址和端口号绑定
头文件:
#include<sys/socket.h>
函数原型:
int bind(int sockfd,(struct sockaddr *)my_addr,int addrlen)
参数:
sockfd:套接字描述符
my_addr:绑定的地址
addrlen:地址长度
3、sendto函数
功能:发送数据
头文件:
#include<sys/socket.h>
函数原型:
int send(int sockfd,const void *buf,int len,int flags,const struct sockaddr *to,int tolen);
参数:
sockfd:套接字描述符
buf:发送缓存区的地址
len:发送数据的长度
flags:一般为0
to:接收方套接字的ip地址和端口号
tolen:地址长度
返回值:
实际发送的字节数
4、recvfrom函数
功能:接收数据
头文件:
#include<sys/socket.h>
函数原型:
int recv(int sockfd,void *buf,int len,unsigned int flags,const struct sockaddr *from,int fromlen)
参数:
sockfd:套接字描述符
buf:存放接收数据的缓存区的地址
len:接收数据的长度
flags:一般为0
from:发送方的ip地址和端口号
fromlen:地址长度
返回值:
实际接收的字节数
5、close函数
功能:关闭套接字
头文件:
#include<sys/socket.h>
函数原型:
int close(int sockfd)
参数:
sockfd:套接字描述符
二、实际案例
1、代码功能:两个进程可以相互收发数据
2、实现需要开启两个终端,同时运行相同的代码,一端发送,一端接收
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#include <stdio.h>
struct sockaddr_in my_addr;//定义本段代码套接字
struct sockaddr_in to_addr;//定义另一端代码套接字
int fd;//定义套接字描述符
void *send_fun(void *p)//处理发送功能的线程函数
{
char buf[100] = { 0 };
while(1)
{
gets(buf);//输入字符串
sendto(fd, buf, 100, 0, (struct sockaddr*)&to_addr, 16);//发送数据
}
}
int main(int argc, char *argv[])
{
pthread_t id;//线程id
fd = socket(AF_INET, SOCK_DGRAM, 0);//套接字fd赋值
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(atoi(argv[3])); //argv[3] 自己的端口号 9999
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); //inet_addr("192.168.31.252"); INADDR_ANY 得到当前计算机的ip地址
bind(fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));//绑定自己的ip地址和端口号
to_addr.sin_family = AF_INET;
to_addr.sin_port = htons(atoi(argv[2])); //argv[2]对方的端口号 8888
to_addr.sin_addr.s_addr = inet_addr(argv[1]); //argv[1]对方的ip地址 127.0.0.1
pthread_create(&id, NULL, send_fun,NULL);//创建线程
while(1)
{
char buf[100];
int len = 16;
recvfrom(fd, buf, 100, 0, (struct sockaddr *)&to_addr, &len);//接收数据
printf("from %d:%s\n", ntohs(to_addr.sin_port), buf);//输出对方的IP地址和端口号
}
}
结果展示
可以实现相互发送数据的两端:
1、127.0.0.1是环回地址
2、8888和9999是两端套接字地址的端口号
总结
1、UDP通信是不可靠的,其中一点是没有建立连接机制,使用ip地址进行数据的传输
2、UDP和TCP主要在于sendto和recvfrom两个函数,这两个函数参数包括了对方的ip地址和端口号,这点与TCP通信区别较大