原始套接字构建 TCP三次握手 及相关问题

分析TCP、IP头部

头部字段

IP头部结构
在这里插入图片描述
TCP头部结构
在这里插入图片描述
熟悉计算机网络的同学对这些都已经很熟悉了,就不复述了。
Tip: 为了结构清晰 分开的代码可能有一定逻辑性问题,请参照源码

构建TCP伪首部结构体

用于计算校验和

struct udp_front  //tcp(udp)伪首部结构体
{
   
    uint32_t srcip;				//源IP 
    uint32_t desip;				//目的IP 
    u_int8_t zero;				
    u_int8_t protocol;			//协议类型 
    u_int16_t len;				//协议长度 
};

填充TCP伪首部

//...
struct udp_front front;
    front.srcip = ip->saddr;
    front.desip = ip->daddr;
    front.len = htons(20 + strlen(message));
    front.protocol = 6;
    front.zero = 0;

填充IP头部

    ip = (struct iphdr *)sendbuf;
    ip->ihl = sizeof(struct iphdr) >> 2; //首部长度
    ip->version = 4;   //ip协议版本
    ip->tos = 0;   //服务类型字段
    ip->tot_len = 0;   //总长度
    ip->id = htons(my_seq);   //id值
    ip->frag_off = 0;
    ip->ttl = 128;
    ip->protocol = IPPROTO_TCP;
    ip->check = 0;  //内核会算相应的效验和
//    ip->saddr = src_ip;
	//将一个点分十进制的IP转换成一个长整数型数 
	ip->saddr = inet_addr(argv[1]);
    ip->daddr = inet_addr(argv[3]);
    //...
    ip->tot_len = (20 + 20 + strlen(message));   //IP头长度+TCP头部长度+数据长度 = 总长度
    printf("ip->tot_len:%d\n",ip->tot_len);
    ip->check = in_chksum((unsigned short *)sendbuf, 20);

填充TCP头部

TCP首部的syn、ack、fin等位 必须按照三次握手的要求构建,第一次请求syn位为1,响应ack位则为1…

 struct tcphdr *tcp;
    tcp = (struct tcphdr *)(sendbuf + sizeof(struct iphdr));
    bzero(tcp, sizeof(struct tcphdr *));
    //-------------------------------------------------------------------
    //将短整型变量从主机字节顺序转变成网络字节顺序
    //htonl 长  
	//atoi 把字符串转换成整型数 
    tcp->source = htons(atoi(argv[2]));  //源端口
    tcp->dest = htons(atoi(argv[4]));    //目的端口
    tcp->seq = htonl(100000000);   
    tcp->ack_seq = htonl(ack_seq); 

    tcp->doff = 5;  //数据偏移(TCP头部字节长度/4)
    tcp->res1 = 0;  //保留字段(4位)
    tcp->fin = 0;       //..用来释放一个连接
    tcp->syn = 1;         //..表示这是一个连接请求
    tcp->rst = 0;         //..用来表示tcp连接是否出现严重差错
    tcp->psh = 0;         //..推送
    tcp->ack = 0;         //..表示是一个连接请求
    tcp->urg = 0;         //..紧急数据标志
    tcp->res2 = 0;  //保留字段(2位)
    tcp->window = htons(65535);  //初始窗口值设置

    tcp->check = 0;
    tcp->urg_ptr = 0; 
    tcp->check = 0;   //效验和,效验整个tcp数据报
    strcpy((sendbuf+20+20), message);  //把message存入IP+TCP头部位之后 

    tcp->check = tcp_check((sendbuf+20), 20+strlen(message), front);

计算校验和

想要详细了解的请 参考 博客

//计算tcp(udp)效验和
unsigned short tcp_check(char *sendbuf, int len, const struct udp_front front)
{
   
    char str[MAXLINE];
    bzero(&str, MAXLINE);
    bcopy(&front, str, sizeof(front));
    bcopy(sendbuf, str+sizeof(front), len);
    struct udp_front *ptr;
    ptr = (struct udp_front *)str;
    char *s;
    s = (str+20);
    return in_chksum((unsigned short *)str, sizeof(front)+len);
}

//效验和算法
uint16_t in_chksum(uint16_t *addr, int len)
{
   
    int nleft = len;
    uint32_t sum = 0;
    uint16_t *w = addr;
    uint16_t answer = 0;
    //把ICMP报头二进制数据以2字节为单位累加起来
    while (nleft > 1)
    {
   
        sum += *
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值