IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> TCP三次握手模拟 -> 正文阅读

[网络协议]TCP三次握手模拟

本博客是计算机网络课程设计任务----模拟TCP三次握手。

可能读者看到“模拟TCP三次握手”时首先会先入为主的认为这是一个很难的课题,要模拟TCP三次握手,会用到计算机通信接口什么的,其实不是这样的。所谓模拟我们只需要在有一个握手过程就行了,简单来说就是,我们能创建两个能相互通信的进程,某个进程率先发起通信请求,另外一个进程收到通信请求,返回一个消息,发起进程再回复一个消息,实现这样一个过程我们就一次“TCP三次握手”!

首先,介绍一下博主的思路:

? ? ? ? 因为要完成这个模拟,需要两个能相互通信的进程(或者说程序),博主首先想到的是Web前后端,因为Socket技术诞生后,前后端程序都能主动向另一方发送消息,这一特性完美解决了课题中两个进程需要通信的问题。

? ? ? ? 所以技术方面本博主采用node.js搭建了一个简易的后端,前端用原生html,css,以及js实现。

项目目录结构如下:

node_modules是导入的模块包使用npm自动安装的,public文件夹是用来放前端文件,app.js是项目入口文件,也是后端事务处理实现。

具体操作如下:

在创建的文件目录下执行npm指令:

按照目录结构所示创建app.js等文件。

主要代码实现如下:

app.js:

/*
服务端
*/
var app = require('express')()
var server = require('http').Server(app)
var io = require('socket.io')(server)

server.listen(3000,()=>{
    console.log("服务器启动成功!")
})
//express处理静态资源
//把public目录设置为静态资源目录
app.use(require('express').static('public'))

app.get('/',function(req,res){
    res.redirect('/index.html')
})

//定义一个模拟TCP报文的Json文件
var TCP_S={}
TCP_S.rport=9090
//定义是否建立连接
var isLink=false

io.on('connection',function(socket){
    console.log("新用户连接了")
    socket.on('asklink',data=>{
        if(data.TCP_C.dport==TCP_S.rport){
            if(data.TCP_C.SYN==1&&data.TCP_C.ACK==0){
                if(isLink){
                    socket.emit('sechandshake',{
                        flag:1,
                        msg:"已建立连接!"
                    })
                }else{
                    console.log("第一次握手")
                    TCP_S.dport=data.TCP_C.rport,
                    TCP_S.SYN=1,
                    TCP_S.ACK=1,
                    TCP_S.seq=Math.ceil(Math.random()*10)
                    TCP_S.ack=data.TCP_C.seq+1
                    socket.emit('sechandshake',{
                        flag:0,
                        TCP_S
                    })
                }
            }else{
                console.log("第一握手失败")
            }
        }else{
            console.log("report:"+data.TCP_C.rport)
            socket.emit('failLink',{
                msg:"该端口不存在"
            })
        }
    })

    socket.on('thirdlink',data=>{
        //判断第三次握手的数据
        //console.log("第三次请求")
        if(data.TCP_C.SYN==1&&data.TCP_C.ACK){
            if(data.TCP_C.seq==TCP_S.ack&&data.TCP_C.ack==(TCP_S.seq+1)){
                isLink=true
                console.log("第三次握手成功!确认建立连接")
                socket.emit('affLink',{
                    msg:"确认建立连接!允许发送消息"
                })

            }else{
                console.log("第三次握手失败,数据不匹配,断开连接!")
                console.log("TCP_C:"+data.TCP_C.seq+"  TCP_S:"+TCP_S.ack+"  TCP_C:"+data.TCP_C.ack+"  TCP_S"+TCP_S.seq)
            }
        }else{
            console.log("第三次握手请求失败,断开连接!")
        } 
    })
    
    socket.on('lunxchmsg',data=>{
        if(isLink){
            console.log(data)
            if(data.msg==1){
                socket.emit('remsg',{
                    flag:1,
                    msg:`服务器信息如下:IPv6 地址 . . . . . . . . . . . . : 2001:da8:8011:371f:acee:16fb:8585:8dd1
                                        临时 IPv6 地址. . . . . . . . . . : 2001:da8:8011:371f:a1bb:25d0:d11:5e3a
                                        本地链接 IPv6 地址. . . . . . . . : fe80::acee:16fb:8585:8dd1%21
                                        IPv4 地址 . . . . . . . . . . . . : 10.55.25.81
                                        子网掩码  . . . . . . . . . . . . : 255.255.240.0
                                        默认网关. . . . . . . . . . . . . : fe80::4abd:3dff:fe22:77e0%21
                                                                            10.55.31.254 `
                })
            }else{
                socket.emit('remsg',{
                    msg:"这是回复消息:"+data.msg,
                    flag:1
                })
            }
        }else{
            socket.emit('remsg',{       
                msg:"未建立连接,不支持发送消息",
                flag:0
            })
        }
    })
    
    socket.on('disconnect',()=>{
        console.log("用户断开连接!")
        isLink=false
    })


})


js文件夹下的index.js文件(jquery文件是从网上下载的,这里就不粘贴了)

/*
客户端
*/
//连接socket服务
var socket = io('http://localhost:3000')
var TCP_C = {}
TCP_C.rport=9000
// 需要告诉socket io服务,客户端请求登录
$('#asklink').on('click', function () {
    //设置第一次请求参数
    TCP_C.dport=$('#link_port').val().trim()
    TCP_C.SYN=1
    TCP_C.ACK=0
    TCP_C.seq=Math.ceil(Math.random()*10)
    $('.showmsg').append("<p>正在进行第一次握手,参数为:SYN="+TCP_C.SYN+"  ACK="+TCP_C.ACK+"  seq="+TCP_C.seq+"</p>")     
    socket.emit('asklink', {
       TCP_C
    })
    sleep(1000)
  })

socket.on('failLink',data=>{
    alert(data.msg)
    $('.showmsg').append("<p>请求的端口不存在,连接失败!</p>")
})

socket.on('sechandshake',data=>{
    if(data.flag){
        $('.showmsg').append("<p>"+data.msg+"</p>")
    }else{
        if(data.TCP_S.SYN==1&&data.TCP_S.ACK==1&&data.TCP_S.ack==(TCP_C.seq+1)){
            $('.showmsg').append("<p>第二次握手成功!参数为:SYN="+data.TCP_S.SYN+"  ACK="+data.TCP_S.ACK+"  ack="+data.TCP_S.ack+"  seq="+data.TCP_S.seq+"</p>")
            TCP_C.ACK=1
            TCP_C.seq=data.TCP_S.ack
            TCP_C.ack=data.TCP_S.seq+1
            sleep(1000)
            socket.emit('thirdlink',{
                TCP_C
            })
            sleep(1000)
            $('.showmsg').append("<p>正在进行第三次握手,参数为:SYN="+TCP_C.SYN+"  ACK="+TCP_C.ACK+"  ack="+TCP_C.ack+"  seq="+TCP_C.seq+"</p>")
            
        }else{
            console.log("第二次握手失败!")
            $('.showmsg').text("第二次握手失败")
        }
    }
})

socket.on('affLink',data=>{
    $('.showmsg').append("<p>"+data.msg+"</p>")
    sleep(1000)
    alert(data.msg)
})

//显示细节
var flag=1
$('#showdetail_B').on('click', function () {
    
    if(flag){
        $('#showdetail').fadeIn()
        flag=0
    }else{
        $('#showdetail').hide()
        flag=1
    }
  })

  $('#LunchMsg').on('click', function () {
   socket.emit('lunxchmsg',{
       msg:$('#Lunch_txt').val().trim()
   })
  })

  socket.on('remsg',data=>{
      if(data.flag){
        $('#socketremsg').text("<p>"+data.msg+"</p>")
      }else{
        alert(data.msg)
      }
  })

//睡眠函数
function sleep(delay) {
    let now = new Date();
    const exitTime = now.getTime() + delay;
    let complite=true;
    while (complite) {
        now = new Date();
        if (now.getTime() > exitTime) {
            complite=false;
        }
    }
    return;
}

前端页面显示index.html文件:

<!DOCTYPE html>
<html>
    <head>
        <title>TCP三次握手</title>
        <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
        <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
        <link rel="stylesheet" href="css/style.css">
    </head>
    <body>
        <div class="container">
            <div class="row">
                <div class="col-md-2" id="sidePage"></div>
                <!--正文-->
                <div class="col-md-8">
                    <div class="emptyBox"></div>
                    <div class="sendBox">
                        <h1 id="title_h1">TCP三次握手模拟</h1>
                        <div class="input-group">
                            <input type="text" id="link_port" class="form-control" placeholder="Input a port you want">
                            <span class="input-group-btn">
                              <button class="btn btn-default" type="button" id="asklink">Link</button>
                            </span>
                        </div>
                        <button class="btn btn-default" type="button" id="showdetail_B">显示细节</button>
                        <div id="showdetail">
                        <p id="showmsg" class="showmsg"></p>
                        </div>
                        <div class="input-group">
                            <input type="text" id="Lunch_txt" class="form-control" placeholder="Input a port you want">
                            <span class="input-group-btn">
                              <button class="btn btn-default" type="button" id="LunchMsg">Lunch</button>
                            </span>
                        </div>
                        <p id="socketremsg"></p>
                    </div>
                </div>
                <!---->
                <div class="col-md-2" id="sidePage"></div>
            </div>
        </div>
        <script src="/socket.io/socket.io.js"></script>      
        <script src="js/jquery.js"></script>
        <script src="js/index.js"></script>
        
    </body>
</html>

写好后在该目录下使用指令启动项目:

本项目监听的是本机3000端口,打开浏览器出入:localhost:3000效果如下:

?输入我们设定的9090端口,点击link效果如下:

?

?

?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:33:55  更:2021-08-09 10:33:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 9:09:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码