UDP套接口编程
时间:2022-04-22
本文章向大家介绍UDP套接口编程,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
常用的UDP实现的程序:DNS域名系统,NFS网络文件系统,SNMP简单网络管理协议
ssize_t recvfrom(int sockfd,void *buff,size_t nbytes,int flags,struct sockaddr * from,socklen_t *addrlen);
ssize_t sendto(int sockfd,void *buff,size_t nbytes,int flags,struct sockaddr * to,socklen_t addrlen);
sockfd:描述字
buff:缓冲区指针
nbytes 读写字节数
UDP服务器端
int main(int argc,char ** argv){
int sockfd;
struct sockaddr_in servaddr,cliaddr;
sockfd = Socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(sockfd,(SA *)&servaddr,sizeof(servaddr));
dg_echo(sockfd,(SA *)&cliaddr,sizeof(cliaddr));
}
void dg_echo(int sockfd,SA *pcliaddr,socklen_t clilen){
int n;
socklen_t len;
char mesg[MAXLINE];
for(;;){
len = clilen;
n = Recvfrom(sockfd,mesg,MAXLINE,0,pcliaddr,&len); //读一个到达的数据包
Sendto(sockfd,mesg,n,0,pcliaddr,len); //发送回给客户机
}
}
SOCK_DGRAM:UDP套接口
1 函数不能终止
2 服务器是迭代服务器,没有fork调用,单一服务器进程处理所有客户。
UDP客户机程序:
int main(int argc,char ** argv){
int sockfd;
struct sockaddr_t servaddr;
if(argc != 2)
err_quit("usage:udpcli<IPaddress>");
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET,argv[1],&servaddr,sin_addr); //装填套接字
sockfd = Socket(AF_INET,SOCK_DGRAM,0);
dg_cli(stdin,sockfd,(SA *)&servaddr,sizeof(servaddr));
exit(0);
}
void dg_cli(FILE *fp,int sockfd,const SA *pservaddr,socklen_t servlen){
int n;
char sendline[MAXLINE],recvline[MAXLINE+1];
while(Fgets(sendline,MAXLINE,fp) != NULL){ //从标准输入读一行
Sendto(sockfd,sendline,strlen(sendline),0,pservaddr,servlen); //使用sendto发送给服务器
n = Recvfrom(sockfd,recvline,MAXLINE,0,NULL,NULL); //使用recvfrom接收服务器回射,NULL无视目标主机
recvline[n] = 0;
Fputs(recvline,stdout); //fputs输出回射行到标准输出
}
}
改进的dg_cli
void dg_cli(FILE *fp,int sockfd,const SA * pservaddr,socklen_t servlen){
int n;
char sendline[MAXLINE],recvline[MAXLINE+1];
socklen_t len;
struct sockaddr *preply_addr;
preply_addr = Malloc(servlen);
while(Fgets(sendline,MAXLINE,fp)!= NULL ){
Sendto(sockfd,sendline,strlen(sendline),0,pservaddr,servlen);
len = servlen;
n = Recvfrom(sockfd,recvline,MAXLINE,0,preply_addr,&len);
if(len != servlen || memcpy(pservaddr,preply_addr,len) != 0){
printf("reply from %s (ignored)n");
Sock_ntop(preply_addr,len);
continue;
}
recvline[n] = 0;
Fputs(recvline,stdout);
}
}
解决办法:
1 给定由recvfrom返回的IP,在DNS中查找服务器验证
2 服务器配置每个IP地址创建套接口,捆绑IP地址此套接口,
仅在进程已将UDP套接口连接到确切的对方后,这些一步错误才返回给进程。
在已连接的UDP套接口上调用connect达到下面两个目的:
1 指定IP地址和端口号
2 断开套接口
使用connect连接后再调用read write
void dg_cli(FILE *fp,int sockfd,const SA * pservaddr,socklen_t servlen){
int n;
char sendline[MAXLINE],recvline[MAXLINE+1];
Connect(sockfd,(SA *)pservaddr,servlen);
while(Fgets(sendline,MAXLINE,fp)!= NULL){
Write(sockfd,sendline,strlen(sendline));
n=Read(sockfd,recvline,MAXLINE);
recvline[n] = 0;
Fputs(recvline,stdout);
}
}
对发送的UDP进行统计:
static void recvfrom_int(int);
static int count;
void dg_echo(int sockfd,SA *pcliaddr,socklen_t clilen){
socklen_t len;
char mesg[MAXLINE];
Signal(SIGINT,recvfrom_int);
for(;;){
len = clilen;
Recvfrom(sockfd,mesg,MAXLINE,0,pcliaddr,&len);
count++;
}
}
static void recvfrom_int(int signo){
printf("nreceived %d datagramsn",count);
exit(0);
}
UDP与TCP的服务器复用:
int main(int argc,char ** argv){
int listenfd,connfd,updfd,nready,maxfdp1;
char mesg[MAXLINE];
pid_t childpid;
fd_set rset;
ssize_t n;
socklen_t len;
const int on = 1;
struct sockaddr_in cliaddr,servaddr;
void sig_child(int);
listenfd = Socket(AF_INET,SOCKSTREAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_add=htonl(INADDR_ANY);
servaddr.sin_port=htons(SERV_PORT);
Setsockopt(listenfd,SOL_SOCKET,SO_RESSEADDR,&on,sizeof(on));
Bind(listenfd,(SA *)&servaddr,sizeof(servaddr));
Listen(listenfd,LISTENQ);
updfd=Socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(SERV_PORT);
Bind(udpfd,(SA *)&servaddr,sizeof(servaddr));
Signal(SIGCHLD,sig_chld);
FD_ZERO(&rset);
maxfdp1=max(listenfd,udpfd)+1;
for(;;){
FD_SET(listenfd,&rset);
FD_SET(udpfd,&rset);
if((nready=select(maxfdp1,&rset,NULL,NULL,NULL,NULL))<0){
if(errno==EINTR)
continue;
else
err_sys("select error");
}
if(FD_ISSET(listenfd,&rset)){
len = sizeof(cliaddr);
connfd=Accept(listenfd,(SA *)&cliaddr,&len);
if((childpid=Fork())==0){
Close(listenfd);
str_echo(connfd);
exit(0);
}
Close(connfd);
}
if(FD_ISSET(udpfd,&rset)){
len=sizeof(cliaddr);
n=Recvfrom(udpfd,mesg,MAXLINE,0,(SA *)&cliaddr,&len);
Sendto(udpfd,mesg,n,0,(SA *)&cliaddr,len);
}
}
}
- 【译】WordPress 中的50个过滤器(5):第31-40个过滤器
- 使用VS2010 C#开发ActiveX控件
- JavaScript 基础(三) 对象 条件判断
- “大数据+定制化服务”或将引领高端旅游市场
- FrameLayout(框架布局)
- WordPress 中变量$allowedposttags 添加自定义HTML属性
- 移动端UC /QQ 浏览器的部分私有Meta 属性
- RelativeLayout(相对布局)
- TableLayout(表格布局)
- 【MindiaX实例】 PHP 在foreach 中获取JSON 单个数据
- 史上十大最严重黑客袭击事件盘点
- LinearLayout(线性布局)
- 服务化了,没想到耦合更加严重?
- 利用好注册的域名
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- php中上传文件的的解决方案
- PHP实现与java 通信的插件使用教程
- thinkPHP5框架接口写法简单示例
- php实现数组重复数字统计实例
- php提取微信账单的有效信息
- php使用pecl方式安装扩展操作示例
- RSA实现JS前端加密与PHP后端解密功能示例
- Laravel源码解析之路由的使用和示例详解
- Linux中crontab输出重定向不生效问题的解决办法
- PHP swoole和redis异步任务实现方法分析
- thinkphp5.1框架中容器(Container)和门面(Facade)的实现方法分析
- 教你一招实现Linux中的文本比对
- PHP基于swoole多进程操作示例
- PHP格式化显示时间date()函数代码
- php函数式编程简单示例