发送TCP数据包
tcp健康检查原理

tcp健康检查原理
TCP健康检查是一种对服务器运行状况进行监测的技术,其原理是通
过发送TCP数据包来检测服务器是否正常工作,从而保证服务的可靠性。
TCP健康检查的基本原理是利用TCP协议中的三次握手来完成的。
在正常的情况下,当客户端向服务器发送一个SYN数据包时,服务器会回复一个SYN/ACK数据包,然后客户端再回复一个ACK数据包,完成TCP连接的建立。
这个过程中,服务器会记录下每个连接的状态和
属性,如果服务器在一定时间内没有收到客户端发来的ACK数据包,就会认为此连接出现异常,并将其标记为不可用。
TCP健康检查通过模拟客户端向服务器发送SYN数据包,然后观察服务器的响应情况,来判断服务器是否正常工作。
如果服务器在规定的
时间内能正常响应SYN/ACK数据包,那么就认为该服务器是健康的,否则就被视为不可用。
在实际应用中,TCP健康检查通常会结合负载均衡器一起使用,通过
不断地检测服务器的状态,以确保流量被正确地分发到健康的服务器上。
例如,在一个负载均衡器集群中,当某个服务器出现故障时,负
载均衡器会自动将该服务器从服务器池中移除,并将其流量重定向到
其他健康的服务器上,从而保证服务的连续性和可用性。
总之,TCP健康检查是一种非常有效的服务器监测技术,能够实时地检测服务器的状态,并及时发现并解决故障,从而提高系统的可靠性和稳定性。
TCP协议传输机制

TCP协议传输机制TCP(Transmission Control Protocol)是一种可靠的、面向连接的传输协议,广泛应用于互联网上的数据传输。
TCP协议主要通过以下几个机制来保证传输的可靠性和顺序性:1.建立连接:在进行数据传输之前,发送方和接收方需要先建立一个TCP连接。
建立连接的过程中,发送方和接收方将交换一些控制信息,以确保双方都准备好进行数据传输。
建立连接是通过三次握手的方式进行的。
首先,发送方发送一个SYN(同步)包给接收方,接收方收到SYN包后回复一个SYN+ACK包给发送方,最后发送方再回复一个ACK包给接收方。
通过三次握手,发送方和接收方都确认对方的接收能力和发送能力,建立了一个可靠的连接。
2.可靠性确认:在数据传输过程中,接收方需要向发送方确认已经接收到的数据。
发送方在发送数据时,会给每个数据包标记一个序列号,接收方在接收到数据后,会通过发送一个确认(ACK)包来告知发送方已经成功接收到数据。
如果发送方在一定时间内没有收到接收方的确认包,那么认为数据丢失或者损坏,发送方会重传这些数据,以确保数据的可靠传输。
3.拥塞控制:TCP协议通过拥塞控制机制来避免网络拥塞。
当发送方发送数据的速度超过了网络的处理能力时,会导致网络的拥塞,从而造成数据的丢失。
为了避免这种情况的发生,TCP协议通过拥塞窗口来控制发送数据的速度。
拥塞窗口的大小会根据网络的情况动态调整,当网络拥塞时,会减小窗口的大小,从而减小数据的发送速度,当网络畅通时,会增大窗口的大小,提高数据的发送速度。
4.顺序控制:TCP协议保证了数据的按序到达,即接收方接收到的数据包的顺序和发送方发送的顺序一致。
为了实现顺序控制,发送方会给每个数据包标记一个序列号,接收方在接收到数据包后,会按照序列号的顺序将数据包进行重组,确保数据的按序到达。
5.可靠重传:当数据包在传输过程中丢失或损坏时,TCP协议会进行可靠重传。
发送方会定期向接收方发送心跳消息,如果一定时间内没有收到接收方的确认,那么发送方会将未确认的数据包进行重传,确保数据的可靠到达。
简述tcp连接的过程

简述tcp连接的过程TCP连接是一种可靠的、面向连接的协议,它可以确保数据的可靠传输。
TCP连接的过程可以分为三个阶段:建立连接、数据传输和关闭连接。
建立连接阶段:1.客户端向服务器发送一个SYN(同步)数据包,其中包含一个随机的序列号和一些其他信息。
2.服务器收到SYN数据包后,会发送一个SYN-ACK(同步-确认)数据包作为响应,其中包含一个确认序列号和一些其他信息。
3.客户端收到SYN-ACK数据包后,会发送一个ACK(确认)数据包作为响应,其中包含一个确认序列号和一些其他信息。
在这个过程中,客户端和服务器都会分配一个唯一的序列号,用于标识数据包的顺序和完整性。
客户端和服务器之间的连接现在已经建立,可以开始传输数据。
数据传输阶段:在数据传输阶段,客户端和服务器之间可以传输任意数量的数据包,每个数据包都包含一个序列号和一些其他信息。
每当一个数据包被发送时,接收方都会发送一个确认数据包,其中包含确认序列号和一些其他信息。
如果发送方没有收到确认数据包,则会重新发送数据包,直到接收方确认收到数据包为止。
关闭连接阶段:当客户端或服务器想要关闭连接时,它们会发送一个FIN(结束)数据包。
接收方收到FIN数据包后,会发送一个ACK数据包作为响应,表示它已经收到了FIN数据包。
然后,接收方也会发送一个FIN数据包,表示它也想要关闭连接。
发送方收到FIN数据包后,会发送一个ACK数据包作为响应,表示它已经收到了FIN数据包。
此时,连接已经关闭,客户端和服务器之间的通信结束。
总结:TCP连接是一种可靠的、面向连接的协议,它可以确保数据的可靠传输。
TCP连接的过程可以分为三个阶段:建立连接、数据传输和关闭连接。
在建立连接阶段,客户端和服务器之间会交换一些数据包,以建立连接。
在数据传输阶段,客户端和服务器之间可以传输任意数量的数据包。
在关闭连接阶段,客户端和服务器会发送一些数据包,以关闭连接。
tcp发包机制

tcp发包机制TCP(Transmission Control Protocol)是一种可靠的、面向连接的协议,用于在计算机网络中传输数据。
它通过一系列的机制来确保数据的可靠性和完整性,使得数据能够按顺序到达目的地。
TCP使用三次握手的机制来建立连接。
发送方首先向接收方发送一个带有SYN标志的数据包,表明请求建立连接。
接收方收到后,回复一个带有SYN和ACK标志的数据包,表示接收方愿意建立连接。
最后,发送方再回复一个带有ACK标志的数据包,表示连接已建立。
这个过程就像两个人握手一样,互相确认彼此的存在和愿意建立连接。
接下来,TCP使用滑动窗口的机制来管理数据的传输。
发送方将数据分割成多个报文段,并按顺序发送给接收方。
接收方在收到报文段后,会发送一个确认报文段给发送方,表明已经成功接收到数据。
如果发送方没有收到确认报文段,就会重新发送数据,确保数据的可靠性。
同时,TCP还会根据网络的拥塞情况动态调整滑动窗口的大小,以提高数据传输的效率。
除了滑动窗口,TCP还使用序列号和确认号的机制来保证数据的顺序和完整性。
发送方在发送数据时,会给每个报文段分配一个序列号,接收方在接收数据时,会按序列号的顺序重新组装数据。
同时,接收方会给发送方发送一个确认号,表示已经成功接收到数据。
如果发送方没有收到确认号,就会重新发送数据,保证数据的完整性。
TCP使用四次挥手的机制来关闭连接。
发送方首先发送一个带有FIN标志的数据包,表示不再发送数据。
接收方收到后,发送一个带有ACK标志的数据包,表示确认收到FIN。
然后,接收方再发送一个带有FIN标志的数据包,表示自己也不再发送数据。
通过以上的机制,TCP确保了数据的可靠性和完整性。
它是一种非常重要的协议,广泛应用于互联网和各种计算机网络中。
无论是浏览网页、发送电子邮件还是下载文件,都离不开TCP的支持。
它的出现极大地促进了信息的传输和共享,使得人们能够更加方便地进行各种网络活动。
packetsender发送tcp用法

packetsender发送tcp用法【实用版】目录1.介绍 TCP 协议和 packetsender2.packetsender 发送 TCP 数据的方法3.示例:使用 packetsender 发送 TCP 数据正文TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输层通信协议。
在网络通信中,TCP 协议负责在发送端和接收端之间建立稳定的连接,以保证数据包能够按照正确的顺序传输和接收。
packetsender 是一个用于发送网络数据包的 Python 库,可以方便地帮助我们实现 TCP 数据的发送。
要使用 packetsender 发送 TCP 数据,首先需要导入所需的库,然后创建一个 TCP 套接字。
接下来,通过该套接字对象,我们可以使用send() 方法发送数据。
以下是一个简单的示例:```pythonimport socketimport packetsender# 创建一个 TCP 套接字tcp_socket = packetsender.TCPSocket("127.0.0.1", 12345)# 连接到服务器tcp_socket.connect()# 发送数据tcp_socket.send("Hello, TCP!")# 关闭套接字tcp_socket.close()```在这个示例中,我们首先导入了 socket 和 packetsender 库。
接着,我们使用 packetsender.TCPSocket() 函数创建了一个 TCP 套接字,该函数接受两个参数:目标 IP 地址和目标端口。
然后,我们使用 connect() 方法连接到服务器。
连接成功后,我们使用 send() 方法发送了一个字符串"Hello, TCP!"。
最后,我们使用 close() 方法关闭了套接字。
tcp半连接 原理

tcp半连接原理
"TCP半连接"通常是指TCP三次握手过程中的一种状态,也称为半开连接或半连接队列。
理解TCP半连接的原理需要先了解TCP的三次握手过程:
1. 客户端发送SYN(同步)包:客户端向服务器发送一个TCP数据包,其中包含SYN标志位,表示请求建立连接。
2. 服务器发送ACK(确认)和SYN包:服务器接收到客户端的SYN包后,会向客户端发送一个ACK(确认)包,并在其中包含SYN标志位,表示接受连接请求。
3. 客户端发送ACK包:客户端收到服务器的ACK和SYN包后,向服务器发送一个ACK包,表示连接建立成功。
在正常的三次握手过程中,连接的建立是可靠的。
然而,如果某一方在握手过程中突然中断,就会导致半连接状态。
半连接状态的原理可以简要描述如下:
-半连接队列:当服务器接收到客户端的SYN包后,会将该连接的信息存储在半连接队列中,等待完成三次握手的过程。
-队列溢出:如果服务器的半连接队列已满,新的连接请求将无法加入队列。
这可能会导致一些连接被拒绝,因为服务器无法处理所有的连接请求。
-超时和重传:如果在正常的三次握手过程中某个阶段发生了超时或连接中断,可能会导致半连接状态。
在这种情况下,TCP协议会尝试重新发送连接请求,直到达到最大尝试次数或连接成功为止。
总的来说,TCP半连接的原理涉及服务器在接收到客户端的连接请求时将其暂时存储在半连接队列中,等待握手的完成。
这有助于处理短暂的连接请求,但在某些情况下,可能需要注意半连接队列的大小以及连接的超时和重传机制。
lwip tcp包处理流程

lwip tcp包处理流程LWIP TCP包处理流程介绍LWIP(轻型网络协议栈)是一个在嵌入式系统中常用的TCP/IP协议栈。
本文将详细介绍LWIP的TCP包处理流程。
接收TCP包的处理流程1.LWIP首先在网络接口上等待TCP包的到来。
2.当一个TCP包到达时,LWIP将会进行一系列的处理步骤。
3.LWIP首先会进行IP层的处理,检查TCP包的IP头部信息,并进行校验。
4.接下来,LWIP会检查TCP头部信息,包括源端口、目标端口等。
5.如果TCP包是一个新连接的SYN包,LWIP会根据包的信息创建一个新的PCB(协议控制块)来表示该连接。
6.如果TCP包是一个已建立连接的数据包或者ACK包,LWIP会根据包的信息找到相应的PCB,并将包中的数据传递给应用层。
7.LWIP还会对收到的ACK包进行确认处理,包括更新已发送和已接收数据的状态。
8.最后,LWIP会根据需要回复ACK包,并进行相应的超时处理和拥塞控制。
发送TCP包的处理流程1.应用层向LWIP发送一个TCP数据包。
2.LWIP会根据目标IP地址和端口号等信息查找相应的PCB。
3.如果没有找到对应的PCB,LWIP会发送一个SYN包来建立新的连接。
4.如果找到了对应的PCB,LWIP会将数据包加入发送缓冲区,并计算出序列号和确认号。
5.当TCP包的发送窗口可用时,LWIP会将数据包发送到对应的网络接口上。
6.LWIP还会在发送过程中进行超时处理和拥塞控制,根据接收方的ACK包进行状态更新和重传等操作。
7.最后,LWIP会在收到对方的ACK包后更新发送和接收的状态,并将发送缓冲区中的数据逐渐发送完毕。
总结通过以上的介绍,我们可以了解到LWIP的TCP包处理流程。
无论是接收TCP包还是发送TCP包,LWIP都会进行一系列的处理步骤,包括IP层的处理、TCP头部的检查和更新、PCB的创建和查找、数据的传输和状态的更新等。
这些流程保证了TCP包在LWIP中的正确处理和传输。
简述tcp协议可靠传输实现方式

简述tcp协议可靠传输实现方式
TCP(Transmission Control Protocol)是一种面向连接的、可
靠的传输协议。
它通过一系列的机制来实现可靠传输,以下是一些主要的实现方式:
1. 序列号和确认机制:TCP协议通过给每个传输的数据包分
配一个序列号,接收方收到数据包后会发送一个确认序列号,发送方根据这个确认序列号来确认数据是否被有效接收。
如果发送方没有收到确认消息,则会重新发送数据。
2. 超时重传:如果发送方在一定时间内没有收到对方的确认消息,就会认为数据包丢失,然后会重传数据包。
发送方会根据网络情况动态调整超时时间,以适应不同的网络环境。
3. 流量控制:TCP使用滑动窗口技术控制数据流量,接收方
会告知发送方它的接收窗口大小,发送方根据接收方的窗口大小控制发送速率,以避免发送过多的数据导致对方无法及时处理。
4. 拥塞控制:TCP通过拥塞窗口算法来控制发送方的发送速率,当网络发生拥塞时,发送方会减小发送速率以避免拥堵情况进一步恶化。
拥塞控制是TCP协议中最重要的特性之一,
它通过一些算法如慢启动、拥塞避免、快速恢复等来实现。
5. 错误校验和重传:TCP在数据包头部添加了一个校验和字段,接收方可以通过校验和来检测有无数据传输过程中的错误。
如果发现错误,接收方会要求发送方重传数据。
这些方式相互协作,使得TCP协议能够在不可靠的网络环境中实现可靠的数据传输。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
四川理工学院课程设计书学院计算机学院专业计算机科学与技术班级09级04班题目发送TCP数据包教师王非,何绍荣,陈超学生赵清勇,谭凯,唐红琴实验分工:程序设计、编写代码由全小组成员共同完成谭凯:在vc下调试运行程序、文档编写赵清勇:在dos下运行检查、初步完成课程设计报告唐红琴:查找资料、整理课程设计报告目录一课程设计准备 (4)1.1课程设计目的 (4)1.2课程设计的要求 (4)1.3相关知识 (5)1.4工作环境 (7)二课程设计分析 (7)2.1使用原始套接字 (7)2.2定义IP头部、TCP头部和伪头部的数据结构 (8)2.3计算校验和的子函数 (10)2.4程序流程图 (11)三源代码 (12)四运行结果与运行情况 (18)五自我评析和总结 (19)六参考文献 (20)发送TCP数据包一课程设计准备1.1课程设计目的TCP(传输控制协议)是一种面向连接的、可靠的传输层协议。
TCP协议在网络层IP协议的基础上,向应用层用户进程提供可靠的、全双工的数据传输流。
本课程设计的目的就是设计一个发送TCP数据包的程序,并根据本设计说明TCP数据包的结构以及TCP协议与IP协议的关系,使学生对TCP协议的工作原理有更深入的认识。
1.2课程设计的要求本程序的功能是填充一个TCP数据包,并发送给目的主机。
1)以命令行形式运行:SendTCP sourse_ip sourse_port dest_ip dest_port其中,SendTCP为程序名;sourse_ip为源端IP地址;sourse_port 为源埠;dest_ip为目的IP地址;dest_port为目的埠。
2)其它的TCP头部参数请自行设定。
3)数据字段为“This is my homework of network,I am happy!”。
4)发送成功后在屏幕上输出”send OK”。
1.3相关知识编制本程序前要对TCP协议有一定的了解。
当应用程序有报文需要通过TCP发送时,它就将此应用层报文传送给执行TCP协议的传输实体。
TCP传输实体将用户数据加上TCP报头,形成TCP 数据包,在TCP数据包上增加IP头部,形成IP包。
下图显示的是TCP数据包和IP包的关系。
TCP协议的传输单元为报文段,其格式如图所示。
报文段报头的长度为20B~60B。
其中固定长度为20B,报文段长度最多为40B。
TCP报文段主要包括以下字段。
·埠号:埠号字段包括源埠号和目的埠号。
每个埠号的长度是16位,分别表示发送该TCP包的应用进程的埠号和接收该TCP包的应用进程的埠号。
·序号:长度为32位。
由于TCP协议是面向数据流的,它所传送的报文段可以视为连续的数据流,因此需要给每一个字节编号。
序号字段的“序号”指的是本报文段数据的第一个字节的顺序号。
·确认号:该字段的长度为32位,它表示接收端希望接收的下一个TCP包的第一个字节的序号。
·报头长度:该字段长度为4位。
TCP报头长度是以4B为一个单元来计算的,实际上报头长度在20B~60B子间。
因此这个字段的值在5~15之间。
·保留:长度为6位,留作今后使用,目前全部置0。
·控制:这个字段定义了6种不同的标志,每个标志占一位,在同一时间可以设置一位或多位。
URG为1时,表明有需要紧急处理的数据。
ACK为1时,表明确认号的字段有效。
PST位为1时,表明要强制切断连接。
SYN位为1时,表明有确立连接的请求,这时,把序号字段的初始值作为序号字段的值,以便开始通信。
FIN 为1时,表明发送方已经没有资料发送了。
·窗口大小:长度为16位,窗口对应的数据是以字节为单位的数据,因此最多能够传送的数据为65535B。
·紧急指针:该字段的长度为16位,指向必须紧急处理的数据的位置,只有当标志URG=1时紧急指针才有效。
从TCP报头后面的报文资料开始,到紧急指针所指出的长度的数据,就是必须紧急处理的数据。
·选项:该字段可以多达40B,包括单字节选项和多字节选项。
·校验和:该字段长度多达16位,校验和的校验范围包括伪头部、TCP报头以及应用层来的数据。
其计算方法与IP协议头部的校验的计算方法一样。
伪头部为12B,它本身并不是TCP数据包的真正头部,只是在计算校验和时,临时和TCP数据包连接在一起。
伪头部的格式如下图所示。
1.4工作环境软件:Microsoft Visual C++ 6.0;硬件:PC机一台。
二课程设计分析本课程设计的目标是发送一个TCP资料包,可以利用原始套接字来完成这个工作。
整个程序由初始化原始套接字和发送TCP数据包两个部分组成。
2.1使用原始套接字SOCKET sock;sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);或者:sock=WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,W SA_FLAG_OVERLAPPED);这里,我们设置了SOCK_RAW标志,表示我们声明的是一个原始套接字类型。
为使用发送接收超时设置,必须将标志位置位置为WSA_FLAG_OVERLAPPED。
在本课程设计中,发送TCP包时隐藏了自己的IP地址,因此我们要自己填充IP头,设置IP头操作选项。
其中flag设置为ture,并设定IP_HDRINCL 选项,表明自己来构造IP头。
注意,如果设置IP_HDRINCL 选项,那么必须具有administrator权限,要不就必须修改注册表:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Afd\ Parameter\修改键:DisableRawSecurity(类型为DWORD),把值修改为1。
如果没有,就添加。
BOOL Flag=TRUE;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.2定义IP头部、TCP头部和伪头部的数据结构//定义IP首部typedef struct _iphdr{UCHAR h_lenver; //4位首部长度+4位IP版本号UCHAR tos; //8位服务类型TOSUSHORT 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;//定义TCP伪首部typedef struct psd_hdr {ULONG saddr; //源地址ULONG daddr; //目的地址UCHAR mbz; //没用UCHAR ptcl;//协议类型USHORT tcpl; //TCP长度}PSD_HEADER;//定义TCP首部typedef struct _tcphdr{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;2.3计算校验和的子函数在填充数据包的过程中,需要调用计算校验和的函数checksum两次,分别用于校验IP头和TCP头部(加上伪头部),其实现代码如下: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);}2.4程序流程图三源代码#include <stdio.h>#include <winsock2.h>#include <ws2tcpip.h>#include <time.h>#include <windows.h>#include <string.h>#include <stdlib.h>#include <iostream.h>#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位生存时间TTLUCHAR 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;//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 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]; //检验和缓冲区const char tcp_send_data[]={"This is my homework of networt,I am happy!"};BOOL flag;int rect,nTimeOver;if (argc!= 5){printf("Useage: SendTcp soruce_ip source_port dest_ip dest_port \n");return false;}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))==INV ALID_SOCKET){printf("Socket Setup Error!\n");return false;}flag=true;if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&flag,sizeof(fl ag))==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;}//填充IP首部ipHeader.h_verlen=(IPVER<<4 | sizeof(ipHeader)/sizeof(unsigned long));ipHeader.tos=(UCHAR)0;ipHeader.total_len=htons((unsignedshort)sizeof(ipHeader)+sizeof(tcpHeader)+sizeof(tcp_send_data));ipHeader.ident=0; //16位标识ipHeader.frag_and_flags=0; //3位标志位ipHeader.ttl=128; //8位生存时间ipHeader.proto=IPPROTO_UDP; //协议类型ipHeader.checksum=0; //检验和暂时为0ipHeader.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)+sizeof(tcp_send_data));//填充TCP首部tcpHeader.th_dport=htons(atoi(argv[4])); //16位目的端口号tcpHeader.th_sport=htons(atoi(argv[2])); //16位源埠号tcpHeader.th_seq=0; //SYN序列号tcpHeader.th_ack=0; //ACK序列号置为0//TCP长度和保留位tcpHeader.th_lenres=(sizeof(tcpHeader)/sizeof(unsignedlong)<<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 ));memcpy(check_Buff+sizeof(PSD_HEADER)+sizeof(TCP_HEADER) ,tcp_send_data,sizeof(tcp_send_data));tcpHeader.th_sum=checksum(check_Buff,sizeof(PSD_HEADER)+ sizeof(TCP_HEADER)+sizeof(tcp_send_data));//填充发送缓冲区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(Sendto_Buff+sizeof(IP_HEADER)+sizeof(TCP_HEADER), tcp_send_data,sizeof(tcp_send_data));int datasize=sizeof(IP_HEADER)+sizeof(TCP_HEADER)+ sizeof(tcp_send_data);//发送数据报的目的地址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!:%d\n",WSAGetLastError());return false;}elseprintf("send ok!\n");closesocket(sock);WSACleanup();return 1;}四运行结果与运行情况在Microsoft Visual C++ 6.0下编写源程序,然后调试成功后运行,生成可执行档sendtcp.exe。