socket 实现udp网络数据通信
利用udp实现网络数据通信
UDP(User Datagram Protocol) 是用户数据报协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。它是 IETF RFC 768 是 UDP 的正式规范。UDP 在 IP 数据包的头部仅仅加入了复用和数据完整性校验(数据包检查)的字段。UDP 是对 IP 层的一个简单封装,仅仅在 IP 数据包头部加入了复用(复用)和数据完整性校验(数据包检查)的字段。
UDP 的主要特点包括:
- 无连接:UDP 发送数据之前不需要建立连接,因此减少了开销和发送数据之前的时延。
- 尽最大努力交付:UDP 不保证可靠交付,也就是说,UDP 协议不保证数据报文能准确地到达目的地,也不保证数据报文的顺序性。
- 面向报文:UDP 一次发送一个完整的报文,并在发送报文时保留报文的边界。接收方也是一次接收一个完整的报文。
- 没有拥塞控制:UDP 发送方只管发送数据,不确认数据是否到达,因此没有拥塞控制。网络出现拥塞时,UDP 也不会降低发送速率。
- 支持一对一、一对多、多对一和多对多的交互通信。
UDP客户端的代码(发送端)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
// 运行客户端可执行文件 ./xxx 服务器端口 服务器地址
int main(int argc,char *argv[])
{
//检查参数有效性
if (argc != 3)
{
fprintf(stderr, "argument is invaild ,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.向目标主机发送消息,需要设置目标端口和目标地址
char buf[128] = "ok";
struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET; //协议族,是固定的
dest_addr.sin_port = htons(atoi(argv[1])); //服务器端口,必须转换为网络字节序
dest_addr.sin_addr.s_addr = inet_addr(argv[2]); //服务器地址 "192.168.64.xxx"
//3.发送客户端的上线时间
sendto(udp_socket,buf,strlen(buf),0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
while(1);
return 0;
}
UDP服务器端的代码(接收端)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int main(int argc,char *argv[])
{
//检查参数有效性
if (argc != 3)
{
fprintf(stderr, "argument is invaild ,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 host_addr;
host_addr.sin_family = AF_INET; //协议族,是固定的
host_addr.sin_port = htons(atoi(argv[1])); //目标端口,必须转换为网络字节序
host_addr.sin_addr.s_addr = inet_addr(INADDR_ANY); //目标地址 "192.168.64.xxx" 已经转换为网络字节序 INADDR_ANY
bind(udp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr));
//3.调用recvfrom等待接收数据,并且接收客户端的网络信息
char buf[128] = {0};
struct sockaddr_in client;
socklen_t client_len = sizeof(client);
while(1)
{
recvfrom(udp_socket,buf,sizeof(buf), 0 ,&client,&client_len); //默认会阻塞
printf("client ip is [%s],time is [%s]\n",inet_ntoa(client.sin_addr),buf);
bzero(buf,sizeof(buf));
}
return 0;
}
在上面的代码中,udp_server.c
创建一个UDP socket,绑定到指定的端口,并等待接收数据。udp_client.c
创建一个UDP socket,并将数据发送到指定的IP地址和端口。
为了运行这些程序,我们需要先编译运行服务器端程序:
gcc udp_server.c -o udp_server
./udp_server 8888
然后编译运行发送端程序:
gcc udp_client.c -o udp_client
./udp_client 192.168.xxx.xxx
如果代码用法有什么问题,请将问题发至网易邮箱 m17872844806@163.com,作者将及时改正,欢迎与各位老爷交流讨论。
麻烦三连加关注!!!!
比心