基于UDP的回射服务器研究---未连接UDP漏洞与ICMP错误
来源:互联网 发布:宁有种乎怎么读 编辑:程序博客网 时间:2024/05/29 02:01
UDP回射服务器模型如下图所示
一、服务器程序分析
代码片段一:
文件:udpserver01.c
#include "unp.h"extern void dg_echo(int, struct sockaddr *, socklen_t clien);int main(int argc, char **argv){ int sockfd; sockfd = Socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in servaddr, cliaddr; 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, (struct sockaddr *) &servaddr, sizeof(servaddr)); dg_echo(sockfd, (struct sockaddr *) &cliaddr, sizeof(cliaddr)); return 0;}
分析:
1、SOCK_DGRAM表示创造一个UDP套接字2
2、将套接字与地址结构绑定起来。
3、主义htonl和htons都是讲主机字节序转化为网络字节序,htonl(转化为32位的网络字节序),htons(转化为16位的网络字节序)。
代码片段二:
文件dg_echo.c
#include "unp.h"#include <stdio.h>void dg_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen){ int n; socklen_t len; char buf[MAXLINE]; for(;;){ len = clilen; n = Recvfrom(sockfd, buf, MAXLINE, 0, pcliaddr, &len); Sendto(sockfd, buf, n, 0, pcliaddr, len);/*当n=-1的时候会出现错误*/ }}
分析:
1、pcliaddr已经指向一片已经初始化的struct sockaddr类型的空间。2、因为UDP套接字中允许返回0字节大小的数据,所以当n = 0时候,也成立。
3、问题:因为sockfd套接字中recvfrom的缓冲区空间是有限的,每个套接字将会按到FIFO的顺序排列的到缓冲区当中,等待读取。然后当缓冲区空间使用完毕的时候,如果在接收的数据报将会摒弃,所以我们可以通过增大缓冲区来解决该问题。增加方式(setsockopt(sockfd,SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof()bufsize))
二、客户端程序分析
代码片段一:
文件udpclient01.c
#include "unp.h"#include <stdio.h>extern void do_cli(FILE*, int, const struct sockaddr*, socklen_t);int main(int argc, char **argv){ int sockfd; if(argc != 2){ fprintf(stderr, "usage: udpclient<IPaddress>\n "); return 0; } struct sockaddr_in servaddr; 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); do_cli(stdin, sockfd,(struct sockaddr*)&servaddr, sizeof(servaddr)); return 0;}分析:
1、extern 引用另外一个程序中的函数do_cli他表示在本代码文件中其为若字符。
2、inet_pton(int fimaly, const char *strptr, void addrptr),其中addrptr是之值-结果参数, 二Inet_pton是unp.h中对该函数的又一次封装。我们一般调用该函数给struct sockaddr_in结构体中的sin_addr复制。
3、创建UDP套接字
代码片段二:
文件dg_cli.c
#include "unp.h"void do_cli(FILE *fp, int sockfd,const struct sockaddr *pservaddr, socklen_t servlen){ int n; char buf[MAXLINE]; char recvbuf[MAXLINE]; while(Fgets(buf, MAXLINE, fp) != NULL){ Sendto(sockfd, buf, strlen(buf), 0, pservaddr, servlen); n = Recvfrom(sockfd, recvbuf, MAXLINE, 0, NULL, NULL); recvbuf[n] = 0;/*字符串结尾*/ Fputs(recvbuf, stdout); }}
分析:
1、通过fget读取数据到buf中,然后发送到UDP服务器去, 然后在接收结果处理后的数据,最后标准输出到屏幕上。2、因为fputs标准输出为C语言中字符串处理形式,所以字符串结尾必须是‘\0’,不然程序会通过char*访问到不该访问的地方,造成内存泄漏。
3、recvfrom第5,6个参数为NULL, 表示我们并不在乎应答数据报是由谁在发出的。这样就存在一个巨大的问题:任何进程无论是在与本机客户进程相同的主机上还是不同的主机上,都可以向本客户Ip和端口发送数据报,这些数据报被客户读入,都会被认为是服务器的应答数据报。
运行结果分析
三、问题分析
1、针对 (二,代码片段二中分析的第三要点)的问题分析
1)我们可以通过新建一个struct sockaddr结构来记录本次recvfrom的记录,然后再和目的套接字网络地址作比较。
#include "unp.h"void do_cli(FILE *fp, int sockfd,const struct sockaddr *pservaddr, socklen_t servlen){ int n; char buf[MAXLINE]; char recvbuf[MAXLINE]; socklen_t len; struct sockaddr *preply_addr; preply_addr = Malloc(servlen); while(Fgets(buf, MAXLINE, fp) != NULL){ Sendto(sockfd, buf, strlen(buf), 0, pservaddr, servlen); len = servlen; n = Recvfrom(sockfd, recvbuf, MAXLINE, 0, preply_addr, &len); if(n >= 0 && (len != servlen || memcmp(pservaddr, preply_addr, len) != 0)){ fprintf(stdout, "replt is from %s (ignored)\n", Sock_ntop(preply_addr, len)); } recvbuf[n] = 0; Fputs(recvbuf, stdout); }}分析:
1) 我们通过调用dg_cli函数来执行程序,因为该函数的执行是与协议无关的。
2)因为len、preply_addr都是值-结果参数, memcmp是用来比较套接字地址结构本身的。
3)因为协议可能使用可变的套接字结构,所以在调用recvfrom前是len = servlen
4、sock_ntop是对inet_ntop函数的进一步封装。
运行结果:
2、服务器未运行问题
1)当服务器程序未运行的时候,将会返回一个ICMP错误客户进程。
2)ICMP错误是异步错误。该错误是由函数sendto引起的,但是sendto函数本身返回成功。因为UDP输出操作返回仅仅是表示在接口输出队列所在的IP数据报缓冲空间,而ICMP错误是后来返回的,所以这就是它异步的原因。
3)UDP套接字的异步错误,在没有连接的情况下并不会返回自己。
4)根据3)中反而言之, 只有在已连接的情况下,返回的异步错误才会返回的进程。
- 基于UDP的回射服务器研究---未连接UDP漏洞与ICMP错误
- 基于UDP广播的回射服务器
- 58-基于 UDP 协议的回射服务器
- 基于无连接(UDP协议)的服务器与客户端编程实例
- 与基于udp协议的tracker服务器进行交互
- 与基于udp协议的tracker服务器进行交互
- android手机与服务器基于UDP协议的通信
- UDP回射服务器
- 基于UDP协议的Socket服务器
- 基于LwIP socket的UDP服务器
- 基于UDP协议的服务器/客户端程序
- 基于UDP协议的服务器/客户端程序
- 基于UDP的nio日志服务器
- 基于UDP的回声服务器/客户端
- 基于UDP协议的服务器/客户端
- 计算机网络基于UDP的服务器和客户端
- 基于UDP的C/S多播回射服务器
- 基于无连接的UDP程序设计
- struts2 基础学习
- CF Round#424(div2)D题 二分+贪心
- struts2的action方法匹配以及通配符的使用
- Java中的static
- ActiveMQ的简单使用
- 基于UDP的回射服务器研究---未连接UDP漏洞与ICMP错误
- MS DOS 常用命令整理
- Git SSH Key 生成步骤
- IntelliJ IDEA 中 Ctrl+Alt+Left/Right 失效
- Java中POJO及其细分XO、DAO的概念
- Spring Boot 系列文章推荐
- Spring Data Redis实战之提供RedisTemplate
- Linux笔记1-简介
- 使用Git上传项目到GitHub