基于无连接的UDP程序设计

同样,在开发基于UDP的应用程序时,其主要流程如下:

对于面向无连接的UDP应用程序在开发过程中服务端和客户端的操作流程基本差不多。对比面向连接的TCP程序,服务端少了listen和accept函数。前面我们也说过listen函数最主要的作用就是将一个socket套接字描述符转为被动监听模式,然后调用accept主要是用于等待客户端(用connect)来连接服务器。connect函数不仅可以用于流式套接字还可用于数据报式套接字。在TCP中,客户端调用connect函数会向服务器端触发一个TCP的3次握手过程,去建立一条TCP连接;而在UDP中,客户端调用该函数主要的作用是告诉后面将要调用的recvfrom函数,仅仅只接受在connect函数中指明的服务器发来的数据,这样当后面调用recvfrom时最后两个参数就可以置为NULL了。也就说对UDP编程来说,客户端调用connect是可选的:如果调用了connect函数,recvfrom就可以省掉最后两个参数;如果不调用connect则recvfrom必须指明从哪儿收数据。

对于UDP的编程其实主要在数据的收发处理上,而面向无连接的UDP编程中收发数据用到的最多的函数就是recvfrom()和sendto(),其原型如下:

ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);ssize_t sendto(int s, const void *buf, size_t len, int flags, struct sockaddr *to, socklen_t tolen);

recvfrom函数主要用于从s所指定的套接字中接收数据,并将其存储在buf所指向的缓冲区里。如果from参数不为NULL,那么其中便会携带消息发送端的地址信息,fromlen则指明了信息发送方地址信息结构体的大小。如果接收方对发送发的地址不感兴趣,将from和fromlen置为NULL即可。返回值:小于0,有错误;大于0,实际收到的字节数;等于0,对端主动关闭。

sendto函数,主要是buf所指向的数据发送到套接字描述符s中,len为要发送的数据长度,to中存储了对端的地址信息,即数据该发往何处,tolen为to所占的字节数。返回值:小于0,有错误;大于0,实际发送的字节数。

另外我们还知道,sendto是可以用于面向连接的流式套接字的,在TCP开发章节我们已经提过。这里在罗嗦一点,如果sendto用于面向流式的套接字编程中,to和tolen参数都会被忽略,如果发送数据时连接还未建立相应的提示错误为ENOTCONN。

这里也没有哪个规定说是不准在TCP程序中用sendto,但我们一般都不这么做,自己体会一下就明白了,除非你的项目开发中有特殊需求必须用。一句话:记住sendto和recvfrom既可以用于面向连接的流式套接字中收发数据,也可以用于面向无连接的数据报式套接字。sendto()和recvfrom()一般用在面向无连接的数据报式套接字的程序开发中。

  UDP服务端代码, server.cpp

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define MAX_MSG_SIZE 1024int main(int argc,char** argv){int skfd,addrlen,ret;struct sockaddr_in addr,cltaddr;char buf[MAX_MSG_SIZE]={0};char sndbuf[MAX_MSG_SIZE]={0};//创建数据报式套接字skfdif(0>(skfd=socket(AF_INET,SOCK_DGRAM,0))){perror("Create Error");exit(1);}bzero(&addr,sizeof(struct sockaddr_in));addr.sin_family = AF_INET;addr.sin_addr.s_addr=htonl(INADDR_ANY);addr.sin_port=htons(atoi(argv[1]));//将socket文件描述符skfd和本地端口和地址绑定起来if(0>(bind(skfd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in)))){perror("Bind Error");exit(1);}//开始收发数据while(1){ret=recvfrom(skfd,buf,MAX_MSG_SIZE,0,(struct sockaddr*)&cltaddr,&addrlen);if(ret < 0){printf("recv data from %s:%d error!",inet_ntoa(cltaddr.sin_addr),ntohs(cltaddr.sin_port));}else if(ret == 0){perror("client has been closing socket!");}else{printf("From %s:%d,%s",inet_ntoa(cltaddr.sin_addr),ntohs(cltaddr.sin_port),buf);memset(sndbuf,0,MAX_MSG_SIZE);switch(buf[0]){case 'a':strcpy(sndbuf,"After u ,lady...");break;case 'b':strcpy(sndbuf,"Before u ,sir...");break;case 'c':strcpy(sndbuf,"Can u?");break;default:strcpy(sndbuf,"I dont't know what u want!");}sendto(skfd,sndbuf,strlen(sndbuf),0,(struct sockaddr*)&cltaddr,addrlen);}memset(buf,0,MAX_MSG_SIZE);}return 0;
}

  UDP客户端代码, client.cpp

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define MAX_MSG_SIZE 1024int main(int argc,char** argv){int skfd,ret,len;struct sockaddr_in srvaddr;char buf[MAX_MSG_SIZE]={0};char sndbuf[MAX_MSG_SIZE]={0};struct in_addr addr;//创建数据报式套接字skfdif(0>(skfd=socket(AF_INET,SOCK_DGRAM,0))){perror("Create Error");exit(1);}if(0 == inet_aton(argv[1],&addr)){perror("server addr invalid!");exit(1);}bzero(&srvaddr,sizeof(struct sockaddr_in));srvaddr.sin_family = AF_INET;srvaddr.sin_addr=addr;srvaddr.sin_port=htons(atoi(argv[2]));//我们的客户端只接收从服务器地址是srvaddr的主机发来的数据if(0>(connect(skfd,(struct sockaddr*)&srvaddr,sizeof(struct sockaddr_in)))){perror("Connect Error");exit(1);}//开始收发数据while(1){memset(sndbuf,0,MAX_MSG_SIZE);len=read(0,sndbuf,MAX_MSG_SIZE);ret=sendto(skfd,sndbuf,strlen(sndbuf),0,(struct sockaddr*)&srvaddr,sizeof(struct sockaddr));if(ret == len){memset(buf,0,MAX_MSG_SIZE);//我们已经知道服务器地址信息了,所以最后两个参数为NULLret=recvfrom(skfd,buf,MAX_MSG_SIZE,0,NULL,NULL);if(ret < 0){perror("read error from server!");}else if(ret == 0){perror("server has been closing socket!");}else{buf[ret]='\0';printf("From Server:%s\n",buf);}}}return 0;
}

  测试结果:

我们客户端接收用户命令行输入的指令,然后将其发给UDP服务器端;服务器端收到不同的指令后给客户端予以不同的提示信息,整个流程如上所示。

udpclt.c的示例代码中我是调用了connect,勤奋好学的童鞋可以动手试验哈不调用connect然后将程序调通吧。

  转载自:http://blog.chinaunix.net/uid-23069658-id-3276167.html

Linux网络编程:基于UDP的程序开发回顾篇相关推荐

  1. Linux网络编程 - 基于UDP的服务器端/客户端

    一 理解UDP 1.0 UDP协议简介 UDP(User Datagram Protocol,用户数据报协议) [RFC 768] UDP协议的数据传输单元叫 UDP用户数据报,而TCP协议的数据传输 ...

  2. 【Linux网络编程】UDP 套接字编程

    [Linux网络编程]UDP 套接字编程 [1]用户数据报协议(UDP) UDP是一个简单的传输层协议,不保证UDP数据报会到达其最终目的地,不保证各个数据报的先后顺序跨网络后保持不变,也不保证每个数 ...

  3. 【网络编程】TCP 网络应用程序开发

    [网络编程]TCP 网络应用程序开发 TCP 网络应用程序开发流程 1. TCP 网络应用程序开发流程的介绍 2. TCP 客户端程序开发流程的介绍 3. TCP 服务端程序开发流程的介绍 4. 小结 ...

  4. 嵌入式linux网络编程之——5年程序员给你深度讲解socket套接字

    以下内容转载自 https://www.toutiao.com/i6827837032622981636/ 本文主要给大家分享网络七层概念之网络编程socket,前边的章节已经给大家讲述了链路层.物理 ...

  5. 【Linux网络编程】UDP编程

    00. 目录 文章目录 00. 目录 01. 概述 02. UDP编程C/S结构 03. UDP常用函数 3.1 sendto函数 3.2 recvfrom函数 3.3 bind函数 04. 程序示例 ...

  6. 【Linux网络编程】UDP洪水攻击

    00. 目录 文章目录 00. 目录 01. 洪水攻击概述 02. UDP洪水攻击原理分析 03. IP协议格式 04. UDP协议格式 05. 原始套接字 5.1 原始套接字概述 5.2 原始套接字 ...

  7. Linux网络编程 之 UDP编程(六)

    目录 1. UDP客户端     核心函数     完整的UDP客户端程序 2. UDP服务端     核心函数     完整的UDP客户端程序 3. 总结 1. UDP客户端 核心函数 ssize_ ...

  8. Java网络编程——基于UDP协议的聊天室

    UDP简述    UDP(User Datagram Protocol)协议是Internet 协议集支持的一个无连接的传输协议,中文名为用户数据报协议.它为应用程序提供了一种无需建立连接就可以发送封 ...

  9. Linux网络编程——基于tcp/ip的模拟聊天(文件传输)工具

    开发平台:Linux 开发工具:Ubuntu, sourceInsight4.0 项目介绍: 本项目基于TCP/IP协议创建一个网络通信系统,可以实现客户之间的聊天通信以及文件传输,同时利用进程实现多 ...

最新文章

  1. 卡尔曼滤波(kalman)相关理论以及与HMM、最小二乘法关系 转
  2. STM32开发 -- STM32初识
  3. php开发者与composer的不得不说故事
  4. Cocos Creator导出场景和预制的问题
  5. LeetCode 1186. 删除一次得到子数组最大和(DP)
  6. Nest入门教程 - 初识控制器
  7. 数字图像处理--图像梯度算子的本质
  8. java中的step_Java中finalize()
  9. 如何解压.bz2文件包
  10. 通信用水泥杆和防腐木电杆在使用中有什么不同
  11. html5文字游戏引擎,HTML5游戏实战(3): 60行代码实现水平跑酷游戏
  12. ThreadLocal 常见使用场景
  13. scrapy爬取动态网页
  14. 问农事 - 菜蔬作物的节令
  15. html字体样式(2)
  16. 很有意境的语句[转]
  17. 高性价比降噪耳机推荐,2023年降噪耳机排行榜推荐
  18. matlab怎么调用filter函数,如何在matlab中建立和调用filter函数
  19. Linux下QT平台Mysql数据库开发环境配置
  20. 基因对疾病的影响规律--读论文

热门文章

  1. Git详解之二 Git基础
  2. 困扰多日的C#调用Haskell问题竟然是Windows的一个坑
  3. Prolog学习:数独和八皇后问题
  4. Python脱产8期 Day02
  5. 填报表中也可以添加 html 事件
  6. 使用phpStudy运行伊人集项目
  7. 让世界零距离 小鱼易连的大梦想
  8. 推荐并简要分析一个silverlight的相册DEMO--ImageSnipper(V2)
  9. html5 canvas雨点打到窗玻璃动画
  10. 需要恢复中断状态的一个场景