TCip数据报分片提取电路设计

TCP实现:TCP用户请求
学习TCP-IP的很好的书。TCP-IP详解卷3。
TCP实现:TCP用户请求下载
下载资料需要,并消耗一定积分。
下载此资料的人还喜欢:
技术交流、我要发言! 发表评论可获取积分! 请遵守相关规定。
本周热点资料
电子资料热门词
上传者其它资料
电子教材下载排行温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
家住群山间,生来不善言。
成长无所好,唯喜作诗篇。
拙文表心迹,愿与诸君勉。
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
TCP11-220B-60B20B40BTCP
l32TCP“”
l4TCP4B20B-60B5-15
l6URG1ACK1PSH1PST1SYN1FIN1
l16URG=1TCP
l16TCPIP7.312BTCPTCP11-3
SOCKET sockR
sockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED);
SOCK_RAWSO_RCVTIMEOSO_SNDTIMEO,WSA_FLAG_OVERLAPPEDTCPIPIPIPflagtureIP_HDRINCLIPIP_HDRINCLadministratorHKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Afd\Parameter\DisableRawSecurity(DWORD)1
boolean Flag=TRUE;
setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char*)&Flag,sizeof(Flag));
int timeout=1000;
setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));
SOL_SOCKETSO_SNDTIMEO1000ms
typedef struct _iphdr
UCHAR h_&&&&&& //4IP4
UCHAR&&&&&&&&&&& //8TOS
USHORT total_&&&&& //16
USHORT&&&&&&&& //16
USHORT frag_and_ //3
UCHAR&&&&&&&&&&& //8&& TTL
UCHAR&&&&&&&&& //8TCP/UDP
USHORT&&&&& //16IP
ULONG sourceIP;&&&&&&& //32IP
ULONG destIP;&&&&&&&&& //332IP
}IP_HEADER;
typedef struct _psdhdr
ULONG&&&&&&&&&& //
ULONG&&&&&&&&&& //
UCHAR&&&&&&&&&&&& //
UCHAR&&&&&&&&&&&&& //
USHORT&&&&&&&&&&&& //TCP
}PSD_HEADER;
typedef struct _tcphdr
USHORT th_&&&&&&&&&&& //16
USHORT th_&&&&&&&&&&& //16
ULONG th_&&&&&&&&&&&&&& //32
ULONG th_&&&&&&&&&&&&&& //32
UCHAR th_&&&&&&&&&&&& //4/6
UCHAR th_&&&&&&&&&&&&&& //6
USHORT th_&&&&&&&&&&&&& &//16
USHORT th_&&&&&&&&&&&&&& //16
USHORT th_&&&&&&&&&&&&&&& //16
}TCP_HEADER;
#define IPVER 4&&&&& &&&&&&&&&&&&&&&&//IP
#define MAX_BUFF_LEN 65500&&&&&&& //
IP_HEADER ip_header={0};&&&&&&&&&&& //IP
PSD_HEADER psd_header={0};&&&&&&&& //TCP
TCP_HEADER tcp_header={0};&&&&&&&& //TCP
char Sendto_Buff[MAX_BUFF_LEN];&&& //
unsigned short check_Buff[MAX_BUFF_LEN]; //
const char tcp_send_data[]={"This is my homework of network,I am happy!"};
ip_header.h_verlen=(IPVER&&4|sizeof(ip_header)/sizeof(unsigned long));
ip_header.tos=(UCHAR)0;&&&&&&&&&&&&&&&&&&& //
ip_header.total_len=htons((unsigned short)(sizeof(IP_HEADER)
+sizeof(TCP_HEADER)+sizeof(tcp_send_data)));
ip_header.ident=0;&&&&&&&&&&&&&&&&&&& //16
ip_header.frag_and_flags=0;&&&&&&&&&&& //3
ip_header.ttl=(UCHAR)128;&&&&&&&&&&& //8
ip_header.proto=IPPROTO_TCP;&&&&&&& //
ip_header.checksum=0;&&&&&&&&&&&&&&& //0
ip_header.sourceIP=inet_addr(argv[1]);&&& //32IP
ip_header.destIP=inet_addr(argv[3]);&&&&& //32IP
memset(check_Buff,0,MAX_BUFF_LEN);
memcpy(check_Buff,&ip_header,sizeof(IP_HEADER));
ip_header.checksum=checksum(check_Buff,sizeof(IP_HEADER));
psd_header.saddr=ip_header.sourceIP;&&& //
psd_header.daddr=ip_header.destIP;&&&&& //
psd_header.mbz=0;
psd_header.ptcl=ip_header.&&&&&&& //
psd_header.tcpl=htons(sizeof(TCP_HEADER)+sizeof(tcp_send_data));
tcp_header.th_sport=htons((unsigned short)atoi(argv[2]));
tcp_header.th_dport=htons((unsigned short)atoi(argv[4]));
tcp_header.th_seq=0; &&&&&&&&&&&&&&&//SYN
tcp_header.th_ack=0;&&&&&&&&&&&&&&& //ACK0
tcp_header.th_lenres=(sizeof(TCP_HEADER)/sizeof(unsigned long)&&4|0);
tcp_header.th_flag=(UCHAR)2;&&&&&&&&&&&&&&& //SYN
tcp_header.th_win=htons((unsigned short)16384);& //
tcp_header.th_urp=0;&&&&&&&&&&&&&&&&&&&&&&&& //
tcp_header.th_sum=0;&&&&&&&&&&&&&&&&&&&& //0
memset(check_Buff,0,MAX_BUFF_LEN);
memcpy(check_Buff,&psd_header,sizeof(PSD_HEADER));
memcpy(check_Buff+sizeof(PSD_HEADER),&tcp_header,sizeof(TCP_HEADER));
memcpy(check_Buff+sizeof(PSD_HEADER)+sizeof(TCP_HEADER),tcp_send_data,sizeof(tcp_send_data));
tcp_header.th_sum=checksum(check_Buff,sizeof(PSD_HEADER)+sizeof(TCP_HEADER)+sizeof(tcp_send_data));
ChecksumIPTCP
USHORT checksum(USHORT *buffer,int size)
& unsigned long cksum=0;
& while(size&1)
& cksum+=*buffer++;
& size-=sizeof(USHORT);
& if(size)
&&& cksum+=*(UCHAR*)
&&& cksum=(cksum&&16)+(cksum & 0xffff);
&&& cksum+=(cksum&&16);
&&& return (USHORT)(~cksum);
TCPsockaddr_insendto
memset(Sendto_Buff,0,MAX_BUFF_LEN);
memcpy(Sendto_Buff,&ip_header,sizeof(IP_HEADER));
memcpy(Sendto_Buff+sizeof(IP_HEADER),&tcp_header,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_&&&&&&&&&&&
&memset(&dest,0,sizeof(dest));
dest.sin_family=AF_INET;
dest.sin_addr.s_addr=inet_addr(argv[3]);//IP
int bwrote=sendto(sockRaw,Sendto_Buff,datasize,0,(struct sockaddr*)&dest,sizeof(dest));
ESendTCP.cppmicrosoft Visual C++ 6.0
2..1DOS“E:”cd debug
3.DOS“SendTCP”
4.DOSSendTCP 115.155.135.142 12 115.135.155.158 25
在对TCP数据包头部进行填充时,首先需要我们去充分了解它的数据结构,在这个过程中可以了解相应字节上应该存放的内容和它们的功能。由于本次的课程设计只要求填充一个TCP数据包,然后将其发送出去,使用的数据发送函数是成功地完成调用只能保证数据已经从本地发送出去,并不意味着数据传送到达目的地。
C/C++JavaJava
class SendTCP
& public static void main(String[] args)
&if(args.lenth!=4)
&& System.out.println(“Your input is Wrong Try again!”);
&& System.ecit(0);
&& String str=new String(“This is my homework of network,I am happy!”);
&& Socket socketObj=new Socket(args[2],Integer.parseInt(args[3]));
OutputStream os=socketOnj.getOutputStream();
OutputStream Write osw=new OutputStream Writer(os);
Osw.writer(str);
Osw.flush();
socketObj.close();
System.out.println(“Send OK!”);
&&&&&& Catch(IOException e)
&&&&&&&& System.out.println(“Sorry,can’t connect to ”+args[0]+” :”+args[3]);
&&&&&&&&& System.out.println(e);
//SendTCP.cpp
#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_&&&&&&&&&&& //4,4IP
UCHAR&&&&&&&&&&&&&&& //8TOS
USHORT total_&&&&&&& //16
USHORT&&&&&&&&&&& //16
USHORT frag_and_&&& //3
UCHAR&&&&&&&&&&&&&&& //8 TTL
UCHAR&&&&&&&&&&& //8 (TCP, UDP )
USHORT&&&&&&& //16IP
ULONG sourceIP;&&&&&&&&&&& //32IP
ULONG destIP;&&&&&&&&&&& //32IP
}IP_HEADER;
typedef struct tsd_hdr //TCP
ULONG&&& //
ULONG&&& //
UCHAR&&&&&&& //
UCHAR&&&&&&& //
USHORT&&& //TCP
}PSD_HEADER;
typedef struct tcp_hdr //TCP
USHORT th_&&&&&&&&&&& //16
USHORT th_&&&&&&&&&&& //16
ULONG th_&&&&&&&&&&&&&&& //32
ULONG th_&&&&&&&&&&&&&&& //32
UCHAR th_&&&&&&&&&&& //4/6
UCHAR th_&&&&&& &&&&&&&&&//6
USHORT th_&&&&&&&&&&&&&&& //16
USHORT th_&&&&&&&&&&&&&&& //16
USHORT th_&&&&&&&&&&&&&&& //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*)
&&& cksum = (cksum && 16) + (cksum & 0xffff);
&&& cksum += (cksum &&16);
&&& return (USHORT)(~cksum);
int main(int argc, char* argv[])
&&& WSADATA WSAD
&&& SOCKET
&&& IP_HEADER ipH
&&& TCP_HEADER tcpH
&&& PSD_HEADER psdH
&&& 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!"};
&&& int rect,nTimeO
&&& if (argc!= 5)
&&&&&&& printf("Useage: SendTcp soruce_ip source_port dest_ip dest_port \n");
&&& if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0)
&&&&&&& printf("WSAStartup Error!\n");
if((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,
WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
&&&&&&& printf("Socket Setup Error!\n");
&&& if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&flag,sizeof(flag))==
SOCKET_ERROR)
&&&&&&& printf("setsockopt IP_HDRINCL error!\n");
&&& nTimeOver=1000;
&&& if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR)
&&&&&&& printf("setsockopt SO_SNDTIMEO error!\n");
&&& ipHeader.h_verlen=(IPVER&&4 | sizeof(ipHeader)/sizeof(unsigned long));
&&& ipHeader.tos=(UCHAR)0;
&&& ipHeader.total_len=htons((unsigned short)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; //0
&&& ipHeader.sourceIP=inet_addr(argv[1]);& //32IP
&&& ipHeader.destIP=inet_addr(argv[3]);&&& //32IP
&&& memset(check_Buff,0,MAX_BUFF_LEN);
&&& memcpy(check_Buff,&ipHeader,sizeof(IP_HEADER));
&&& ipHeader.checksum=checksum(check_Buff,sizeof(IP_HEADER));
&&& psdHeader.saddr=ipHeader.sourceIP;
&&& psdHeader.daddr=ipHeader.destIP;
&&& psdHeader.mbz=0;
&&& psdHeader.ptcl=ipHeader.
&&& psdHeader.tcpl=htons(sizeof(TCP_HEADER)+sizeof(tcp_send_data));
&&& 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;&&&&&&&&&&&&&&&&&&&&&&&& //ACK0
&&& tcpHeader.th_lenres=(sizeof(tcpHeader)/sizeof(unsigned long)&&4|0);
&&& tcpHeader.th_flag=2; //2SYN1//FIN16ACK
&&& tcpHeader.th_win=htons((unsigned short)16384);&&&& //
&&& tcpHeader.th_urp=0;&&&&&&&&&&&&&&&&&&&&&&&&&&& //&&&
&&& tcpHeader.th_sum=0;&&&&&&&&&&&&&&&&&&&&&&&&&&& //0
&&& 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&&&
&&& 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());
&&& printf("send ok!\n");
&&& closesocket(sock);
&&& WSACleanup();
&&& return 1;
阅读(5628)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_083069',
blogTitle:'【课程设计】发送TCP数据包',
blogAbstract:'
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}2008年2月 VB大版内专家分月排行榜第一2003年4月 VC/MFC大版内专家分月排行榜第一2002年11月 VC/MFC大版内专家分月排行榜第一
2011年11月 VC/MFC大版内专家分月排行榜第二2008年3月 VB大版内专家分月排行榜第二2008年3月 硬件/嵌入开发大版内专家分月排行榜第二2003年4月 其他开发语言大版内专家分月排行榜第二2003年4月 VB大版内专家分月排行榜第二2003年3月 VB大版内专家分月排行榜第二
本帖子已过去太久远了,不再提供回复功能。计算机网络(4)
& CSDN lidp &
tcp/ip协议栈属于操作系统内核层,通过提供系统调用供用户空间访问,从数据报到达最底层的网卡到最终传递给上层软件有一个过程,
当一个数据报到达时网络驱动程序把数据报放到一个队列中,同时发送一个消息给ip进程,这里ip进程是一个独立的程序,专门处理ip数据报,tcp/ip协议栈中,根据协议的功能及复杂程度,一般通过进程方式实现,而协议间的数据传递则借助于操作系统提供的进程间通讯机制,当ip进程接受了一个传入的数据报,他必须决定将其发往何处作进一步处理,如果数据报中的内容是一个报文段,则必须将其交付给TCP模块,如果他携带的是用户数据报(UDP),则必须将其交付给udp模块,以此类推。
由于TCP比较复杂,因而在许多设计方案中,有一个独立的进程来处理传入的TCP报文段,由于IP和TCP有各自独立的进程执行,因而IP和TCP必须借助进程间的通信机制来通信。
一旦tcp模块收到ip进程传送过来的报文段,就利用tcp协议端口号来寻找该报文段所属的连接,如果报文段中含有数据,TCP将把数据添加到与该连接相关的一个缓冲区中,并给发送方返回一个确认,如果输入的报文段中含有对放送出去的数据的确认,tcp输入进程还必须与tcp定时器管理进程通信,取消超时重发事件。
而处理udp数据报的进程结构与处理tcp进程采用的结构不同,由于udp比tcp要简单,udp模块不作为独立进程存在,事实上,它是由一些常规过程组成。ip进程通过调用来处理传入的udp数据报,这些过程检查udp目的站的协议端口号,根据端口号为udp数据报选择一个操作系统队列,ip进程把udp数据报放在响应的端口中,是应用程序可从这些端口中提取数据报。
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &TCP/UDP数据输入流程图
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &&
TCP数据报输出过程
与输入一样,tcp的输出也是很复杂的,必须先建立连接,所传送的数据必须放到报文段中,在对方发来确认之前,报文段必须不断重发,tcp把报文交给ip,由ip来处理选路和传送,系统协议栈利用两个tcp进程来处理这一复杂过程,一个为tcpout,由他来处理报文段和数据传输细节,另一个进程是tcptimer,他管理一个定时器,为超时重发事件定时,通知tcpout进程重发。下图为tcp, udp数据输出结构图。
& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &&
总结:tcp/ip协议栈是计算机操作系统中的一部分,它使用进程这一抽象概念使各个协议软件互相独立,每一个进程独立执行,并提供明确的并行机制,这种系统中有ip进程,tcp输入进程,tcp输出进程和tcp定时器管理进程,同时每个应用程序还各有一个进程。
上层应用程序作为独立进程通过系统调用向tcp传递数据流或者想udp数据报,对于udp输出处理,运行某个应用程序的进程调用一个系统调用,执行一段udp过程,申请一个ip数据报,填写相应的目的地址,将udp数据封装在Ip数据报中,然后将ip数据报传递给ip进程,由ip进程发送出去。
对于tcp输出,运行应用程序的进程调用一个系统调用(socket,send..),将数据传入操作系统中,并保存在一个缓冲区内,应用进程随后通知tcp输出进程,有新的数据等待发送,当tcp输出进程执行时,他将数据流划分成报文段,然后将这些数据封装在ip数据报中,最后,tcp输出进程将ip数据报放入某一端口中,ip进程将从该端口中提取并发送这些数据报。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:39727次
排名:千里之外
原创:20篇
转载:53篇
(2)(18)(12)(10)(10)(3)(8)(3)(17)socket(6)
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的通信协议,数据在传输前要建立连接,传输完毕后还要断开连接。
客户端在收发数据前要使用 connect() 函数和服务器建立连接。建立连接的目的是保证IP地址、端口、物理链路等正确无误,为数据的传输开辟通道。
TCP建立连接时要传输三个数据包,俗称三次握手(Three-way
Handshaking)。可以形象的比喻为下面的对话:
[Shake 1] 套接字A:“你好,套接字B,我这里有数据要传送给你,建立连接吧。”[Shake 2] 套接字B:“好的,我这边已准备就绪。”[Shake 3] 套接字A:“谢谢你受理我的请求。”
TCP数据报结构
我们先来看一下TCP数据报的结构:
带阴影的几个字段需要重点说明一下:
1) 序号:Seq(Sequence Number)序号占32位,用来标识从计算机A发送到计算机B的数据包的序号,计算机发送数据时对此进行标记。
2)&确认号:Ack(Acknowledge Number)确认号占32位,客户端和服务器端都可以发送,Ack = Seq + 1。
3)&标志位:每个标志位占用1Bit,共有6个,分别为 URG、ACK、PSH、RST、SYN、FIN,具体含义如下:
URG:紧急指针(urgent pointer)有效。ACK:确认序号有效。PSH:接收方应该尽快将这个报文交给应用层。RST:重置连接。SYN:建立一个新连接。FIN:断开一个连接。
对英文字母缩写的总结:Seq 是&Sequence 的缩写,表示序列;Ack(ACK) 是&Acknowledge 的缩写,表示确认;SYN 是&Synchronous 的缩写,愿意是“同步的”,这里表示建立同步连接;FIN 是 Finish 的缩写,表示完成。
连接的建立(三次握手)
使用 connect() 建立连接时,客户端和服务器端会相互发送三个数据包,请看下图:
客户端调用 socket() 函数创建套接字后,因为没有建立连接,所以套接字处于CLOSED状态;服务器端调用
listen() 函数后,套接字进入LISTEN状态,开始监听客户端请求。
这个时候,客户端开始发起请求:
1) 当客户端调用 connect() 函数后,TCP协议会组建一个数据包,并设置 SYN 标志位,表示该数据包是用来建立同步连接的。同时生成一个随机数字 1000,填充“序号(Seq)”字段,表示该数据包的序号。完成这些工作,开始向服务器端发送数据包,客户端就进入了SYN-SEND状态。
2) 服务器端收到数据包,检测到已经设置了 SYN 标志位,就知道这是客户端发来的建立连接的“请求包”。服务器端也会组建一个数据包,并设置 SYN 和 ACK 标志位,SYN 表示该数据包用来建立连接,ACK
用来确认收到了刚才客户端发送的数据包。
服务器生成一个随机数 2000,填充“序号(Seq)”字段。2000 和客户端数据包没有关系。
服务器将客户端数据包序号(1000)加1,得到1001,并用这个数字填充“确认号(Ack)”字段。
服务器将数据包发出,进入SYN-RECV状态。
3) 客户端收到数据包,检测到已经设置了 SYN 和 ACK 标志位,就知道这是服务器发来的“确认包”。客户端会检测“确认号(Ack)”字段,看它的值是否为 ,如果是就说明连接建立成功。
接下来,客户端会继续组建数据包,并设置 ACK 标志位,表示客户端正确接收了服务器发来的“确认包”。同时,将刚才服务器发来的数据包序号(2000)加1,得到 2001,并用这个数字来填充“确认号(Ack)”字段。
客户端将数据包发出,进入ESTABLISED状态,表示连接已经成功建立。
4) 服务器端收到数据包,检测到已经设置了 ACK 标志位,就知道这是客户端发来的“确认包”。服务器会检测“确认号(Ack)”字段,看它的值是否为 ,如果是就说明连接建立成功,服务器进入ESTABLISED状态。
至此,客户端和服务器都进入了ESTABLISED状态,连接建立成功,接下来就可以收发数据了。
最后的说明
三次握手的关键是要确认对方收到了自己的数据包,这个目标就是通过“确认号(Ack)”字段实现的。计算机会记录下自己发送的数据包序号 Seq,待收到对方的数据包后,检测“确认号(Ack)”字段,看Ack
= Seq + 1是否成立,如果成立说明对方正确收到了自己的数据包。
大致流程:首先是客户端发起请求连接,服务器告诉客户端服务器已经连接,客户端收到后告诉服务器他已经连接。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:6419次
排名:千里之外
转载:19篇
(5)(2)(1)(7)(2)(1)(9)}

我要回帖

更多关于 易语言数据报 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信