《原始套接字编程》课程设计报告.doc
《《原始套接字编程》课程设计报告.doc》由会员分享,可在线阅读,更多相关《《原始套接字编程》课程设计报告.doc(8页珍藏版)》请在冰豆网上搜索。
《原始套接字编程》
课程设计报告
姓名:
王延兴
班级:
9班
学号:
54110904
《原始套接字编程》课程设计报告
班级:
11级9班 学号:
54110904 姓名:
王延兴
一、设计任务分析
(一)实验环境
操作系统:
Windows
编程工具及集成开发环境:
VC++
(二)实验目的和要求
实验目的:
掌握原始套接字编程。
实验要求:
完成下列功能:
(1)利用RAWSOCKET捕获网络数据包的程序模型
SOCKET_STREAM流式套接字
SOCKET_DGRAM
SOCKET_RAW原始套接字
IPPROTO_IPIP协议
IPPROTO_ICMPINTERNET控制消息协议,配合原始套接字可以实现ping的功能
IPPROTO_IGMPINTERNET网关服务协议,在多播中用到
在AF_INET地址族下,有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW三种套接字类型。
SOCK_STREAM也就是通常所说的TCP,而SOCK_DGRAM则是通常所说的UDP,而SOCK_RAW则是用于提供一些较低级的控制的;第3个参数依赖于第2个参数,用于指定套接字所用的特定协议,设为0表示使用默认的协议。
RAWSOCKET能够对较低层次的协议直接访问,网络监听技术很大程度上依赖于它。
(2)能够抓取第二节课的并发服务器程序的服务器端或客户端的应用层数据,即:
时间值,打印输出。
二、设计方案
同一台主机不同进程可以用进程号来唯一标识,但是在网络环境下进程号并不能唯一标识该进程。
TCP/IP主要引入了网络地址、端口和连接等概念来解决网络间进程标识问题。
套接字(Socket)是一个指向传输提供者的句柄,TCP/IP协议支持3种类型的套接字,分别是流式套接字、数据报式套接字和原始套接字。
流式套接字(SOCKET_STREAM)提供了面向连接、双向可靠的数据流传输服务。
数据报式套接字(SOCKET_DGRAM)提供了无连接服务,不提供无错保证。
原始套接字(SOCKET_RAW)允许对较低层次的协议直接访问,比如IP、ICMP协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,因为RAWSOCKET可以自如地控制Windows下的多种协议,能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。
比如,我们可以通过RAWSOCKET来接收发向本机的ICMP、IGMP协议包,或者接收TCP/IP栈不能够处理的IP包,也可以用来发送一些自定包头或自定协议的IP包。
网络监听技术很大程度上依赖于SOCKET_RAW。
本实验采用原始套接字进行捕获通过本主机的包并对本主机的包进行处理。
u各个函数功能:
char*GetProtocol(intproto)//获得协议类型
send(CientSocket,tmp,(int)strlen(tmp),0);发送数据
recv(CientSocket,RecvBuffer,MAX_PATH,0);接收数据
WSAStartup(MAKEWORD(2,2),&Ws)初始化套接字类库
socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);创建套接字
bind(ServerSocket,(structsockaddr*)&LocalAddr,sizeof(LocalAddr));绑定套接字
listen(ServerSocket,10);侦听,队列大小为10
u设计思想:
采用原始套接字进行捕获通过本主机的包并对本主机的包进行处理。
三、详细设计
头文件ip.h:
详细代码:
//定义标准的的TCP头和IP头
#defineURG0x20
#defineACK0x10
#definePSH0x08
#defineRST0x04
#defineSYN0x02
#defineFIN0x01
typedefstruct_iphdr//定义IP首部
{
unsignedcharh_verlen;//4位首部长度+4位IP版本号
unsignedchartos;//8位服务类型TOS
unsignedshorttotal_len;//16位总长度(字节)
unsignedshortident;//16位标识
unsignedshortfrag_and_flags;//3位标志位
unsignedcharttl;//8位生存时间TTL
unsignedcharproto;//8位协议(TCP,UDP或其他)
unsignedshortchecksum;//16位IP首部校验和
unsignedintsourceIP;//32位源IP地址
unsignedintdestIP;//32位目的IP地址
}IP_HEADER;
typedefstruct_tcphdr//定义TCP首部
{
USHORTth_sport;//16位源端口
USHORTth_dport;//16位目的端口
unsignedintth_seq;//32位序列号
unsignedintth_ack;//32位确认号
unsignedcharth_lenres;//4位首部长度/6位保留字
unsignedcharth_flag;//6位标志位
USHORTth_win;//16位窗口大小
USHORTth_sum;//16位校验和
USHORTth_urp;//16位紧急数据偏移量
}TCP_HEADER;
//定义ICMP首部
typedefstructicmp_hdr
{
unsignedchari_type;//类型
unsignedchari_code;//代码
unsignedshorti_cksum;//校验码
unsignedshorti_id;//非标准的ICMP首部
unsignedshorti_seq;
unsignedlongtimestamp;
}ICMP_HEADER;
typedefstructudp_hdr//8Bytes定义udp首部
{
unsignedshortuh_sport;
unsignedshortuh_dport;
unsignedshortuh_len;
unsignedshortuh_sum;
}UDP_HEADER;
源文件:
详细代码:
#include
#include
#pragmacomment(lib,"ws2_32")
#defineSIO_RCVALL_WSAIOW(IOC_VENDOR,1)
structip//定义IP首部
{
unsignedcharh_verlen;//4位首部长度,4位IP版本号
unsignedchartos;//8位服务类型TOS
unsignedshortip_length;//16位总长度(字节)
unsignedshortident;//16位标识
unsignedshortfrag_and_flags;//3位标志位
unsignedcharttl;//8位生存时间TTL
unsignedcharproto;//8位协议(TCP,UDP或其他)
unsignedshortchecksum;//16位IP首部校验和
unsignedintsourceIP;//32位源IP地址
unsignedintdestIP;//32位目的IP地址
};
//定义TCP首部
structtcp
{
USHORTth_sport;//16位源端口
USHORTth_dport;//16位目的端口
unsignedintth_seq;//32位序列号
unsignedintth_ack;//32位确认号
unsignedcharth_lenres;//4位首部长度/6位保留字
unsignedcharth_flag;//6位标志位
USHORTth_win;//16位窗口大小
USHORTth_sum;//16位校验和
USHORTth_urp;//16位紧急数据偏移量
};
voidmain()
{
intsock,bytes_recieved,fromlen;
charbuffer[65535];
structsockaddr_infrom;
structip*ip;
structtcp*tcp;
WORDwVersionRequested;//版本号
WSADATAwsaData;//启动SOCKET的
interr;
wVersionRequested=MAKEWORD(2,2);//建立版本
err=WSAStartup(wVersionRequested,&wsaData);//启用socket
if(err!
=0)//如果返回值不等于0,那么表示出错,直截退出程序
{
return;
}
sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP);
boolflag=true;
setsockopt(sock,IPPROTO_IP,2,(char*)&flag,sizeof(flag));
sockaddr_inaddr;
addr.sin_family=AF_INET;
addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//IP设置
addr.sin_port=htons(0);
if(SOCKET_ERROR==bind(sock,(sockad