TCP/IP头格式
IP头格式:
版本号 (4位)
IP头长度 (4位)
服务类型 (8位)
数据包长度 (16位)
标识段 (16位)
标志段 (16位)
生存时间 (8位)
传输协议 (8位)
头校验和 (16位)
发送地址 (16位)
目标地址 (16位)
选项
填充
简单说明
============
1. IP头长度计算所用单位为32位字, 常用来计算数据开始偏移量
2. 数据包长度用字节表示, 包括头的长度, 因此最大长度为65535字节
3. 生存时间表示数据被丢失前保存在网络上的时间, 以秒计.
4. 头校验和的算法为取所有16位字的16位和的补码.
5. 选项长度是可变的, 填充区域随选项长度变化, 用于确保长度为整字节的倍数.
描述
============
struct iphdr {
BYTE versionihl;
BYTE tos;
WORD tot_len;
WORD id;
WORD frag_off;
BYTE ttl;
BYTE protocol;
WORD check;
DWORD saddr;
DWORD daddr;
/* Put options here. */
};
二、TCP头格式
TCP头格式:
源端口 (16位)
目的端口 (16位)
序号 (32位)
确认号 (32位)
数据偏移 (4位)
保留 (6位)
标志 (6位)
窗口 (16位)
校验和 (16位)
紧急指针 (16位)
选项
填充
简单说明
============
1. 数据偏移用于标识数据段的开始
2. 保留段6位必须为0
3. 标志包括紧急标志、确认标志、入栈标志、重置标志、同步标志等。
4. 校验和计算方式为将头与16位二进制反码和中的16位二进制反码加在一起。
5. 选项长度是可变的, 填充区域随选项长度变化, 用于确保长度为整字节的倍数.
6. 更详细的说明请参阅有关资料。
描述
============
struct tcphdr {
WORD SourPort;
WORD DestPort;
DWORD SeqNo;
DWORD AckNo;
BYTE HLen;
BYTE Flag;
WORD Window;
WORD ChkSum;
WORD UrgPtr;
/* Put options here. */
};
UDP
一、说明
使用UDP时,直接使用API代替控件。
第一个程序(ReadBufferUdp)使用来接收到缓存中。
"Destino"变量非常重要,如果你从其他地方接收数据到Buffer,你必须设置Destino = 0
并且在以后执行的时候赋值你将要发送的包的地址给它(after the execution it will have the address
which send you the packet.)。
如果你只想从一个指定的地址接收数据,你必须设置变量Destino = <address>.
"gvEncerrar" 用来中止处理过程。(gvEncerrar被设置为全局变量。)
超时时间设置。"Inicio + 12" = 12 sec of timeout.
第三个程序是用来准备WinSock程序。
二、代码
int ReadBufferUdp(unsigned long *Destino,void *T,int Size)
{
char Buffer[128];
SOCKADDR_IN SockAddr;
int LenSockAddr=sizeof(SOCKADDR_IN);
fd_set FdRead;
struct timeval t_val;
int Ret;
time_t Inicio = time(NULL);
Application->ProcessMessages();
if(gvEncerrar)
return false;
FD_ZERO(&FdRead);
FD_SET(gvSocket,&FdRead);
t_val.tv_sec=0;
t_val.tv_usec=0;
while((Ret=select(0,&FdRead,NULL,NULL,&t_val))!=1 && (Inicio + 12) >
time(NULL) && !gvEncerrar)
{
FD_ZERO(&FdRead);
FD_SET(gvSocket,&FdRead);
t_val.tv_sec=0;
t_val.tv_usec=0;
Application->ProcessMessages();
}
if(Ret != 1)
return false;
if(recvfrom(gvSocket,Buffer,Size,0,(LPSOCKADDR)&SockAddr,&LenSockAddr)!=Size)
return false;
if(*Destino == 0)
{
*Destino = SockAddr.sin_addr.s_addr;
}
else
if(*Destino != SockAddr.sin_addr.s_addr)
return false;
memcpy(T,Buffer,Size);
return true;