当前位置:文档之家› TCP数据包的发送和接收设计报告

TCP数据包的发送和接收设计报告

TCP数据包的发送和接收设计报告

1 / 11 湖北工业大学

课 程 设 计 报 告

设计题目:TCP数据包的发送和接收

专 业:计算机科学与技术

班 级:10计科2班

学 号:1010311211

姓 名:吕红杰

指导老师:涂军

TCP数据包的发送和接收设计报告

2 / 11 一.设计题目

发送和接收TCP数据包

二.设计要求

1.正确理解题意;

2.具有良好的编程规范和适当的注释;

3.有详细的文档,文档中应包括设计题目涉及的基础知识、设计思路、程序流程图、程序清单、开发中遇到的问题及解决方法、设计中待解决的问题及改进方向。

三.需求分析

TCP是一种面向连接的、可靠的传输层协议。TCP协议工作在网络层IP协议的基础上。本课程设计的目的是设计一个发送和接收TCP数据包的程序,其功能是填充一个TCP数据包,发送给目的主机,并在目的主机接收此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, SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout, sizeof(timeout));

在这里我们使用基本套接字SOL_SOCKET,设置SO_SNDTIMEO表示使用发送超时设置,超时时间设置为1000ms。

2.构造IP头和TCP头

这里, IP头和TCP头以及TCP伪部的构造请参考下面它们的数据结构。

typedef struct _iphdr //定义IP首部

{ TCP数据包的发送和接收设计报告

3 / 11 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 或其他)

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)

{

unsigned long cksum=0;

while(size >1)

{

cksum+=*buffer++;

size -=sizeof(USHORT);

}

if(size )

{ TCP数据包的发送和接收设计报告

4 / 11 cksum += *(UCHAR*)buffer;

}

cksum = (cksum >> 16) + (cksum & 0xffff);

cksum += (cksum >>16);

return (USHORT)(~cksum);

}

4.流程图

开始构造原始套接字并初始化填充IP首部计算IP首部校验和构造TCP伪首部填充TCP首部计算TCP首部校验和填充发送缓冲区填入目的地址发送数据包结束

五.实验内容

1.先用vc++编译运行程序代码 TCP数据包的发送和接收设计报告

5 / 11 2.用命令指示符运行Debug下的sendTCP

3.输入源ip和端口及目的ip和端口

4.输入发送内容 TCP数据包的发送和接收设计报告

6 / 11

5.发送完成

六.附代码

#include

#include

#include

#include

#include TCP数据包的发送和接收设计报告

7 / 11 #include

#include

#include

#pragma comment(lib,"ws2_32.lib")

#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地址

}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;

TCP数据包的发送和接收设计报告

8 / 11 //CheckSum:计算校验和的子函数

USHORT checksum(USHORT *buffer, int size)

{

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);

}

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--;

}

str[readlen]=NULL;

return readlen;

}

int main(int argc, char* argv[])

{

WSADATA WSAData;

SOCKET sock;

相关主题