基于UDP协议的接收和发送实验

基于UDP协议的接收和发送实验

选修了一门TCP/IP协议分析及应用,做了几个小实验,这里把实验的原理、自己的代码和经验教训和大家分享一下。

实验中的全部代码托管在Github上,请通过 fork + pull request 方法来帮助改进项目。

导语:

UDP协议是User Datagram Protocol 的简称,他是无连接的,不可靠的网络协议。
本实验目的是使用因特网提供的UDP传输协议,实现一个简单的UDP客户/服务器程序,以了解传输层所提供的UDP服务的特点,应用层和传输层之间的软件接口风格,熟悉socket机制和UDP客户端/服务器方式程序的结构。
本文在介绍UDP协议收发技术的同时,提供了相关代码,并将笔者在debug过程中的经验和教训带给读者。

一,实验内容

设计与实现UDP echo客户及服务器程序,完成以下功能:
客户从标准输入读一行文本,写到服务器上;服务器从网络输入读取此行,并回射(echo)给客户;客户读此回射行,并将其写到标准输出。
扩展一下三个内容
* 在客户机上显示服务器的目录
* 将服务器指定的文件下载到客户机
* 讲客户机指定的文件上传到服务器

二,UDP编程框架

使用UDP进行程序设计可以分为客户端和服务器端两个部分。服务器端主要包含建立套接字、将套接字与地址结构进行帮顶、读写数据、关闭套接字几个过程。客户端包括建立套接字、读写数据、关闭套接字几个过程。服务器端和客户端两个流程志坚的主要差别在于对地址的绑定(bind())函数,客户端可以不用进行地址和端口的绑定操作。

2.1 UDP服务器编程框架

上图中对UDP协议服务器程序框架进行了说明,服务器流程主要分为下述6个部分吗,即建立套接字、设置套接字地址参数、进行端口绑定、接收数据、发送数据、关闭套接字。
1. 建立套接字文件描述符,使用socket(), 生成套接字文件描述符,例如:

int s = socket(AF_INET, SOCK_DGRAM, 0);

建立一个AF_INET 族的数据包套接字,UDP协议的套接字使用SOCK_DGRAM选项。
2. 设置服务器地址和侦听端口,初始化要绑定的网络地址结构,例如:

struct sockaddr addr_serv;
addr_serv.sin_family = AF_INET;                     //地址类型为AF_INET
addr_serv.sin.addr.s_addr = htonl(INADDR_ANY);      //任意本机地址
addr_serv.sin_port = htons(PORT_SERV);              //服务器端口

地址结构的类型为AF_INEF ; IP地址为任意的本地地址; 服务器的端口为用户定义的端口地址; 注意成员sin_addr.s_addrsin_port均为网络字节序。
3. 绑定侦听端口,使用bind()函数,将套接字文件描述符和一个地址类型变量进行绑定,例如

bind(s,(struct sockaddr*) &addr_serv,sizeof(addr_serv));    //绑定地址
  1. 接收客户端的数据,使用recvfrom()函数接受客户端的网络数据。
  2. 向客户端发送数据,是应用sendto()函数向服务器主机发送数据。
  3. 关闭套接字,使用close()函数释放资源

2.2 UDP客户端编程框架

在上图中,同样对UDP协议的客户端流程进行了描述,按照图中所示,UDP协议的客户端流程分为套接字建立、设置目的的地址和端口、向服务器发送数据、从服务器接收数据、关闭套接字5个部分。与服务器的框架相比,少了bind()部分,客户端程序的端口和本地的地址可以由系统使用时指定,在使用sendto()recvfrom()的时候,网络协议栈会临时指定本地的端口和地址,流程如下:
1. 建立套接字文件描述符,socket()
2. 设置服务器地址和端口,struct sockaddr
3. 向服务器地址和端口,sendto();
4. 接收服务器的数据,recvfrom();
5. 关闭套接字,close();

三,UDP协议程序设计的常用函数

UDP协议常用的函数有recv() /recvform()send()/ sendto()socket()bind() 等。当然这些函数同样可以用于TCP协议的程序设计。

3.1 建立套接字socket() 和绑定套接字bind()

UDP协议使用建立套接字的方式和TCP方式一样,使用socket() 函数,只不过协议的类型描述符使用SOCK_DGRAM, 而不是参数SOCK_STREAM。 例如下面是一个建立UDP套接字文件描述符的代码。

int s;
s = socket(AF_INEF, SOCK_DGRAM, 0);

UDP协议使用bind()函数的方法与TCP没有什么差别,将一个套接字描述符与一个地址结构绑定在一起。例如,下面的代码将一个本地的地址和套接字文件描述符绑定在在了一起。

struct sockaddr_in local;                               //本地的地址信息
int from_len = sizeof(from);                            //地址结构的长度
local. sin _family = AF_INET;                           //协议簇
local. sin _port = htons(8888);                         //本地端口
local. sin _addr.s_addr = htonl(INADDR_ANY);            //任意本机地址
s = socket(AF_INET, SOCK_DGRAM, 0);         //初始化一个IPv4族的数据包套接字
if (s == -1) {                              //检查是否正常初始化socket
    perror("socket");
    exit(EXIT_FAILURE);
}
bind(s, (struct sockaddr*) &local, sizeof(local));      //套接字绑定

绑定函数bind()使用的时机,即什么时候需要绑定需要介绍一下。函数bind()的作用是将一个套接字文件描述符和一个本地地址绑定在一起,即把发送数据的端口地址和IP地址进行了制定。例如在发送数据的时候,如果不进行绑定,则会临时选择一个随机的端口。

3.2 接收函数recvfrom()/recv()

当客户端成功建立了一个套接字文件描述符并建立了合适的strcut sockaddr结构后,或者服务器端成功将套接字文件描述符和地址结构绑定后,可以使用recv()故意整个recvfrom()来接收到达此套接字文件描述符上的数据或者在这个套接字文件描述符上的等待数据的到来。

recv()函数和recvfrom()函数的原型如下:

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int s, void *buff, size_t len, int flags);
ssize_t recvfrom(int s, void *buff,size_t len, int flags, struct sockaddr *from, socklen_t *from)

3.3 发送函数sendto()/send()

当客户端成功建立了一个套接字文件描述符,并构建了合适的struct sockaddr结构后,或者服务器成功地将套接字文件描述符和地址结构绑定后,可以使用send()或者sendto()函数来发送数据到某个主机上。

send()函数和sendto()函数的原型如下:

#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int s, const void *buff, size_t len, int flags);
ssize_t sento(int s, const void *buff, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);

四,实验代码实现

4.1 UDP客户端 dupcli01.cpp

  • 首先给出udp client端的代码,标准的实现方法,比较简单。
/*
 * udpcli01.cpp
 *
 *  Created on: 2015年4月23日
 *      Author: gzxultra
 */

    #include        <netinet/in.h>
    #include        <errno.h>
    #include        <stdio.h>
    #include        <stdlib.h>
    #include        <sys/socket.h>
    #include        <string.h>
    #include        <arpa/inet.h>
    #define MAXLINE                  4096
    #define LISTENQ                  1024    /* 2nd argument to listen() */
    #define SERV_PORT                9877
    #define SA      struct sockaddr

    void dg_cli(FILE *, int, const SA *, socklen_t);

    
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验三 网络信息扫描实验 一、实验目的 1、通过练习使用网络端口扫描器,可以了解目标主机开放的端口和服务程序,从而获取系统的有用信息,发现网络系统的安全漏洞。在实验中,我们将练习使用Superscan网络端口扫描工具。通过端口扫描实验,增强网络安全方面的防护意识。 2、通过使用综合扫描及安全评估工具,学习如何发现计算机系统的安全漏洞,并对漏洞进行简单分析,加深对各种网络和系统漏洞的理解。在实验中,我们将练习使用流光Fluxay5和SSS。 二、实验原理 1、网络端口扫描原理 一个开放的网络端口就是一条与计算机进行通信的信道,对网络端口的扫描可以得到目标计算机开放的服务程序、运行的系统版本信息,从而为下一步的入侵做好准备。对网络端口的扫描可以通过执行手工命令实现,但效率较低;也可以通过扫描工具实现,效率很高。扫描工具是对目标主机的安全性弱点进行扫描检测的软件。它一般具有数据分析功能,通过对端口的扫描分析,可以发现目标主机开放的端口和所提供的服务,以及相应服务软件版本和这些服务及软件的安全漏洞,从而能及时了解目标主机存在的安全隐患。 扫描工具根据作用的环境不同,可分为两种类型:网络漏洞扫描工具和主机漏洞扫描工具。主机漏洞扫描工具是指在本机运行的扫描工具,以期检测本地系统存在的安全漏洞。网络漏洞扫描工具是指通过网络检测远程目标网络和主机系统所存在漏洞的扫描工具。本实验主要针对网络漏洞扫描工具进行介绍。 1)端口的基础知识 为了了解扫描工具的工作原理,首先简单介绍一下端口的基本知识。 端口是TCP协议中所定义的,TCP协议通过套接字(socket)建立起两台计算机之间的网络连接。套接字采用[IP地址:端口号]的形式来定义,通过套接字中不同的端口号可以区别同一台计算机上开启的不同TCP和UDP连接进程。对于两台计算机间的任一个TCP连接,一台计算机的一个[IP地址:端口]套接字会和另一台计算机的一个[IP地址:端口]套接字相对应,彼此标识着源端、目的端上数据传输的源进程和目标进程。这样网络上传输的数据就可以由套接字中的IP地址和端口号找到需要传输的主机和连接进程了。由此可见,端口和服务进程一一对应,通过扫描开放的端口,就可以判断出计算机中正在运行的服务进程。 TCP/UDP的端口号在0~65535范围之内,其中1024以下的端口保留给常用的网络服务。例如:21端口为FTP服务,23端口为TELNET服务,25端口为SMTP服务,80端口为HTTP服务,110端口为POP3服务等。 2)扫描的原理 扫描的方式有多种,为了理解扫描原理,需要对TCP协议简要介绍一下。 一个TCP头的数据格式如图4-16所示。它括6个标志位,其中: SYN用来建立连接; ACK为确认标志位,例如,当SYN=1,ACK=0表示请求连接的数据;当SYN=1,ACK=1表示接受连接的数据。 FIN表示发送端已经没有数据可传了,希望释放连接。 RST位用于复位错误的连接,比如收到的一个数据分段不属于该主机的任何一个连接,则向远端计算机发送一个RST=1的复位数据,拒绝连接请求。 根据上面介绍的知识,下面我们介绍基于TCP和UDP协议的几种端口扫描方式。 1) TCP全连接扫描 TCP全连接扫描方法是利用TCP的三次握手,与目标主机建立正常的TCP连接,以判断指定端口是否开放。这种方法的缺点是非常容易被记录或者被检测出来。 2)TCP SYN扫描 本地主机向目标主机发送SYN数据段,如果远端目标主机端口开放,则回应SYN=1,ACK=1,此时本地主机发送RST给目标主机,拒绝连接。如果远端目标主机端口未开放,则会回应RST给本地主机。由此可知,根据回应的数据段可判断目标主机的端口是否开放。由于TCP SYN扫描没有建立TCP正常连接,所以降低了被发现的可能,同时提高了扫描性能。 3)TCP FIN扫描 本地主机向目标主机发送FIN=1,如果远端目标主机端口开放,则丢弃此,不回应;如果远端目标主机端口未开放,则返回一个RST。FIN扫描通过发送FIN的反馈判断远端目标主机的端口是否开放。由于这种扫描方法没有涉及TCP的正常连接,所以使扫描更隐秘,也称为秘密扫描。这种方法通常适用于UNIX操作系统主机,但有的操作系统(如Windows NT)不管端口是否打开,都回复RST,这时这种方法就不适用了。 4)UDP ICMP扫描 这种方法利用了UDP协议,当向目标主机的一个未打开的UDP端口发送一个数据时,会返回一个ICMP_PORT_UNREACHABLE错误,这样就会发现关闭的端口。 5)ICMP 扫描 这种扫描方法利用了ICMP协议的功能,如果向目标主机发送一个协议项存在错误的IP数据,则根据反馈的ICMP错误报文,判断目标主机使用的服务。 6)间接扫
TCP和UDP是网络传输协议,用于在计算机网络上传输数据。TCP提供可靠的、面向连接的数据传输服务,而UDP则提供不可靠的、面向无连接的数据传输服务。 在双机通信实验中,可以使用TCP或UDP协议来实现数据传输。以下是基于TCP和UDP的双机通信实验的步骤: 1. 确定两台计算机的IP地址和端口号。其中一个计算机作为服务器,另一个计算机作为客户端。 2. 在服务器上创建一个套接字,并将其绑定到服务器的IP地址和端口号上。 3. 在客户端上创建一个套接字,并将其连接到服务器的IP地址和端口号上。 4. 客户端向服务器发送数据。 5. 服务器接收客户端发送的数据,并对数据进行处理。 6. 服务器向客户端发送处理后的数据。 7. 客户端接收服务器发送的数据,并进行处理。 8. 关闭连接。 对于TCP协议,可以使用Socket编程实现双机通信。服务器和客户端都可以使用Socket创建套接字,并使用Socket的bind、listen、accept、connect、send和receive方法来实现数据传输。 对于UDP协议,也可以使用Socket编程实现双机通信。服务器和客户端都可以使用Socket创建套接字,并使用Socket的bind、sendto和recvfrom方法来实现数据传输。由于UDP是面向无连接的,因此在发送数据时需要指定目标IP地址和端口号。在接收数据时,需要指定自己的IP地址和端口号。 需要注意的是,在实现双机通信时,需要考虑数据的正确性和完整性。TCP协议提供可靠的数据传输服务,可以确保数据的正确性和完整性。而UDP协议提供不可靠的数据传输服务,需要在应用层进行数据校验和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值