第一篇:计算机网络 课程设计 发送TCP数据包
课设名称:发送TCP数据包
班级:
学号:
姓名:
指导老师: 日期: 2012.6.15
计算机网络课程设计报告
目录
一.设计题目与要求........................................................................................................2
1.设计题目................................................................................................................2
2.设计要求................................................................................................................2
二.需求分析...................................................................................................................2三.详细设计...................................................................................................................2
1.创建一个原始套接字,并设置IP头选项.................................................................3
2.构造IP头和TCP头...............................................................................................3
3.计算校验和的子函数..............................................................................................4
4.流程图...................................................................................................................6
四.调试分析...................................................................................................................7
五.运行结果...................................................................................................................7
六.总结..........................................................................................................................8
七.源程序......................................................................................................................9
发送TCP数据包
一.设计题目与要求
1.设计题目
发送TCP数据包 2.设计要求
本设计的功能是填充一个TCP数据包,并发送给目的主机。
1)以命令行形式运行:TCP source_ip source_port dest_ip dest_port,其中SendTCP是程序名,source_ip为源端IP地址,source_port为源端口号,dest_ip为目的地址,dest_port为目的端口号。
2)其他的TCP头部参数请自行设定。3)数据字段为“hello”。
4)成功发送后在屏幕上输出“send OK”。
二.需求分析
1.本程序需完成发送一个TCP数据包给目的主机
2.程序的输入:TCP source_ip source_port dest_ip dest_port,然后根据提示输入要发送的数据,回车即可。
3.程序的输出:Send OK!
4.测试数据 TCP 192.168.1.100 200 192.168.1.101 200
三.详细设计
本课程设计的目标是发送一个TCP数据包,可以利用原始套接字来完成这个工作。整个程序由初始化原始套接字和发送TCP数据包两个部分组成。
2发送TCP数据包
1.创建一个原始套接字,并设置IP头选项
SOCKET sock;sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);或者:
sock=WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);这里,设置了SOCK_RAW标志,表示我们声明的是一个原始套接字类型。为使用发送接收超时设置,必须将标志位置位置为WSA_FLAG_OVERLAPPED。在本课程设计中,发送TCP包时隐藏了自己的IP地址,因此我们要自己填充IP头,设置IP头操作选项。其中flag设置为ture,并设定 IP_HDRINCL 选项,表明自己来构造IP头。
setsockopt(sock, IPPROTO_IP, IP_HDRINCL,(char *)&Flag, sizeof(Flag));int timeout=1000; setsockopt(sock, sizeof(timeout));在这里我们使用基本套接字SOL_SOCKET,设置SO_SNDTIMEO表示使用发送超时设置,超时时间设置为1000ms。2.构造IP头和TCP头
这里,IP头和TCP头以及TCP伪部的构造请参考下面它们的数据结构。
typedef struct _iphdr //定义IP首部 { UCHAR h_lenver;//4位首部长度+4位IP版本号 UCHAR tos;//8位服务类型TOS
USHORT total_len;//16位总长度(字节)USHORT ident;//16位标识
USHORT frag_and_flags;//3位标志位 UCHAR ttl;//8位生存时间 TTL
UCHAR proto;//8位协议(TCP, UDP 或其他)
SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,3发送TCP数据包
USHORT checksum;//16位IP首部校验和 ULONG sourceIP;//32位源IP地址
ULONG destIP;//32位目的IP地址
}IP_HEADER;typedef struct psd_hdr //定义TCP伪首部 { ULONG saddr;ULONG daddr;//源地址 //目的地址
UCHAR mbz;//没用 UCHAR ptcl;
USHORT tcpl;//协议类型 //TCP长度
}PSD_HEADER;typedef struct _tcphdr //定义TCP首部 { USHORT th_sport;//16位源端口 USHORT th_dport;//16位目的端口 ULONG th_seq;//32位序列号 ULONG th_ack;//32位确认号
UCHAR th_lenres;//4位首部长度/6位保留字 UCHAR th_flag;//6位标志位 USHORT th_win;//16位窗口大小 USHORT th_sum;//16位校验和 USHORT th_urp;//16位紧急数据偏移量
}TCP_HEADER;
3.计算校验和的子函数
在填充数据包的过程中,需要调用计算校验和的函数checksum两次,分别用于校验IP头和TCP头部(加上伪头部),其实现代码如下:
USHORT checksum(USHORT *buffer, int size)
4发送TCP数据包
{ unsigned long cksum=0;while(size >1){ cksum+=*buffer++;size-=sizeof(USHORT);} if(size){ cksum += *(UCHAR*)buffer;} cksum =(cksum >> 16)+(cksum & 0xffff);cksum +=(cksum >>16);return(USHORT)(~cksum);}
5发送TCP数据包
4.流程图
开始构造原始套接字并初始化填充IP首部计算IP首部校验和构造TCP伪首部填充TCP首部计算TCP首部校验和填充发送缓冲区填入目的地址发送数据包结束
6发送TCP数据包
四.调试分析
本程序流程简单,调试过程中没有出现大的问题。
调试过程中没有出现重大的语法错误,主要是运行的结果不理想,和预期的结果有差距。填充数据包的程序部分是不容易出错的。至于数据包的发送,由于是利用函数sendto()来实现的,而sendto()是面向UDP的,将协议类型修改为UDP(Header.proto=IPPROTO_UDP;)后,调试运行成功,问题得到解决。
调试时,要添加 #include
五.运行结果
1.输入:TCP 192.168.1.100 200 192.168.1.101 200
7发送TCP数据包
2.输入要发送的字符串:“hello”按Ctrl+Z发送
六.总结
通过本次课程设计,我对发送TCP数据包的原理有了一定的了解。理解了TCP数据报的报文格式、TCP连接时的三次握手和TCP连接结束时的四次握手的过程及它们的作用。此外,在设计过程中,通过查阅资料,也让我对TCP的三大特点(流量控制、差错控制、拥塞控制)有了认识。,在课程设计过程中,由于编程知识的欠缺,使我在课程设计过程中不是很顺利,编程知识的欠缺是我的最大障碍,不过,这也给了我动力,我会努力去学好编程的相关知识,为以后的学习和工作打下基础。最后,感谢老师安排了此次课程设计。
发送TCP数据包
七.源程序
#include
#define IPVER 4 //IP协议预定 #define MAX_BUFF_LEN 65500 //发送缓冲区最大值
typedef struct ip_hdr //定义IP首部 {
UCHAR h_verlen;//4位首部长度,4位IP版本号 UCHAR tos;//8位服务类型TOS USHORT total_len;//16位总长度(字节)USHORT ident;//16位标识 USHORT frag_and_flags;//3位标志位 UCHAR ttl;//8位生存时间 TTL UCHAR proto;//8位协议(TCP, UDP 或其他)USHORT checksum;//16位IP首部校验和 ULONG sourceIP;//32位源IP地址 ULONG destIP;//32位目的IP地址
发送TCP数据包
}IP_HEADER;
typedef struct tsd_hdr //定义TCP伪首部 {
ULONG saddr;//源地址 ULONG daddr;//目的地址 UCHAR mbz;//没用 UCHAR ptcl;//协议类型 USHORT tcpl;//TCP长度
}PSD_HEADER;
typedef struct tcp_hdr //定义TCP首部 {
USHORT th_sport;//16位源端口 USHORT th_dport;//16位目的端口 ULONG th_seq;//32位序列号 ULONG th_ack;//32位确认号
UCHAR th_lenres;//4位首部长度/6位保留字 UCHAR th_flag;//6位标志位 USHORT th_win;//16位窗口大小 USHORT th_sum;//16位校验和
USHORT th_urp;//16位紧急数据偏移量
}TCP_HEADER;
//CheckSum:计算校验和的子函数
USHORT checksum(USHORT *buffer, int size){ unsigned long cksum=0;while(size >1)
发送TCP数据包
{ cksum+=*buffer++;size-=sizeof(USHORT);} if(size){ cksum += *(UCHAR*)buffer;} cksum =(cksum >> 16)+(cksum & 0xffff);cksum +=(cksum >>16);return(USHORT)(~cksum);}
int ReadData(char *str,int maxlen){ int readlen=0;char ch=NULL;if(str==NULL||maxlen<=0){
printf(“ReadData Error!!n”);
return 0;//failed } printf(“Input Data(End By Ctrl+Z): n”);while(maxlen){
ch=getchar();
if(ch==EOF)break;
str[readlen++]=ch;maxlen--;
发送TCP数据包
} } str[readlen]=NULL;return readlen;int main(int argc, char* argv[]){ WSADATA WSAData;SOCKET sock;
IP_HEADER ipHeader;TCP_HEADER tcpHeader;PSD_HEADER psdHeader;
char Sendto_Buff[MAX_BUFF_LEN];//发送缓冲区
unsigned short check_Buff[MAX_BUFF_LEN];//检验和缓冲区 char tcp_send_data[1000];
BOOL flag;int rect,nTimeOver;if(argc!= 5){ printf(“Usage: SendTcp soruce_ip source_port dest_ip dest_port n”);return false;} read_data_len=ReadData(tcp_send_data,1000);int read_data_len=0;
发送TCP数据包
if(read_data_len<=0)return 1;
if(WSAStartup(MAKEWORD(2,2), &WSAData)!=0){ printf(“WSAStartup Error!n”);return false;} if((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0, WSA_FLAG_OVERLAPPED))==INVALID_SOCKET){ printf(“Socket Setup Error!n”);return false;} flag=true;if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&flag,sizeof(flag))==SOCKET_ERROR){ printf(“setsockopt IP_HDRINCL error!n”);return false;} nTimeOver=1000;if(setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,(char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR){ printf(“setsockopt SO_SNDTIMEO error!n”);return false;}
发送TCP数据包
//填充IP首部
ipHeader.h_verlen=(IPVER<<4 | sizeof(ipHeader)/sizeof(unsigned long));ipHeader.tos=(UCHAR)0;ipHeader.total_len=htons((unsigned short)sizeof(ipHeader)+sizeof(tcpHeader)+read_data_len);ipHeader.ident=0;//16位标识 ipHeader.frag_and_flags=0;//3位标志位 ipHeader.ttl=128;//8位生存时间 ipHeader.proto=IPPROTO_TCP;//协议类型 ipHeader.checksum=0;//检验和暂时为0 ipHeader.sourceIP=inet_addr(argv[1]);//32位源IP地址 ipHeader.destIP=inet_addr(argv[3]);//32位目的IP地址
//计算IP头部检验和
memset(check_Buff,0,MAX_BUFF_LEN);memcpy(check_Buff,&ipHeader,sizeof(IP_HEADER));ipHeader.checksum=checksum(check_Buff,sizeof(IP_HEADER));
//构造TCP伪首部
psdHeader.saddr=ipHeader.sourceIP;psdHeader.daddr=ipHeader.destIP;psdHeader.mbz=0;psdHeader.ptcl=ipHeader.proto;psdHeader.tcpl=htons(sizeof(TCP_HEADER)+read_data_len);
//填充TCP首部
tcpHeader.th_dport=htons(atoi(argv[4]));//16位目的端口号 tcpHeader.th_sport=htons(atoi(argv[2]));//16位源端口号
发送TCP数据包
tcpHeader.th_seq=0;//SYN序列号 tcpHeader.th_ack=0;//ACK序列号置为0 //TCP长度和保留位
tcpHeader.th_lenres=(sizeof(tcpHeader)/sizeof(unsigned long)<<4|0);tcpHeader.th_flag=2;//修改这里来实现不同的标志位探测,2是SYN,1是//FIN,16是ACK探测 等等
tcpHeader.th_win=htons((unsigned short)16384);//窗口大小 tcpHeader.th_urp=0;//偏移大小 tcpHeader.th_sum=0;//检验和暂时填为0
//计算TCP校验和
memset(check_Buff,0,MAX_BUFF_LEN);memcpy(check_Buff,&psdHeader,sizeof(psdHeader));
memcpy(check_Buff+sizeof(psdHeader),&tcpHeader,sizeof(tcpHeader));
//填充发送缓冲区
memset(Sendto_Buff,0,MAX_BUFF_LEN);memcpy(Sendto_Buff,&ipHeader,sizeof(IP_HEADER));
memcpy(Sendto_Buff+sizeof(IP_HEADER), &tcpHeader,sizeof(TCP_HEADER));memcpy(check_Buff+sizeof(PSD_HEADER)+sizeof(TCP_HEADER), tcp_send_data,read_data_len);tcpHeader.th_sum=checksum(check_Buff,sizeof(PSD_HEADER)+ sizeof(TCP_HEADER)+read_data_len);memcpy(Sendto_Buff+sizeof(IP_HEADER)+sizeof(TCP_HEADER), tcp_send_data,read_data_len);
发送TCP数据包
int datasize=sizeof(IP_HEADER)+sizeof(TCP_HEADER)+read_data_len;//发送数据报的目的地址 SOCKADDR_IN dest;memset(&dest,0,sizeof(dest));dest.sin_family=AF_INET;dest.sin_addr.s_addr=inet_addr(argv[3]);dest.sin_port=htons(atoi(argv[4]));
rect=sendto(sock,Sendto_Buff,datasize, 0,(struct sockaddr*)&dest, sizeof(dest));if(rect==SOCKET_ERROR){ printf(“send error!:%dn”,WSAGetLastError());return false;} else
closesocket(sock);WSACleanup();return 1;} printf(“nsend ok!n”);
第二篇:计算机网络 课程设计 IP数据包解析
课设名称:IP数据包解析
班
级:
学
号:
姓
名:
指导老师:
日期: 2012.6.15
计算机网络课程设计报告
目录
1.课程设计目的..............................................................1
2.课程设计要求..............................................................1
3.程序设计分析..............................................................1
3.1 网卡设置................................................................1
3.2 使用套接字..............................................................2
3.2.2 接收数据包.............................................................2
3.3 定义IP头部的数据结构....................................................3
3.4 IP包的解析..............................................................3
3.5 协议的定义..............................................................4
3.6捕获处理.................................................................4
4.运行结果..................................................................5
5.总结......................................................................5
6.源程序代码................................................................6
Ip数据包解析
1.课程设计目的
本课程设计的目的就是设计一个捕获并解析IP数据包的程序,并根据这个程序,说明IP数据包的结构及IP协议的相关问题,从而对IP层的工作原理有更好的理解和认识。
2.课程设计要求
本设计的目标是捕获网络中的IP数据包,解析数据包的内容,将结果显示在标准输出上,并同时写入日志文件。程序的具体要求如下:
1)以命令行形式运行:ipparse logfile,其中ipparse是程序名, 而logfile则代表记录结果的日志文件。
2)在标准输出和日志文件中写入捕获的IP包的版本、头长度、服务类型、数据包总长度、数据包标识、分段标志、分段偏移值、生存时间、上层协议类型、头校验和、源IP地址和目的IP地址等内容。
3)当程序接收到键盘输入Ctrl+C时退出
3.程序设计分析
3.1 网卡设置
为了获取网络中的IP数据包,必须对网卡进行编程,在这里使用套接字(socket)进行编程。但是,在通常情况下,网络通信的套接字程序只能响应与自己硬件地址相匹配的数据包或是以广播形式发出的数据包。对于其他形式的数据包,如已到达网络接口,但却不是发送到此地址的数据包,网络接口在骓投递地
Ip数据包解析
址并非自身地址之后将不引起响应,也就是说应用程序无法收取与自己无关的数据包。我们要想获取网络设备的所有数据包,就是需要将网卡设置为混杂模式。
3.2 使用套接字
套接字分为三种,即流套接字(Stream socket)、数据报套接字(Datagram Socket)和原始套接字(Raw Socket)。要进行IP层数据包的接收和发送,应使用原始套接字。创建原始套接字的代码如下: Socket sock: Sock=wsasocket(af_inet,sock_raw,ipproto-ip,null,0,wsa-flag-overlapped): 本设计不用考虑超时情况。
创建套接后,IP头就会包含在接收数据包中。然后,我可以设置IP头操作选项,调用setsockopt函数。其中flag设置为true,并设定IP-HDRINCL选项,表明用户可以亲自对IP头进行处理。最后使用bind()函数将socket绑定到本地网卡上。绑定网卡后,需用WSAIoctl()函数把网卡设置为混杂模式,使网卡能够接收所有的网络数据。如果接收的数据包中的协议类型和定义的原始套接字匹配,那么接收的数据就拷贝到套接字中,因此,网卡就可以接收所有经过的IP包。
3.2.2 接收数据包
在程序中可使用recv()函数接收经过的IP包。该函数有四个参数,第一个参数接收操作所用的套接字描述符;第二个参数接收缓冲区的地址;第三个参数接收缓冲区的大小,也就是所要接收的字节数;第四个参数是一个附加标志,如
Ip数据包解析
果对所发送的数据没特殊要求,直接设为0。因为IP数据包的最大长度是65535B,因此缓冲区的大小不能小于65535B。设置缓冲区后,可利用循环来反复监听接收IP包,用recv()函数实现接收功能。
3.3 定义IP头部的数据结构
程序需要定义一个数据结构表示IP头部。其代码如下: struct IP_HEADER { unsigned short ip_version, /*IP的版本号 */ ip_hdr_len; /*IP包头的长度*/ ip_tos; /*IP包的服务类型*/ ip_total_len; /*IP包的总长度*/ ip_id; /*IP包的分段标识*/ ip_flags; /*IP包的分段标志*/ ip_frag_offset; /*IP包的分段偏移*/ ip_ttl; /*IP包的生存时间*/ ip_proto; /*IP包的高层协议*/ ip_hdr_chksum;/*IP包的校验和*/ struct IPADDRESS ip_src_addr; /*IP包的源IP地址*/ ip_dest_addr; /*IP包的目的IP地址*/ }ipheader;3.4 IP包的解析
Ip数据包解析
解析IP包的字段有两种策略。针对长度为8位、16位和32位的字段(或子字段)时,可以利用IP-HEADER的成员直接获取。要解析长度不是8位倍数的字段(或子字段)时,可以利用C语言中的移位以人、及与、或操作完成。
3.5 协议的定义
(包含相应的头文件#include #include):
DWORD dwIoControlCode=SIO_RCVALL, /*接收所有的IP包*/ dwProtocol=IPPROTO_IP;/*协议类型为IP*/
3.6捕获处理
1.加载 Winsock;
2.创建一个接收原始IP包的socket连接; 3.绑定到一个接口;
4.进行WSAIoctl设置,接收所有的IP数据包。代码如下:
if(WSAIoctl(s, dwIoControlCode, &optval, sizeof(optval), NULL, 0, &dwBytesRet, NULL, NULL)== SOCKET_ERROR)5.接着设定一个线程进行捕获:(1)创建一个接收IP包的链表头;
(2)设置一个标识,为真,则不断进行IP包的捕获;(3)建立一个新的结点,将捕获的数据包加入到该结点;
(4)如果链表的长度达到指定的长度,创建一个线程对该链表的IP包进行解析;再设置一个在IP数据包链表不足给定的长度,而又中止IP捕获时,对链表的处理;
Ip数据包解析
(5)为下一个IP包链表创建一个链表头。
6.建立一个进行IP包解析并显示的线程,进行解析IP数据包,然后显示IP数据包。
4.运行结果
截获IP数据包程序运行结果如下:
5.总结
在本次课程设计中,通过多次上机的实践,充分利用所学的计算机网络以及socket编程与C语言编程的知识,并上网搜索一部分相当资料,粗略设计出该程序。
通过本次课程设计,充分运用了所学的计算机网络知识,设计出了如何解析IP数据包,从而更加深刻的了解到了IP数据包的结构及IP协议的相关问题,从而对IP层的工作原理有更好的理解和认识。
Ip数据包解析
在课程设计的过程也碰到的不少问题。例如:对IP数据包的结构不了解、IP层工作原理也不熟悉、C语言编程基础差等一系列问题。让我认识到了自己的很大不足,在以后的学习过程中还将努力提高。
6.源程序代码
#include “winsock2.h” #include “ws2tcpip.h” #include “iostream.h” #include “stdio.h”
#pragma comment(lib, “ws2_32.lib”)
#define IO_RCVALL _WSAIOW(IOC_VENDOR,1)#define BUFFER_SIZE 65535
/* 定义IP头部数据结构 */ typedef struct _IP_HEADER{
union{
};BYTE ServiceType;//服务类型 WORD TotalLen;//总长度 WORD ID;//标识 union{
};BYTE TimeToLive;WORD Flags;WORD FragOff;BYTE Version;//版本(前4位)
BYTE HdrLen;//报头标长(后四位),IP头长度
Ip数据包解析
BYTE Protocol;WORD HdrChksum;DWORD SrcAddr;DWORD DstAddr;BYTE Options;}IP_HEADER;
//逐位解析IP头中的信息,获取版本号 void getVersion(BYTE b,BYTE &version){ }
void getIHL(BYTE b,BYTE &result){ }
//解析服务类型
char * parseServiceType_getProcedence(BYTE b){
version = b>>4;result =(b & 0x0f)*4;switch(b>>5){
case 7: return “Network Control”;case 6: return “Internet work Control”;case 5: return “CRITIC/ECP”;case 4: return “Flash Override”;
Ip数据包解析
}
} case 3: return “Falsh”;case 2: return “Immediate”;case 1: return “Priority”;case 0: return “Routine”;default: return “Unknown”;char * parseServiceType_getTOS(BYTE b){
b=(b>>1)&0x0f;switch(b){ case 0: return “Normal service”;
case 1:
return “Minimize monetary cost”;case 2: return “Maximize reliability”;case 4: return “Maximize throughput”;case 8: return “Minimize delay”;case 15: return “Maximize security”;default: return “Unknown”;
Ip数据包解析
} } /* 获取禁止分片标志和分片标志 */ void getFlags(WORD w,BYTE &DF, BYTE &MF){
}
/* 获取分片偏移量 */ void getFragoff(WORD w,WORD &fragoff){ }
//获取协议
char * getProtocol(BYTE Protocol){
DF=(w>>14)&0x01;MF=(w>>13)&0x01;fragoff=w&0x1ffff;switch(Protocol){
case 1: return “ICMP”;case 2: return “IGMP”;case 3: return “GGP”;case 4: return “IP in IP ”;case 6: return “TCP”;case 8: return “EGP”;case 17:
Ip数据包解析
}
} return “UDP”;case 41: return “IPv6”;case 46: return “OSPF”;default: return “UNKNOWN”;/* 解析IP数据包 */ void ipparse(FILE * file,char *buffer){
IP_HEADER ip = *(IP_HEADER *)buffer;fseek(file,0,SEEK_END);BYTE version;getVersion(ip.Version,version);fprintf(file,“版本=IPV%drn”,version);BYTE headerLen;getIHL(ip.HdrLen,headerLen);fprintf(file,“头长度=%d(BYTE)rn”,headerLen);fprintf(file,“服务类型=%s,%srn”, parseServiceType_getProcedence(ip.ServiceType), parseServiceType_getTOS(ip.ServiceType));fprintf(file,“数据报长度=%d(BYTE)rn”,ip.TotalLen);fprintf(file,“数据报ID=%drn”,ip.ID);/* DF表示禁止分片标志,MF表示分片标记 */ BYTE DF,MF;getFlags(ip.Flags,DF,MF);fprintf(file,“分段标志 DF=%d,MF=%drn”,DF,MF);WORD fragOff;
Ip数据包解析
} getFragoff(ip.FragOff,fragOff);fprintf(file,“分段偏移值=%drn”,fragOff);fprintf(file,“生存期=%d(hops)rn”,ip.TimeToLive);fprintf(file,“协议=%srn”,getProtocol(ip.Protocol));fprintf(file,“头校验和=0x%0xrn”,ip.HdrChksum);fprintf(file,“源IP地址=%srn”,inet_ntoa(*(in_addr*)&ip.SrcAddr));fprintf(file,“目的IP地址=%srn”,inet_ntoa(*(in_addr*)&ip.DstAddr));fprintf(file,“__________________________________rn”);
/* 程序入口 */ int main(int argc,char *argv[]){
/* cmd参数 */ if(argc!=2){
} printf(“usage error!n”);return-1;FILE *file;/* 以读写的方式建立一个文本文件logfile.txt */ if((file=fopen(argv[1],“w+”))==NULL){
}
WSAData wsData;/* 启动2.2版本的Socket,并将Socket版本信息保存到wsData中 */ if(WSAStartup(MAKEWORD(2,2),&wsData)!=0){ printf(“WSA startup failed!n”);return-1;printf(“fail to open file %s”,“logfile.txt”);return-1;
Ip数据包解析
} fprintf(file,“Socket初始化...rn”);fprintf(file,“==================================rn”);fprintf(file,“描述:%srn”,wsData.szDescription);fprintf(file,“状态:%srn”,wsData.szSystemStatus);fprintf(file,“==================================rn”);SOCKET sock;/* 创建原始套接字 */ if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP))==INVALID_SOCKET){
}
BOOL flag=true;/* 设置IP头操作选项 */ if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(CHAR*)&flag,sizeof(flag))==SOCKET_Eprintf(“Can not create socket!n”);return-1;RROR){
} printf(“setsockopt failed!n”);return-1;char hostName[128];/* 获取本地主机名 */ if(gethostname(hostName,100)==SOCKET_ERROR){
}
hostent *pHostIP;printf(“gethostname failed!n”);return-1;
Ip数据包解析
R){
/* 根据主机名获取主机信息 */ if((pHostIP=gethostbyname(hostName))==NULL){
} printf(“Hostname: %srn”,pHostIP->h_name);printf(“IPAddress: %srn”,inet_ntoa(*((struct in_addr *)pHostIP->h_addr)));printf(“gethostbyname failed!n”);return-1;/* 封装IP地址信息 */ sockaddr_in addr_in;addr_in.sin_addr=*(in_addr*)pHostIP->h_addr_list[0];addr_in.sin_family=AF_INET;addr_in.sin_port=htons(6000);//监听的端口号 /* 把Socket绑定到本地网卡 */ if(bind(sock,(PSOCKADDR)&addr_in,sizeof(addr_in))==SOCKET_ERROR){
}
DWORD dwBufferLen[10];DWORD dwBufferInLen=1;DWORD dwBytesReturned=0;/* 设置网卡为混杂模式 */ if(WSAIoctl(sock,IO_RCVALL,&dwBufferInLen,sizeof(dwBufferInLen), printf(“bind failed”);return-1;&dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL)==SOCKET_ERRO
} printf(“icotlsocket failedn”);return-1;
Ip数据包解析
}
char buffer[BUFFER_SIZE];printf(“=============开始解析=============rn”);while(true){
} /* 解除Socket绑定 */ if(WSACleanup()==SOCKET_ERROR){
} /* 关闭文件 */ fclose(file);return 0;printf(“WSACleanup failed!n”);return-1;/* 从套接字接收IP数据报 */ int size=recv(sock,buffer,BUFFER_SIZE,0);if(size>0){
} ipparse(stdout,buffer);ipparse(file,buffer);
第三篇:计算机网络课程设计_IP数据包的捕获与分析[范文]
CENTRAL SOUTH UNIVERSITY
计算机网络课程设计报告
目录
第一章 课程设计的目的与要求..........................错误!未定义书签。1.1 课程设计的目的...................................错误!未定义书签。1.2 课程设计的要求....................................................1 第二章 课程设计的内容.................................................3 2.1 课程设计的内容....................................................3 2.2 内容的要求........................................................3 第三章 程序分析与设计.................................................4 3.1 IP数据包..........................................................4 3.1.1 IP数据包的格式说明..........................................4 3.1.2 IP数据包的格式..............................................4 3.1.3 IP数据包的C++定义...........................................5 3.1.4 IP数据包的解析..............................................6 3.2 套接字............................................................7 3.1.4 套接字的使用.................................................7 3.1.4 使用原始套接字...............................................7 3.3 接受数据包........................................................7 第四章 实验结果.......................................................10 4.1 程序截图.........................................................10 第五章 总结..........................................................11 5.1 实验心得.........................................................11 第六章 附录..........................................................12 6.1 源代码...........................................................12
第一章 课程设计的目的与要求
1.1 课程设计的目的
计算机网络课程设计的目的,是为了让学生更深入地掌握计算机网络的核心内容,实现理论与实践相结合。让学生用具体的实践成果,体现对理论知识的掌握程度。有利于学生提高计算机网络的实践能力,加深对计算机网络理论知识的理解。
1.2 课程设计的要求
(1)编写程序,实现系统的基本功能,鼓励自行增加新功能;
(2)要有用户界面:要求至少采用文本菜单界面;鼓励采用图形菜单界面;(3)写课程设计报告,内容包括: 封面(参见附录I)
需求分析:以无歧义的陈述说明程序设计的任务,强调的是程序要做什么?给出功能模块图和流程图。同时明确规定:输入的形式和输出值的范围;输出的形式;程序所能够达到的功能;测试数据,包括正确的输入及其输出结果和含有错误的输入及其输出结果。
概要设计:包括程序设计组成框图,程序中使用的存储结构设计说明(如果指定存储结构请写出该存储结构的定义)。
详细设计:包括模块功能说明(如函数功能、入口及出口参数说明,函数调用关系描述等),每个模块的算法设计说明(可以是描述算法的流程图)。其中源程序要按照写程序的规则来编写,结构清晰,重点函数的重点变量,重点功能部分要加上清晰的程序注释。
运行结果:包括典型的界面、输入和输出数据等;
总结:包括课程设计中遇到的问题,解决问题的过程及体会、收获、对课程设计的认识与思考等。
附录:包括主要程序清单,要有适当的注释,使程序容易阅读。
(4)课程设计报告书写规范参见附录II,不按照规范书写的,成绩不能评为“优”或“良”。
(5)无论在校外、校内,都要严格遵守学校和所在单位的学习和劳动纪律、1 规章制度,学生有事离校必须请假。课程设计期间,无故缺席按旷课处理;缺席 时间达四分之一以上者,其成绩按不及格处理。
第二章 课程设计的内容
2.1 课程设计的内容
本次实验的要求在网络环境,使用VC++编写程序实现捕获网络中的IP数据包,解析数据包的内容,将结果显示在标准输出上,并同时写入日志文件。
2.2 内容的要求
(1)以命令行形式运行(应如程序名+参数名):ipparse logfile,其中ipparse是程序名,而logfile为该程序所带参数,其代表记录结果的日志文件。(2)在标准输出和日志文件中写入捕获的IP包的版本、头长度、服务类型、数据包总长度、数据包标识、分段标志、分段偏移值、生存时间、上层协议类型、头校验和、源IP地址和目的IP地址等内容。(3)当程序接收到键盘输入Ctrl+C时退出。
第三章 程序设计与分析
3.1 IP数据包
3.1.1 IP数据包的格式说明
IP数据包格式包含了标头固定部分,标头可变部分和数据区三部分。IP数据报标头部分固定为20个字节,其中包含了12个参数域,各参数域隐含着网间协议的传输机制。IP具体的标头格式如图1所示。
各参数域的具体含义如下:
1)版本号:长度4位,表示所使用的IP协议的版本。IPv4版本号字段值为4;IPV6版本号字段号的值为6.2)标头长:长度4位,定义了一个以4B为一个单位的IP包的报头长度 3)服务类型:共8位,高3位组成优先级子域,随后4位组成服务类型子域。4)数据报总长度:总长度为2B(即6位)。定义了以字节为单位的数据报的总长度。5)重装标识:长度16位,用于识别IP数据报的编号,让目的主机判断新来的数据属于哪个分组。
6)分片标识:共3位,最高位为0;DF禁止分片标识。DF=0,可以分片;DF=1,不能分片。MF:分片标识。MF=0,表示接的是最后一个分片;MF=1,不是最后一个分片。
7)片偏移值:共13位,说明分片在整个数据报中的相对位置。
8)生存周期:8位,用来设置数据数据报在整个网络传输过程中的寿命。常以一个数据报可以经过的最多的路由器跳步数来控制。9)协议类型:共8位,表示该IP数据报的高层协议类型。10)标头校验和:共16位,用于存放检查报头错误的校验码。
11)源、宿主机地址:共32位,分别表示发送和接受数据报的源主机和宿主机的IP地址。
选项数据域:0-40B,用于控制和测试
3.1.2 IP数据包的格式
4位版本4位首部长度8位服务类型(TOS)3位标志8位协议32位源IP地址32位目的IP地址16位总长度(字节为单位)13位片偏移16位首部检验和16位标识8位生存时间(TTL)
3.1.3 IP数据包的C++定义 typedef struct _IP { union {
BYTE Version;// 版本
BYTE HdrLen;//IHT };BYTE ServiceType;// 服务类型 WORD TotalLen;// 总长
WORD ID;// 标识
union {
WORD Flags;// 标志
WORD FragOff;// 分段偏移
};BYTE TimeToLive;// 生命期
BYTE Protocol;// 协议
WORD HdrChksum;// 头校验和
DWORD SrcAddr;// 源地址
DWORD DstAddr;// 目的地址 BYTE Options;// 选项
} IP;
3.1.4 IP数据包的解析
通过IP_HEADER解析IP头各个字段的代码: /*获取版本字段*/ ip.Version>>4;/*获取头部长度字段*/ ip.HdrLen & 0x0f;/*获取服务类型字段中的优先级子域*/ ip.ServiceType>>5;/*获取服务类型字段中的TOS子域*/(ip.ServiceType>>1)&0x0f;/*获取总长度字段*/ ip.TotalLen;/*获取标识字段*/ ip.ID;/*解析标志字段*/ DF =(ip.Flags>>14)& 0x01;MF =(ip.Flags>>13)& 0x01;/*获取分段偏移字段*/ ip.FragOff & 0x1fff;/*获取生存时间字段*/ ip.TimeToLive;/*获取协议字段*/ ip.Protocol;/*获取头校验和字段*/ ip.HdrChksum;/*解析源IP地址字段*/ inet_ntoa(*(in_addr*)&ip.SrcAddr);/*解析目的IP地址字段*/ inet_ntoa(*(in_addr*)&ip.DstAddr);3.2 套接字
3.2.1 套接字的使用
本程序使用套接字socket编程,将网卡设为能够接受流经网卡的所有类型的数据包。首先,初始化套接字,然后监听数据包,解析数据包。
SOCKET sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP)用来创建套接字,其参数为通信发生的区字段和套接字的类型。
WSAIoctl(sock,IO_RCVALL ,&dwBufferInLen , sizeof(dwBufferInLen)函数用来把网卡设置为混杂模式。
recv(sock,buffer,65535,0)函数用来接收经过的IP包,其参数分别是套接字描述符,缓冲区的地址,缓冲区的大小。
3.2.1 使用原始套接字
要进行IP层数据包的接收和发送,应使用原始套接字。创建原始套接字的代码如下:
SOCKET sock;sock=WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0, WSA_FLAG_OVERLAPPED);在WSASoccket函数中,第一个参数指定通信发生的区字段,AF_INET是针对Internet的,允许在远程主机之间通信。第二个参数是套接字的类型,在AF_INET地址族下,有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW三种套接字类型。在这里,设置为SOCK_RAW,表示声明的是一个原始套接字类型。第三个参数依赖于第二个参数,用于指定套接字所有的特定协议,这里使用IP协议。第四个参数为WSAPROTOCOL_INFO位,该位可以置空。第五个参数保留,永远置0。第六个参数是标志位,WSA_FLAG_OVERLAPPED表明可以使用发送接收超时设置。
创建原始套接字后,IP头就会包含在接收的数据中。然后,可以设置IP头操作选项,调用setsockopt函数。其中flag设置为true,并设定IP_HDRINCL选项,表明用户可以亲自对IP头进行处理。
BOOL flag=true;setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(CHAR*)&flag,sizeof(flag));之后,使用如下代码完成对socket的初始化工作: /*获取主机名*/ char hostName[128];gethostname(hostName,100);/*获取本地IP地址*/ hostent * pHostIP;pHostIP = gethostbyname(hostName);/*填充SOCKADDR_IN结构的内容*/ sockaddr_in addr_in;addr_in.sin_addr = *(in_addr *)pHostIP->h_addr_list[0];addr_in.sin_family = AF_INET;addr_in.sin_port = htons(6000);/*绑定socket*/ bind(sock,(PSOCKADDR)&addr_in,sizeof(addr_in));填写sockaddr_in的内容时,其地址值应填写为本机IP地址,本机IP地址可以通过gethostbyname()函数获取;端口号可以随便填写,但不能与系统冲突;协议族应填为AF_INET。使用htons()函数可以将无符号短整型的主机数据转换为网络字节顺序的数据。最后使用bind(0函数将socket绑定到本机网卡上。绑定网卡后,需要用WSAIoctl()函数把网卡设置为混杂模式,使网卡能够接收所有网络数据,其关键代码如下:
#define SIO_RCVALL_WSAIOW(IOC_VENDOR,1)DWORD dwBufferLen[10];DWORD dwBufferInLen = 1;DWORD dwBytesReturned = 0;WSAIoct1(SnifferSocket, IO_RCVALL,&dwBufferInLen,sizeof(dwBufferInLen),&dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL);如果接收的数据包中的协议类型和定义的原始套接字匹配,那么接收到的数据就拷贝到套接字中。因此,网卡就可以接收所有经过的IP包。
3.3 接收数据包 在程序中可使用recv()函数接收经过的IP包。该函数有四个参数,第一个参数接收操作所用的套接字描述符;第二个参数接收缓冲区的地址;第三个参数接收缓冲区的大小,也就是所要接收的字节数;第四个参数是一个附加标志,如果对所发送的数据没特殊要求,直接设为0。因为IP数据包的最大长度是65535B,因此,缓冲区的大小不能小于65535B。设置缓冲区后,可利用循环来反复监听接收IP包,用RECV()函数实现接收功能的代码如下:
#define BUFFER_SIZE 65535 char buffer[BUFFER_SIZE];//while(true){ recv(sock,buffer,BUFFER_SIZE,0);// /*然后是解析接收的IP包*/ }
设置缓冲区 接收数据包
第四章 实验结果
4.1 程序截图
第五章 总结
通过这次课程设计,我们了解到关于计算机网络数据传送及处理过程中,软件起到了巨大的作用。熟悉了C++语言在计算机网络方面的应用,是一次难得的机会。此外,我还了解了网络通信协议的基本工作原理及套接字的使用,虽然刚开始的时候比较模糊,但是通过与同学共同探讨和网上查阅资料,最终我成功完成了实验。这次课程设计培养了我们基本掌握网络编程的基本思路和方法,让我们懂得如何去学习这类东西。同时提高我们对所学计算机网络理论知识的理解能力,提高和挖掘我们对所学知识的实际应用能力和创新能力。同学们的合作是实验成功的必要条件,而谨慎对待事物的态度是成功的关键。
第六章 附录
6.1 源代码
#include
//定义IP头 { union {
BYTE Version;
//版本(前4位)
BYTE HdrLen;
//报头标长(后4位),IP头长度
};BYTE ServiceType;
//服务类型
WORD TotalLen;
//数据报总长
WORD ID;
//标识
union {
WORD Flags;
//标识(前3位)
WORD FragOff;
//分段偏移(后13位)
};BYTE TimeToLive;
//生存周期
BYTE Protocol;
//协议
WORD HdrChksum;
//头校验和
DWORD SrcAddr;
//源地址
DWORD DstAddr;
//目地地址
BYTE Options;
//选项 }IP_HEADER;
char * parseServiceType_getProcedence(BYTE b){ switch(b>>5)
//获取服务类型字段中优先级子域
{ case 7:
return “Network Control”;
//网络控制
break;case 6:
return “Internet work Control”;
//网络控制
break;case 5:
return “CRITIC/ECP”;
break;case 4:
return “Flash Override”;
//最优先信号
break;case 3:
return “Flsah”;
break;case 2:
return “Immediate”;
break;case 1:
return “Priority”;
//协议
break;case 0:
return “Routine”;
//路由
break;default:
return “Unknow”;
break;} } char * parseServiceType_getTOS(BYTE b){ b=(b>>1)&0x0f;
//获取服务类型字段中的TOS子域
switch(b)
{
case 0:
return “Normal service”;
//正常运行
break;case 1:
return “Minimize monetary cost”;
//成本
break;case 2:
return “Maximize reliability”;
//可靠性
break;case 4:
return “Maximize throughput”;
//吞吐量
break;case 8:
return “Minimize delay”;
//延迟
break;case 15:
return “Maximize security”;
//安全性
break;default:
return “Unknow”;
} } char * getProtocol(BYTE Protocol)
//获取协议字段共8位 { switch(Protocol)
//以下为协议号说明:
{
case 1:
return “ICMP”;
//Internet控制报文协议
case 2:
return “IGMP”;
//Internet组管理协议
case 4:
return “IP in IP”;
//移动IP数据封装和隧道
case 6:
return “TCP”;
//传输控制协议
case 8:
return “EGP”;
//外部网关协议
case 17:
return “UDP”;
//用户数据报文协议
case 41:
return “IPv6”;case 46:
return “RSVP”;
//资源预留协议
case 89:
return “OSPF”;
//Open Shortest Path First 开发式最短路径优先
default:
return “UNKNOW”;} } void ipparse(FILE* file,char* buffer){ IP_HEADER ip=*(IP_HEADER*)buffer;
//通过指针把缓冲区的内容强制转化为IP_HEADER数据结构
fseek(file,0,SEEK_END);
fprintf(file,“_______________________________________________rn”);fprintf(file,“版本号:IPV%drn”,ip.Version>>4);fprintf(file,“报头标长:%d(BYTE)rn”,((ip.HdrLen & 0x0f)*4));fprintf(file,“服务器类型 : %s,%srn”,parseServiceType_getProcedence(ip.ServiceType),parseServiceType_getTOS(ip.ServiceType));fprintf(file,“总长度 : %d(BYTE)rn”,ip.TotalLen);fprintf(file,“标识 : %drn”,ip.ID);fprintf(file,“标志位 DF:%d , MF=%drn”,((ip.Flags>>14)&0x01),((ip.Flags>>13)&0x01));fprintf(file,“分段偏移值 : %drn”,(ip.FragOff&0x1fff));
fprintf(file,“生存期 : %d(hops)rn”,ip.TimeToLive);fprintf(file,“协议 : %srn”,getProtocol(ip.Protocol));fprintf(file,“头校验和 : 0x%0xrn”,ip.HdrChksum);fprintf(file,“源IP地址 : %srn”,inet_ntoa(*(in_addr*)&ip.SrcAddr));fprintf(file,“目的IP地址 : %srn”,inet_ntoa(*(in_addr*)&ip.DstAddr));fprintf(file,“________________________________________________rn”);}
int main(){
FILE * file;if((file=fopen(“logfile.txt”,“wb+”))==NULL){
printf(“fail to open file %s”);
return-1;
}
WORD rv;WSADATA WSAData;
//定义了能够储存WSAStarup调用返回值的结构
rv=MAKEWORD(2,2);
//Winsock2版本
WSAStartup(rv,&WSAData);
SOCKET sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP);//创建套接字,sock为套接字描述符
BOOL flag=true;setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(CHAR*)&flag,sizeof(flag));//任意类型、任意状态套接口的设置选项值
char hostName[128];gethostname(hostName,100);
//获取主机名
hostent * pHostIP;
//获取本地IP地址
pHostIP = gethostbyname(hostName);
sockaddr_in addr_in;addr_in.sin_addr=*(in_addr *)pHostIP->h_addr_list[0];addr_in.sin_family = AF_INET;addr_in.sin_port = htons(6000);//将无符号短整型主机数据转换为网络字节顺序数据
bind(sock,(PSOCKADDR)&addr_in,sizeof(addr_in));
DWORD dwBufferLen[10];
//设置网卡为混杂模式
DWORD dwBufferInLen=1;DWORD dwBytesReturned=0;WSAIoctl(sock, IO_RCVALL,&dwBufferInLen,sizeof(dwBufferInLen), &dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL);
char buffer[BUFFER_SIZE];
//设置缓冲区
char i,a;
printf(“
*************************************n”);
printf(“
*
IP数据包捕获程序
*n”);
printf(“
*
捕获并解析本机的数据包输入Y
*n”);
printf(“
*
放弃执行输入N
*n”);
printf(“
*
退出程序按 Ctrl+c
*n”);
printf(“
*************************************n”);cin>>i;system(“cls”);while(true&&i=='Y'||i=='y'){
int size=recv(sock,buffer,BUFFER_SIZE,0);
//接收数据包
if(size>0)
{
printf(“nnIP数据包捕获解析程序n”);
ipparse(stdout,buffer);
ipparse(file,buffer);
printf(“是否要继续捕获并解析本机的IP数据包? Y/N n”);
fflush(stdin);
cin>>i;
continue;
}
else
fclose(file);
return 0;}
closesocket(sock);}
计算机网络课程的结束已经过去将近1年,当时的学习也仅限于上课和考试。这次计算机网络课程设计给予了我一次难得的锻炼机会。刚拿到题目的时候,感觉还无从下手。后来通过上网查询各种资料和查阅书籍,我们慢慢摸索探讨出了整个组网的设计过程。该组网只是一个简单的酒店网络模拟,它离实际还是有相当的距离,需要进行不断地补充和完善。通过本次课程设计我们学到了不少新的东西,也发现了大量的问题,有些在设计过程中已经解决,有些还有待今后慢慢学习只要学习就会有更多的问题,有更多的难点,但也会有更多的收获。本次课程设计用到的packet tracer软件是我们第一次接触,但通过自学和网络的帮助,我们慢慢掌握了packet tracer软件的使用方法。从一开始的无处着手到通过自己的努力,我基本上完成了这次的任务,但是由于知识的欠缺及时间的限制,我们的成果仅限于现在完成的部分,还有很大的改善空间。总的来说,本次课程设计让我获益匪浅,希望以后还有这样锻炼自己的机会。
第四篇:计算机网络课程设计-编程实现简单的TCP协议分析器
编程实现简单的TCP协议分析器
编程实现简单的TCP协议分析器
一、问题描述
编程实现简单的TCP协议分析器,TCP协议分析器是一种用于监督和跟踪网络活动的诊断工具,它从局域网中抓取IP数据包,并对它进行分析得到相应的头部信息,过滤TCP包进行分析,得到TCP包的相应信息。
二、基本要求
1.利用原始套接字实现简单的TCP协议分析器。2.系统功能包括:
2.1 原始套接字与网卡绑定,并接收流经网卡的所有数据包; 2.2 对数据包进行分析以获得源IP地址和目的IP地址; 2.3 对TCP Segment进行分析以获得其首部详细信息; 2.4 显示分析结果。3 建议使用VC++。
三、设计思想
TCP协议的数据传送程序是由二个子程序组成的。也可以看成是服务器端程序和客户端程序,其中:服务器端程序的功能是侦听端口号,接收远 程主要的TCP连接申请,并接收远程主机传送来的文字数据。另外一个子程序,也就是所谓的客户端程序,主要实现向网络的远程主机提出TCP连接申请。
程序利用原始套接字抓取局域网中的IP包。
TCP协议分析器实现了sniffer的一部分功能。而sniffer的工作原理是:1.把网卡置于混杂模式;2.捕获数据包;3.分析数据包。
Raw Socket: 原始套接字可以用它来发送和接收 IP 层以上的原始数据包, 如 ICMP,TCP, UDP等。
四、系统结构
(1)Pcap_addr描述网络接口地址;
(2)pcap_pkthdr用来描述每个捕获到的数据包的基本信息;(3)int_pcaplookupnet获取网络地址和网络掩码;
(4)int_pcaploop循环捕获网络数据包,直到遇到错误或满足退出条件;(5)pcap_t* pcap_open_dead构造一个libpcap句柄。
五、程序流程(或模块划分)
编程实现简单的TCP协议分析器
六、源程序
#include “pcap.h” struct ether_header {
u_int8_t ether_dhost[6];
/* 目的以太网地址 */
u_int8_t ether_shost[6];
/* 源以太网地址 */
u_int16_t ether_type;
/* 以太网类型 */ };struct arp_header
编程实现简单的TCP协议分析器
{
u_int16_t arp_hardware_type;
/* 硬件类型 */
u_int16_t arp_protocol_type;
/* 协议类型 */
u_int8_t arp_hardware_length;
/* 硬件地址长度 */
u_int8_t arp_protocol_length;
/* 协议地址长度 */
u_int16_t arp_operation_code;
/* 操作码 */
u_int8_t arp_source_ethernet_address[6];
/* 源以太网地址 */
u_int8_t arp_source_ip_address[4];
/* 源IP地址 */
u_int8_t arp_destination_ethernet_address[6];
/* 目的以太网地址 */
u_int8_t arp_destination_ip_address[4];
/* 目的IP地址 */ };struct ip_header {
#if defined(WORDS_BIGENDIAN)
u_int8_t ip_version: 4,/* 版本 */
ip_header_length: 4;
/* 首部长度 */
#else
u_int8_t ip_header_length: 4, ip_version: 4;
#endif
u_int8_t ip_tos;
/* 服务质量 */
u_int16_t ip_length;
/* 长度 */
u_int16_t ip_id;
/* 标识 */
u_int16_t ip_off;
编程实现简单的TCP协议分析器
/* 偏移 */
u_int8_t ip_ttl;
/* 生存时间 */
u_int8_t ip_protocol;
/* 协议类型 */
u_int16_t ip_checksum;
/* 校验和 */
struct in_addr ip_souce_address;
/* 源IP地址 */
struct in_addr ip_destination_address;
/* 目的IP地址 */ };struct udp_header {
u_int16_t udp_source_port;
/* 源端口号 */
u_int16_t udp_destination_port;
/* 目的端口号 */
u_int16_t udp_length;
/* 长度 */
u_int16_t udp_checksum;
/* 校验和 */ };struct tcp_header {
u_int16_t tcp_source_port;
/* 源端口号 */
u_int16_t tcp_destination_port;
/* 目的端口号 */
u_int32_t tcp_sequence_liuzhen;
/* 序列号 */
u_int32_t tcp_acknowledgement;
/* 确认序列号 */
#ifdef WORDS_BIGENDIAN
u_int8_t tcp_offset: 4,/* 偏移 */
编程实现简单的TCP协议分析器
tcp_reserved: 4;
/* 未用 */
#else
u_int8_t tcp_reserved: 4,/* 未用 */
tcp_offset: 4;
/* 偏移 */
#endif
u_int8_t tcp_flags;
/* 标记 */
u_int16_t tcp_windows;
/* 窗口大小 */
u_int16_t tcp_checksum;
/* 校验和 */
u_int16_t tcp_urgent_pointer;
/* 紧急指针 */ };struct icmp_header {
u_int8_t icmp_type;
/* ICMP类型 */
u_int8_t icmp_code;
/* ICMP代码 */
u_int16_t icmp_checksum;
/* 校验和 */
u_int16_t icmp_id;
/* 标识符 */
u_int16_t icmp_sequence;
/* 序列码 */ };void tcp_protocol_packet_callback(u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content){
struct tcp_header *tcp_protocol;
/* TCP协议变量 */
u_char flags;
编程实现简单的TCP协议分析器
/* 标记 */
int header_length;
/* 长度 */
u_short source_port;
/* 源端口 */
u_short destination_port;
/* 目的端口 */
u_short windows;
/* 窗口大小 */
u_short urgent_pointer;
/* 紧急指针 */
u_int sequence;
/* 序列号 */
u_int acknowledgement;
/* 确认号 */
u_int16_t checksum;
/* 校验和 */
tcp_protocol =(struct tcp_header*)(packet_content + 14+20);
/* 获得TCP协议内容 */
source_port = ntohs(tcp_protocol->tcp_source_port);
/* 获得源端口 */
destination_port = ntohs(tcp_protocol->tcp_destination_port);
/* 获得目的端口 */
header_length = tcp_protocol->tcp_offset *4;
/* 长度 */
sequence = ntohl(tcp_protocol->tcp_sequence_liuzhen);
/* 序列码 */
acknowledgement = ntohl(tcp_protocol->tcp_acknowledgement);
/* 确认序列码 */
windows = ntohs(tcp_protocol->tcp_windows);
/* 窗口大小 */
urgent_pointer = ntohs(tcp_protocol->tcp_urgent_pointer);
/* 紧急指针 */
flags = tcp_protocol->tcp_flags;
/* 标识 */
checksum = ntohs(tcp_protocol->tcp_checksum);
编程实现简单的TCP协议分析器
/* 校验和 */
printf(“-------TCP协议
-------n”);
printf(“源端口号:%dn”, source_port);
printf(“目的端口号:%dn”, destination_port);
switch(destination_port)
{
case 80:
printf(“上层协议为HTTP协议n”);
break;
case 21:
printf(“上层协议为FTP协议n”);
break;
case 23:
printf(“上层协议为TELNET协议n”);
break;
case 25:
printf(“上层协议为SMTP协议n”);
break;
case 110:
printf(“上层协议POP3协议n”);
break;
default:
break;
}
printf(“序列码:%un”, sequence);
printf(“确认号:%un”, acknowledgement);
printf(“首部长度:%dn”, header_length);
printf(“保留:%dn”, tcp_protocol->tcp_reserved);
printf(“标记:”);
if(flags &0x08)
printf(“PSH ”);
if(flags &0x10)
printf(“ACK ”);
if(flags &0x02)
printf(“SYN ”);
if(flags &0x20)
编程实现简单的TCP协议分析器
printf(“URG ”);
if(flags &0x01)
printf(“FIN ”);
if(flags &0x04)
printf(“RST ”);
printf(“n”);
printf(“窗口大小:%dn”, windows);
printf(“校验和:%dn”, checksum);
printf(“紧急指针:%dn”, urgent_pointer);} void ip_protocol_packet_callback(u_char *argument, const struct pcap_pkthdr *packet_header, const u_char *packet_content){
struct ip_header *ip_protocol;
/* IP协议变量 */
u_int header_length;
/* 长度 */
u_int offset;
/* 偏移 */
u_char tos;
/* 服务质量 */
u_int16_t checksum;
/* 校验和 */
ip_protocol =(struct ip_header*)(packet_content + 14);
/* 获得IP协议内容 */
checksum = ntohs(ip_protocol->ip_checksum);
/* 获得校验和 */
header_length = ip_protocol->ip_header_length *4;
/* 获得长度 */
tos = ip_protocol->ip_tos;
/* 获得服务质量 */
offset = ntohs(ip_protocol->ip_off);
/* 获得偏移 */ if(ip_protocol->ip_protocol==6)
{
printf(“-----------IP协议
-----------n”);
编程实现简单的TCP协议分析器
printf(“版本号:%dn”, ip_protocol->ip_version);
printf(“首部长度:%dn”, header_length);
printf(“服务质量:%dn”, tos);
printf(“总长度:%dn”, ntohs(ip_protocol->ip_length));
printf(“标识:%dn”, ntohs(ip_protocol->ip_id));
printf(“偏移:%dn”,(offset &0x1fff)*8);
printf(“生存时间:%dn”, ip_protocol->ip_ttl);
printf(“协议类型:%dn”, ip_protocol->ip_protocol);
printf(“上层协议为TCP协议n”);
printf(“校验和:%dn”, checksum);
printf(“源IP地址:%sn”, inet_ntoa(ip_protocol->ip_souce_address));
/* 获得源IP地址 */
printf(“目的IP地址:%sn”, inet_ntoa(ip_protocol->ip_destination_address));
/* 获得目的IP地址 */
} } void ethernet_protocol_packet_callback(u_char *packet_header, const u_char *packet_content){ static int packet_number = 1;
/* 数据包个数,静态变量 */ u_short ethernet_type;
/* 以太网类型 */
struct ether_header *ethernet_protocol;struct ip_header *ip_protocol;
/* IP协议变量 */
u_int header_length;
/* 长度 */
u_int offset;
/* 偏移 */
u_char tos;
/* 服务质量 */
u_int16_t checksum;
/* 校验和 */
ip_protocol =(struct ip_header*)(packet_content + 14);
/* 获得IP协议内容 */
checksum = ntohs(ip_protocol->ip_checksum);
*argument, const struct pcap_pkthdr 编程实现简单的TCP协议分析器
/* 获得校验和 */
header_length = ip_protocol->ip_header_length *4;
/* 获得长度 */
tos = ip_protocol->ip_tos;
/* 获得服务质量 */
offset = ntohs(ip_protocol->ip_off);
/* 获得偏移 */
/* 以太网协议变量 */ ethernet_protocol =(struct ether_header*)packet_content;ethernet_type = ntohs(ethernet_protocol->ether_type);/* 获得以太网类型 */ if(ethernet_type==0x0800 && ip_protocol->ip_protocol==6){ u_char *mac_string;
/* 以太网地址 */
printf(“**************************************************n”);
printf(“捕获第%d个TCP网络数据包n”, packet_number);
printf(“捕获时间:n”);
printf(“%s”, ctime((const time_t*)&packet_header->ts.tv_sec));
/* 获得捕获数据包的时间 */
printf(“数据包长度:n”);
printf(“%dn”, packet_header->len);
printf(“--------
以太网协议
--------n”);
/* 获得以太网协议内容 */
printf(“类型:n”);
printf(“%04xn”, ethernet_type);
printf(“源以太网地址: n”);
mac_string = ethernet_protocol->ether_shost;
printf(“%02x:%02x:%02x:%02x:%02x:%02xn”,*mac_string, *(mac_string *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
/* 获得源以太网地址 */
printf(“目的以太网地址: n”);
mac_string = ethernet_protocol->ether_dhost;
printf(“%02x:%02x:%02x:%02x:%02x:%02xn”, *mac_string, *(mac_string *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
/* 获得目的以太网地址 */
ip_protocol_packet_callback(argument, packet_header, packet_content);
+ 1),+ 1), 编程实现简单的TCP协议分析器
packet_number++;
printf(“**************************************************n”);
} } void main(){
pcap_t *pcap_handle;
/* Winpcap句柄 */
char error_content[PCAP_ERRBUF_SIZE];
/* 存储错误信息 */
char *net_interface;
/* 网络接口 */
struct bpf_program bpf_filter;
/* BPF过滤规则 */
char bpf_filter_string[] = "";
/* 过滤规则字符串 */
bpf_u_int32 net_mask;
/* 掩码 */
bpf_u_int32 net_ip;
/* 网路地址 */
net_interface = pcap_lookupdev(error_content);
/* 获得可用的网络接口 */
pcap_lookupnet(net_interface, &net_ip, &net_mask, error_content);
/* 获得网络地址和掩码地址 */
pcap_handle = pcap_open_live(net_interface, BUFSIZ, 1, 1, error_content);
/* 打开网路接口 */
pcap_compile(pcap_handle, &bpf_filter, bpf_filter_string, 0, net_ip);
/* 编译BPF过滤规则 */
pcap_setfilter(pcap_handle, &bpf_filter);
/* 设置过滤规则 */
if(pcap_datalink(pcap_handle)!= DLT_EN10MB)
return;
pcap_loop(pcap_handle,-1, ethernet_protocol_packet_callback, NULL);
/* 注册回调函数,循环捕获网络数据包,利用回调函数来处理每个数据包 */
pcap_close(pcap_handle);
/* 关闭Winpcap操作 */ }
编程实现简单的TCP协议分析器
七、测试数据
本地局域网IP数据包
八、测试情况
程序运行结果图:
编程实现简单的TCP协议分析器
编程实现简单的TCP协议分析器
结 论
通过两周的课程设计,增强了我的实际动手能力,通过实际的编程整合串联了我所学到的知识。另外我还学到了作为编程人员的一些基本素质,这为我毕业后找工作奠定了基础。
通过做TCP协议分析器学习的很多网络编程知识: 1.学会了winpcap网络数据报捕获开发包的使用; 2.绑定网卡函数bind(); 3.数据接受函数recv(); 4.Windows套接字编程;
5.学习了原始套接字编程的基本机制; 6.学习对数据包进行协议分析的基本方法。
通过做TCP协议分析器学习的很多Visual C++ Windows编程知识:
1.学会了Windows常用数据结构的使用;
2.学到了一些用Visual C++ Windows编程的技巧。
编程实现简单的TCP协议分析器
参考文献
[1] 甘玲 邱劲 《面向对象技术与Visual C++ 》 清华大学出版社 [2] 任哲 《MFC Windows 应用程序设计》清华大学出版社 [3] 《计算机网络》 北京:机械工业出版社
[4] 《Visual C++网络通信编程实用案例精选》 人民邮电出版社 [5] 《windows程序设计》 北京大学出版社
第五篇:计算机网络课程设计
目
录
1.课题描述........................................................1 2 系统设计概述...................................................1 3 课程设计的主要内容............................................2 3.1站点总体设计原则及设计目标....................................2 3.2用户需求......................................................2 3.3动态IP地址的设置及服务器的配置...............................3 3.3.1.动态IP配置简介...........................................3 3.3.2.配置DHCP服务器...........................................3 3.3.3配置IIS服务器.............................................6 3.4制作网站......................................................6 3.4.1.建站流程..................................................6 3.4.2.网站各模块的设计...........................................7 3.4.3.建站实现软件...............................................8 3.5.建站注意要点..................................................9 3.5.1.前期调研分析...............................................9 3.5.2.网站的目的及功能定位.......................................9 3.5.3网站技术解决方案...........................................9 3.5.4.网站内容规划.............................................10 3.5.5.网页设计.................................................10 3.5.6.网站测试..................................................10 4.网站维护.......................................................10 4.1、静态页面的添加修改..........................................10 4.2、动态功能支持在线更新........................................10
总结..............................................................12 参考文献.........................................................12
1.课题描述
计算机网络近年来获得了飞速的发展。计算机通信网络以及Internet已成为我们社会结构的一个基本组成部分。网络被应用于工商业的各个方面,电子银行、电子商务、企业管理、信息服务业等都以计算机网络系统为基础。从学校远程教育到公司日常办公乃至现在的电子社区,很多方面都离不开网络技术。可以不夸张地说,网络在当今世界无处不在。
网络的发展也是一个经济上的冲击。数据网络使个人化的远程通信成为可能,并改变了商业通信的模式。一个完整的用于发展网络技术、网络产品和网络服务的新兴工业已经形成,计算机网络的普及性和重要性已经导致了在不同岗位上对具有更多网络知识的人才的大量需求。企业需要雇员来规划、获取、安装、操作、管理那些构成计算机网络的软硬件系统,建立自己的网站,方便办公及交流 系统设计概述
传统的企业内部办公存在着种种弊端,往往造成人员和资源的极大浪费,应用网络技术组建余个高效、快捷、安全的办公环境成为许多企业和单位的当务之急。与传统的单机工作相比,网络化办公具有以下几个明显优点: 1共享软硬件资源,节约资金投入,提高运作效率
企业内部组件web站点后,可以在一个部门只安装一台打印机和扫描仪,其他计算机通过局域网共享这些设备和数据,有利于降低成本。2对重要数据进行安全、集中的管理
组建站点后,可以把一些重要数据放置在专门的网络服务器上集中管理,并通过网络服务器的访问控制限制其他计算机对总要数据的访问。这样就可以有效管理企业内部的重要数据,保证数据安全性,防止数据丢失和被窃取。3方便企业内部信息发布与交流
当企业进行诸如企业内部新闻、电话号码、产品文档、技术文件等信息发布时,可以把这些信息放置在web站点的共享目录上,供员工下载,方便了信息的发布和接收。4便于员工的协调操作
利用内部的办公网,可以方便的对同一事务进行协同处理,提高工作效率,缩短任务完成的时间
图2.1企业内部网络拓扑 课程设计的主要内容
3.1站点总体设计原则及设计目标
组建企业内部web站点要注意站点的分块、共享、安全性、可管理性、以及可维护性。在设计中,系统结构模块化,软硬件平台可以模块化瓶装,系统配置灵活,使系统具有强大的可增长性和强壮性。满足多层次安全控制手段,建立完善的安全管理体系,防止数据的丢失和被窃取。
组建企业内部web站点,既能将公司内部所有计算机纳入系统中去,实现统一规划、分块工作、异地互联、整体管理,并可为将来的应用扩展升级预留接口。
3.2用户需求 作为企业内部网络需要满足:
1、办公事务管理
主要包括公文与文档管理、公告、大事记、会议纪要、资产与办公用品管理、行政制度、办公事务讨论等。
2、人力资源管理
主要包括员工档案、岗位职责、员工通信录、认识管理规范等。
3、财务资产管理
主要包括固定资产管理、工资管理、经费管理等。
4、网站管理
主要包括用户及权限设置、数据库维护、网页设置、标志与标题设置及网络各栏目内容编辑等功能。
3.3动态IP地址的设置及服务器的配置
3.3.1.动态IP配置简介
动态IP地址,顾名思义就是设备所取得的IP地址是非固定的,是可以动态分配和取得的。使用动态IP地址的原因主要有两个:一是可以用较少的IP地址构建较大的网络。如果与连入网络的主机和其它设备相比,所分得的公用IP地址略少一些,如果为每个设备都分配一个固定的IP地址,则显然部分计算机将不能接入网络。考虑到并非所有的计算机都在同一时间内运行并与网络连接,所以,如果将IP进行动态分配,即计算机连入网络时自动取得,断开与网络的连接时自动收回,即可满足网络对IP地址的需求。二是可以增加网络内计算机的可移动性。当某台主机从一个子网移动到另一个子网时,由于IP地址中网络号的不同,从而导致该计算机与其它主机间无法进行通信,解决该类问题最简单的方式就是为移动的主机在新子网中重新分配IP地址。但是,如果采用动态IP地址,就会减少这种网络管理的复杂性。Windows NT使用DHCP来解决动态IP地址的分配问题。使用DHCP时,整个网络中必须至少有一台运行Windows NT主机安装有DHCP软件,充当DHCP服务器,而其它所有欲使用DHCP功能的工作站也必须具有支持DHCP的功能。这样,当DHCP工作站启动时,它就会自动与DHCP服务器通信,并由DHCP服务器为其提供一个IP地址。当然,这个地址只是临时的 3.3.2.配置DHCP服务器
DHCP提供了计算机IP地址的动态配置,如果需要服务器为域中的计算机动态分配IP地址,则必须配置DHCP服务器。配置DHCP服务器的具体步骤如下:
图3.1打开服务器配置向导
图3.2配置服务器向导
图3.3配置服务器向导
图3.4为配置服务器向导
图3.5管理服务器
图3.6 再来就是通过“开始”选择“控制面板”|“添加或删除程序”也可以安装DHCP。
3.3.3配置IIS服务器
右键单击“我的电脑”选择“管理”~服务及应用程序~Internet信息服务~网站~默认网站,单击右键,选择属性,打开主目录,设置主目录为web站点的根目录,也可选择修改其他属性
图3.7配置IIS服务器
3.4制作网站
3.4.1.建站流程
建立网站的流程大致可以分成三个阶段,如图所示
图3.8网站的流程框图
构建内容信息、搜索整理资料和规划网站结构是建立网站的
企业的每一个员工都存在向企业内部网发布内容的潜在可能性。但员工必须按照他们各自的角色协调作业活动。不同规模的公司都需要以省时省钱的方式组织交互信息发布的流程。
通常情况下,为在网站上发布内容,作者创建的材料要经过一个或多个编辑的审校和核准。在这个过程中,作者及编辑按照各种特定的标准分类及标注信息,并为发布设计页面及连接。这一流程通常不是正式的,且要接受网络管理员的协调,这就导致了管理员在“站点发布狂潮”到来时,或是当用户对实时信息需求迅速增长时陷入孤立无援的境地。
使用Site Server可以解决,Site Server还定义了一套为站点增添内容的四步流程,既提交、标注、核准和部署。
图3.9新闻发布系统框图
3.4.3.建站实现软件
可以用Dreamweaver,主要包括两种页面,即html和asp。
HTML(Hyper Text Markup Language ,超文本标记语言),或称为“多媒体文件语言”,是用于创建Web页和Web 信息发布的
(1)通用性:可实现不同平台的文档共享。
(2)可扩展性:HTML的标签集合可以根据新需求而不断修正或加入有限的新标签符, 为实现有限的新功能的扩展提供保障。
(3)创建的灵活性:HTML文档是纯文本文档, 可以由网页编辑器以及其他文本编辑软件创建。
HTML是“Hyper Text Markup Language”的缩写,它是一种超文本标记语言,是网页的描述语言,用于编制通过万维网显示的超文本文件。它是目前在网页设计中,所使用的最基本的标记语言。现在很多HTML 的编辑器,都是通过跟文字处理器相似的接口来编辑网页的。
ASP 文件和 HTML 文件类似ASP 文件可包含文本、HTML、XML 和脚本 ASP 文件中的脚本可在服务器上执行。ASP 文件的扩展名是 “.asp”.当浏览器请求某个 HTML 文件时,服务器会返回这个文件.而当浏览器请求某个 ASP 文件时,IIS 将这个请求传递至 ASP 引擎。ASP 引擎会逐行地读取这个文件,并执行文件中的脚本。最后,ASP 文件将以纯 HTML 的形式返回到浏览器。ASP 指 Active Server Pages(动态服务器页面)ASP 是运行于 IIS 之中的程序.3.5.建站注意要点
另外在网页制作过程中应注意以下要点: 3.5.1.前期调研分析
了解网页制作后具体的工作人员具体权限,以保证公司机密信息不会被泄露,同时又能让每个人从网站上获取足够的工作信息;同时对于私人隐私的公开应得到个人的允许。在注意到以上的同时,还要考虑公司的自身情况、建设网站的能力等 3.5.2.网站的目的及功能定位
本次为企业内部web站点的构建及维护 3.5.3网站技术解决方案
确定服务器,是自建服务器还是租用虚拟主机。选择操作系统。网站安全性措施,如:防入侵,防病毒,防窃取方案
3.5.4.网站内容规划
根据网站的目的和功能规划网站内容。一般企业内部网站应包括:公司简介、部门简介、公共信息、新闻发布、员工联系方式、任务信息、信息搜索查询、相关帮助等内容。
3.5.5.网页设计
网页美术设计要求。网页美术设计一般要求与企业整体形象一致,企业内部网色彩要与办公环境保持和谐 3.5.6.网站测试
①网站发布前要进行细致周密的测试,以保证正常的浏览和使用。主要测试内容有: ②服务器稳定性、安全性。③程序及数据库测试
④网页兼容性测试,包括不同浏览器下的现实结果、不同显示器分辨率的页面效果等。⑤需要的其他测试
4.网站维护
服务器及相关软硬件的维护,对可能出现的问题进行评估,制定相应时间。数据库维护。有效地利用数据是网站维护的重要内容,因此数据库的维护要受到重视。
内容的更新、调整计划。
制定相关网站维护的规定,将网站维护制度化、规范化。
4.1、静态页面的添加修改
静态页面的更新需要使用专业的网页设计工具,然后将修改后的网页通过FTP上传到相应的位置,在此同时还要保证不能破坏其他的页面程序和格局
4.2、动态功能支持在线更新
如果企业信息量很大,如工作信息经常需要更新,有更多的企业资讯需要告诉员工,企业建立动态数据库系统。这里的动态并不是指动画,而是指网站的内容来自企业的数据库。如果更改了数据库,那么前台页面的内容也会随之而更改。
总 结
通过这次课程设计,我拓宽了知识面,锻炼了能力,综合素质得到较大提高。安排课程设计的基本目的,在于通过理论与实际的结合、人与人的沟通,进一步提高思想觉悟。尤其是观察、分析和解决问题的实际工作能力,以便培养成为能够主动适应社会主义现代化建设需要的高素质的复合型人才。作为整个学习体系的有机组成部分,课程设计虽然安排在一周进行,但并不具有绝对独立的意义。它的一个重要功能,在于运用学习成果,检验学习成果。运用学习成果,把课堂上学到的系统化的理论知识,尝试性地应用于实际设计工作,并从理论的高度对设计工作的现代化提出一些有针对性的建议和设想。检验学习成果,看一看课堂学习与实际工作到底有多大距离,并通过综合分析,找出学习中存在的不足,以便为完善学习计划,改变学习内容与方法提供实践依据。对计算机专业的本科生来说,实际能力的培养至关重要,必须从课堂走向实践。这也是一次预演和准备毕业设计工作。通过课程设计,让我找出自身状况与实际需要的差距,并在以后的学习期间及时补充相关知识,为求职与正式工作做好充分的知识、能力准备,从而缩短从校园走向社会的心理转型期。课程设计促进了我系人才培养计划的完善和课程设置的调整。在一个星期的课程设计之后,我感到不仅实际动手能力有所提高,更重要的是通过对网站开发流程以及维护方面的了解,进一步激发了我对专业知识的兴趣,并能够结合实际存在的问题在专业领域内进行更深入的学习。
在课程设计过程中,我学到了很多人生的哲理,懂得怎么样去制定计划,怎么样去实现这个计划,并掌握了在执行过程中怎么样去克服心理上的不良情绪,黑夜过去了,我收获的是黎明。
参考文献
[1]朱兵.小型网组建与应用进阶[M].南方出版社.2004.[2]邓文达胡伏湘.计算机网络教程[M].清华大学出版社.2007.[3] 赵永超.新编网站规划与设计教程[M].西北工业大学出版社.2004.[4] 杨力学.ASP商业网站整站集成开发[M].电子工业出版社.2007.[5] 石志国.ASP动态网站编程[M].清华大学出版社.2001.[6] 李岚.网络设计与维护[M].中国物资出版社.2002.