当前位置: 首页 > news >正文

UDP编程

 udp是无连接的,没有listen 与 accept。

bind

服务端一定需要bind,告知别人自己的ip和port。

客户端可以不bind,在发送数据时候可以随机分配,客户端推荐bind(与tcp不同,udp本身无连接)。

注意:

  • 服务端当中另一个进程已经用tcp bind了 8080,该进程还可以使用udp bind 8080,tcp 与 udp没有关系。

udp只能使用sendto

sendto携带ip

如果客户端没有bind,那么只能由客户端sendto

udp接收消息只能使用recvfrom

可以获取发送方的ip和port

udp 中的close

由于无连接,另一端无影响(另一端不知道对方断开连接)。

如果一端已经close了,对面继续sendto,消息丢失不重传,可以在应用层实现可靠性。

如果一端已经close了,对面继续recvfrom,一直阻塞。

udp 和 tcp 的区别

udp 不可靠,无连接,消息有边界

tcp 可靠,有连接,是一种流式协议,消息无边界

使用udp实现即时聊天

尽管传输层没有建立连接,但是我们在应用层实现了。在做聊天之前,需要客户端先发一条消息给服务端,让服务端知道客户端的ip 和 port。

退出时可以利用recvfrom的返回值,在udp中,如果recvfrom的返回值为0,说明是空包,对面已经退出,此时本方可以退出。

代码实现

server_udp.c

#include <my_header.h>
#define BUFSIZE 4096
/* Usage:  */
int main(int argc, char *argv[]){                                  ARGS_CHECK(argc,3);int sockfd = socket(AF_INET,SOCK_DGRAM,0);struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(argv[1]);addr.sin_port = htons(atoi(argv[2]));int ret = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));ERROR_CHECK(ret,-1,"bind");char buf[BUFSIZE];struct sockaddr_in clientAddr;socklen_t clientAddrlen = sizeof(clientAddr);recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&clientAddr,&clientAddrlen);printf("client connected! ip = %s, port = %d, [buf] %s\n",inet_ntoa(clientAddr.sin_addr),htons(clientAddr.sin_port),buf);fd_set fd;while(1){FD_ZERO(&fd);FD_SET(STDIN_FILENO,&fd);FD_SET(sockfd,&fd);select(sockfd+1,&fd,NULL,NULL,NULL);if(FD_ISSET(sockfd,&fd)){bzero(buf,sizeof(buf));ssize_t sret = recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&clientAddr,&clientAddrlen);if(sret == 0){printf("client disconnected\n");break;}printf("[buf] %s\n",buf);}if(FD_ISSET(STDIN_FILENO,&fd)){bzero(buf,sizeof(buf));ssize_t sret = read(STDIN_FILENO,buf,sizeof(buf));if(sret == 0){printf("server disconnected\n");sendto(sockfd,buf,0,0,(struct sockaddr*)&clientAddr,clientAddrlen);break;}sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&clientAddr,clientAddrlen);}}close(sockfd);return 0;
}

client_udp.c

#include <my_header.h>
#define BUFSIZE 4096
/* Usage:  */
int main(int argc, char *argv[]){                                  ARGS_CHECK(argc,3);int sockfd = socket(AF_INET,SOCK_DGRAM,0);struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(argv[1]);addr.sin_port = htons(atoi(argv[2])); socklen_t serverlen = sizeof(addr);sendto(sockfd,"nihao",5,0,(struct sockaddr *)&addr,sizeof(addr));char buf[BUFSIZE];fd_set fd;while(1){FD_ZERO(&fd);FD_SET(STDIN_FILENO,&fd);FD_SET(sockfd,&fd);select(sockfd+1,&fd,NULL,NULL,NULL);if(FD_ISSET(sockfd,&fd)){bzero(buf,sizeof(buf));ssize_t sret = recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&addr,&serverlen);if(sret == 0){printf("server disconnected\n");break;}printf("[buf] %s\n",buf);}if(FD_ISSET(STDIN_FILENO,&fd)){bzero(buf,sizeof(buf));ssize_t sret = read(STDIN_FILENO,buf,sizeof(buf));if(sret == 0){printf("I will close connection\n");sendto(sockfd,buf,0,0,(struct sockaddr*)&addr,sizeof(addr));break;}sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&addr,sizeof(addr));}}close(sockfd);return 0;
}

服务端回复消息,服务端先recvfrom获取ip和ort,随后就可以sendto回去了。

对比tcp与udp来说,tcp操作更简单。但是udp的性能更好,在音视频等领域应用更广。

相关文章:

  • 4.1.1 Spark SQL概述
  • 2025年信息素养大赛 图形化编程复赛 官方样题绘制图形答案解析
  • 循环神经网络(RNN)模型
  • 【机器学习基础】机器学习入门核心算法:K均值(K-Means)
  • 强化学习(十三)DQN
  • CSS基础巩固-选择
  • 手机设备多?怎样设置IP保证不关联
  • 计算机视觉---YOLOv4
  • git reset --hard HEAD~1与git reset --hard origin/xxx
  • 力扣每日一题——连接两棵树后最大目标节点数目 ||
  • python 包管理工具uv
  • Python基础 | jupyter工具的安装与基本使用
  • 使用k8s服务进行端口代理
  • Parasoft C++Test软件单元测试_常见问题及处理
  • 长安链合约操作 查询合约命令解析
  • 2025年OE SCI2区TOP,进化麻雀搜索算法ESSA+海洋阻尼器迟滞建模与辨识,深度解析+性能实测
  • 本地Markdown开源知识库选型指南
  • 【数据分析】Pandas
  • 4 串电池保护芯片创芯微CM1341-DAT使用介绍
  • 前端面试准备2