Linux网络编程:基于UDP的程序开发回顾篇
基于无连接的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 1024 int main(int argc,char** argv){
int skfd,addrlen,ret;
struct sockaddr_in addr,cltaddr;
char buf[MAX_MSG_SIZE]={};
char sndbuf[MAX_MSG_SIZE]={}; //创建数据报式套接字skfd
if(>(skfd=socket(AF_INET,SOCK_DGRAM,))){
perror("Create Error");
exit();
} 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[])); //将socket文件描述符skfd和本地端口和地址绑定起来
if(>(bind(skfd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in)))){
perror("Bind Error");
exit();
} //开始收发数据
while(){
ret=recvfrom(skfd,buf,MAX_MSG_SIZE,,(struct sockaddr*)&cltaddr,&addrlen);
if(ret < ){
printf("recv data from %s:%d error!",inet_ntoa(cltaddr.sin_addr),ntohs(cltaddr.sin_port));
}else if(ret == ){
perror("client has been closing socket!");
}else{
printf("From %s:%d,%s",inet_ntoa(cltaddr.sin_addr),ntohs(cltaddr.sin_port),buf);
memset(sndbuf,,MAX_MSG_SIZE);
switch(buf[]){
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),,(struct sockaddr*)&cltaddr,addrlen);
}
memset(buf,,MAX_MSG_SIZE);
}
return ;
}
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 1024 int main(int argc,char** argv){
int skfd,ret,len;
struct sockaddr_in srvaddr;
char buf[MAX_MSG_SIZE]={};
char sndbuf[MAX_MSG_SIZE]={};
struct in_addr addr; //创建数据报式套接字skfd
if(>(skfd=socket(AF_INET,SOCK_DGRAM,))){
perror("Create Error");
exit();
} if( == inet_aton(argv[],&addr)){
perror("server addr invalid!");
exit();
} bzero(&srvaddr,sizeof(struct sockaddr_in));
srvaddr.sin_family = AF_INET;
srvaddr.sin_addr=addr;
srvaddr.sin_port=htons(atoi(argv[])); //我们的客户端只接收从服务器地址是srvaddr的主机发来的数据
if(>(connect(skfd,(struct sockaddr*)&srvaddr,sizeof(struct sockaddr_in)))){
perror("Connect Error");
exit();
} //开始收发数据
while(){
memset(sndbuf,,MAX_MSG_SIZE);
len=read(,sndbuf,MAX_MSG_SIZE);
ret=sendto(skfd,sndbuf,strlen(sndbuf),,(struct sockaddr*)&srvaddr,sizeof(struct sockaddr));
if(ret == len){
memset(buf,,MAX_MSG_SIZE);
//我们已经知道服务器地址信息了,所以最后两个参数为NULL
ret=recvfrom(skfd,buf,MAX_MSG_SIZE,,NULL,NULL); if(ret < ){
perror("read error from server!");
}else if(ret == ){
perror("server has been closing socket!");
}else{
buf[ret]='\0';
printf("From Server:%s\n",buf);
}
}
}
return ;
}
测试结果:

我们客户端接收用户命令行输入的指令,然后将其发给UDP服务器端;服务器端收到不同的指令后给客户端予以不同的提示信息,整个流程如上所示。
udpclt.c的示例代码中我是调用了connect,勤奋好学的童鞋可以动手试验哈不调用connect然后将程序调通吧。
Linux网络编程:基于UDP的程序开发回顾篇的更多相关文章
- Linux网络编程:基于TCP的程序开发回顾篇《转》
		面向连接的TCP程序设计 基于TCP的程序开发分为服务器端和客户端两部分,常见的核心步骤和流程: 其实按照上面这个流程调用系统API确实可以完全实现应用层程序的开发,一点问题没有.可随着时间的推移,你 ... 
- Linux网络编程:UDP Socket编程范例
		TCP协议提供的是一种可靠的,复杂的,面向连接的数据流(SOCK_STREAM)传输服务,它通过三段式握手过程建立连接.TCP有一种"重传确认"机制,即接收端收到数据后要发出一个肯 ... 
- 网络编程(基于udp协议的套接字/socketserver模块/进程简介)
		一.基于UDP协议的套接字 TCP是建立可靠连接,并且通信双方都可以以流的形式发送数据.相对TCP,UDP则是面向无连接的协议. 使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号,就 ... 
- JAVA基础知识之网络编程——-基于UDP协议的通信例子
		UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramS ... 
- UNIX网络编程——基于UDP协议的网络程序
		一.下图是典型的UDP客户端/服务器通讯过程 下面依照通信流程,我们来实现一个UDP回射客户/服务器: #include <sys/types.h> #include <sys/so ... 
- 网络编程——基于UDP的网络化CPU性能检测
		网络化计算机性能检测软件的开发,可对指定目标主机的CPU利用率进行远程检测,并自动对远程主机执行性能指标进行周期性检测,最终实现图形化显示检测结果. 网络通信模块:(客户端类似,因为udp是对等通信) ... 
- Linux网络编程:UDP实现可靠的文件传输
		我们知道,用TCP实现文件传输很简单.相对于TCP,因为UDP是面向无连接.不可靠的传输协议,所以我们需要考虑丢包和后发先至(包的顺序)的问题,所以我们想要实现UDP传输文件,则需要解决这两个问题.方 ... 
- linux网络编程笔记——UDP
		目前这部分代码会出现阻塞问题,暂时尚未解决 #include "udp.h" #include <stdio.h> #include <string.h> ... 
- 网络编程: 基于UDP协议的socket
		udp是无链接的,启动服务之后可以直接接受消息,不需要提前建立链接 UDP协议的通信优势: 允许一个服务器同时和多个客户端通信, TCP不行 服务端 import socket sk = socket ... 
随机推荐
- Android adb logcat使用技巧
			前言 新买的笔记本E431装了最新版的Eclipse,搞定了Android开发环境,可是logcat里查看东西居然仅仅显示level,没有错误的具体信息.我本身也不是一个愿意折腾图形界面,更喜欢纯命令 ... 
- Revit API切换三维视图
			切换视图必须在事务结束之后,这个困惑了半天,记录一下. , , -));//斜视45度 ts.Commit(); //切换视图必须在事务结束后,否则会提 ... 
- 排名前16的Java工具类
			原文:https://www.jianshu.com/p/9e937d178203 在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法 ... 
- 在Android.mk文件中输出打印消息
			http://www.xuebuyuan.com/1947880.html 在进行Android NDK的开发当中有时想看看Android.mk文件当中某个变量的值,可以再Android.mk文件当中 ... 
- 发展受阻第一至四季/全集Arrested迅雷下载
			发展受阻 第一至四季 Arrested Development 1-4 (2013)本季看点:<发展受阻>讲述了一个很有钱的Bluth家庭的故事,主要聚焦家族里的各种古怪事和相互算计带来的 ... 
- 高速Android开发系列通信篇之EventBus
			概述及基本概念 **EventBus**是一个Android端优化的publish/subscribe消息总线,简化了应用程序内各组件间.组件与后台线程间的通信.比方请求网络,等网络返回时通过Hand ... 
- Generalized normal distribution and Skew normal distribution
			Density Function The Generalized Gaussian density has the following form: where (rho) is the " ... 
- CDR话单主要字段介绍
			l Time of call connection RRC连接时的时间,格式:yyyy年mm月dd日hh时mm分ss秒 l Call Setup Time per sections 呼叫建立时长 ... 
- 部署Percona XtraDB Cluster高可用和多Master集群
			http://www.it165.net/admin/html/201401/2306.html http://www.oschina.net/p/percona-xtradb-cluster/ ht ... 
- postgresql共享内存的三个结构体
			本文原创为freas_1990,转载请标明出处:http://blog.csdn.net/freas_1990/article/details/16105797 postgresql的共享内存维护主要 ... 
