HOME 首頁
SERVICE 服務(wù)產(chǎn)品
XINMEITI 新媒體代運營
CASE 服務(wù)案例
NEWS 熱點資訊
ABOUT 關(guān)于我們
CONTACT 聯(lián)系我們
創(chuàng)意嶺
讓品牌有溫度、有情感
專注品牌策劃15年

    tcp服務(wù)器端流程(tcp服務(wù)器程序)

    發(fā)布時間:2023-03-19 03:00:31     稿源: 創(chuàng)意嶺    閱讀: 50        問大家

    大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關(guān)于tcp服務(wù)器端流程的問題,以下是小編對此問題的歸納整理,讓我們一起來看看吧。

    開始之前先推薦一個非常厲害的Ai人工智能工具,一鍵生成原創(chuàng)文章、方案、文案、工作計劃、工作報告、論文、代碼、作文、做題和對話答疑等等

    只需要輸入關(guān)鍵詞,就能返回你想要的內(nèi)容,越精準(zhǔn),寫出的就越詳細(xì),有微信小程序端、在線網(wǎng)頁版、PC客戶端

    官網(wǎng):https://ai.de1919.com

    本文目錄:

    tcp服務(wù)器端流程(tcp服務(wù)器程序)

    一、TCP/IP協(xié)議棧的封裝過程

    以傳輸層采用TCP或者UPD、網(wǎng)絡(luò)層采用IP、鏈路層采用Ethernet為例。用戶數(shù)據(jù)必須經(jīng)過應(yīng)用層協(xié)議封裝后傳遞給傳輸層,傳輸層封裝TCP頭部,交給網(wǎng)絡(luò)層,網(wǎng)絡(luò)層再封裝IP頭部,再交給數(shù)據(jù)鏈路層,數(shù)據(jù)鏈路層封裝Ethernet幀頭和幀尾,交給物理層,物理層以比特流的形式將數(shù)據(jù)發(fā)送到物理線路上。其TCP/IP中報文的封裝過程如圖1所示。

    TCP為應(yīng)用程序提供一種面向連接的、可靠的服務(wù)。

    1.面向連接的傳輸。

    2.最大報文段長度。

    3.傳輸確認(rèn)機制。

    4.首部和數(shù)據(jù)的校驗和。

    5.流量控制。

    TCP使用IP作為網(wǎng)絡(luò)協(xié)議,TCP數(shù)據(jù)段被封裝在一個IP數(shù)據(jù)包內(nèi)。TCP數(shù)據(jù)段由TCP Head(頭部)和TCP Data(數(shù)據(jù))組成。

    TCP最多有60個字節(jié)的首部,如果沒有任選字段,正常的長度是20字節(jié)。TCP Head如圖3表示的一些字段組成,這里列出幾個常用的字段。

    16位源端口號: TCP會為源應(yīng)用程序分配一個源端口號。

    16位目的端口號: 目的應(yīng)用程序的端口號。每個TCP段都包含源和目的端口號,用于尋找發(fā)端和收端應(yīng)用程序。這兩個值加上IP首部中的源端IP地址和目的端IP地址可以唯一確定一個TCP連接。

    32位序列號: 用于標(biāo)識從TCP發(fā)端想TCP收端發(fā)送的數(shù)據(jù)字節(jié)流。

    32位確認(rèn)序列號: 確認(rèn)序列號包含發(fā)送確認(rèn)的一段所期望收到的下一個序號。確認(rèn)序號為上次成功收到數(shù)據(jù)序列號加1。

    4位首部長度: 表示首部占32bit字的數(shù)目。因為TCP首部的最大長度為60字節(jié)。

    16位窗口大小 :表示接收端期望接收的字節(jié),由于該字段為16位,因而窗口大小最大值為65535字節(jié)。

    16位檢驗和: 檢驗和覆蓋了整個TCP報文段,包括TCP首部和TCP數(shù)據(jù)。該值有發(fā)端計算和存儲并由接收端進行驗證。

    TCP連接的建立是一個三次握手的過程。如圖4所示。

    1、請求端(通常也稱為客戶端)發(fā)送一個SYN段表示客戶期望連接服務(wù)器端口,初始序列號為a。

    2、服務(wù)器發(fā)回序列號為b的SYN段作為響應(yīng)。同時設(shè)置確認(rèn)序號為客戶端的序列號加1(a+1)作為對客戶端的SYN報文的確認(rèn)。

    3、客戶端設(shè)置序列號為服務(wù)器端的序列號加1(b+1)作為對服務(wù)器端SYN報文段的確認(rèn)。

    這三個報文段完成TCP連接的建立。

    TCP連接的建立是一個三次握手的過程,而TCP連接的終止則需要經(jīng)過四次握手,如圖5所示。

    1、請求端(通常也稱為客戶端)想終止連接則發(fā)送一個FIN段,序列號設(shè)置為a。

    2、服務(wù)器回應(yīng)一個確認(rèn)序列號為客戶端的序列號加1(a+1)的ACK確認(rèn)段,作為對客戶端的FIN報文的確認(rèn)。

    3、服務(wù)器端向客戶端發(fā)送一個FIN終止段(設(shè)置序列號為b,確認(rèn)號為a+1)。

    4、客戶端返回一個確認(rèn)報文(設(shè)置序列號為b+1)作為響應(yīng)。

    二、簡述TCP協(xié)議建立連接的過程

    1,TCP使用三次握手

    three-way

    handshake

    協(xié)議來建立連接,這三次握手為:

    請求端(通常稱為客戶)發(fā)送一個

    SYN

    報文段(

    SYN

    1

    )指明客戶打算連接的服務(wù)器的端口,以及初始順序號(

    ISN

    )。

    服務(wù)器發(fā)回包含服務(wù)器的初始順序號的

    SYN

    報文段(

    SYN

    1

    )作為應(yīng)答。同時,將確認(rèn)號設(shè)置為客戶的

    ISN

    1

    以對客戶的

    SYN

    報文段進行確認(rèn)(

    ACK

    也為

    1

    )。

    客戶必須將確認(rèn)號設(shè)置為服務(wù)器的

    ISN

    1

    以對服務(wù)器的

    SYN

    報文段進行確認(rèn)(

    ACK

    1

    ),該報文通知目的主機雙方已完成連接建立。

    發(fā)送第一個

    SYN

    的一端將執(zhí)行主動打開(

    active

    open

    ),接收這個

    SYN

    并發(fā)回下一個

    SYN

    的另一端執(zhí)行被動打開(

    passive

    open

    )。另外,

    TCP

    的握手協(xié)議被精心設(shè)計為可以處理同時打開(

    simultaneous

    open

    ),對于同時打開它僅建立一條連接而不是兩條連接。因此,連接可以由任一方或雙方發(fā)起,一旦連接建立,數(shù)據(jù)就可以雙向?qū)Φ鹊亓鲃?,而沒有所謂的主從關(guān)系。

     

    2,應(yīng)用層向TCP層發(fā)送用于網(wǎng)間傳輸?shù)?、?位字節(jié)表示的數(shù)據(jù)流,然后TCP把數(shù)據(jù)流分割成適當(dāng)長度的報文段(通常受該計算機連接的網(wǎng)絡(luò)的數(shù)據(jù)鏈路層的最大傳送單元(MTU)的限制)。之后TCP把結(jié)果包傳給IP層,由它來通過網(wǎng)絡(luò)將包傳送給接收端實體的TCP層。TCP為了保證不發(fā)生丟包,就給每個字節(jié)一個序號,同時序號也保證了傳送到接收端實體的包的按序接收。然后接收端實體對已成功收到的字節(jié)發(fā)回一個相應(yīng)的確認(rèn)(ACK);

    如果發(fā)送端實體在合理的往返時延(RTT)內(nèi)未收到確認(rèn),那么對應(yīng)的數(shù)據(jù)(假設(shè)丟失了)將會被重傳。TCP用一個校驗和函數(shù)來檢驗數(shù)據(jù)是否有錯誤;在發(fā)送和接收時都要計算校驗和。

    三、C#中TCP進行同步套接字編程,服務(wù)器和客戶端的工作流程(需要代碼和圖)

    代碼來了,。。

    服務(wù)器:

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Text;

    using System.Windows.Forms;

    using System.Net.Sockets;

    using System.Net;

    using System.Reflection;

    using System.Diagnostics;

    using System.Text.RegularExpressions;

    namespace msgServer

    {

    public partial class frmServer : Form

    {

    private Socket socket;

    private IPAddress myIP;

    private IPEndPoint endPoint;

    private int point;

    private Socket clientSocket;

    private Assembly ass = null;

    private System.IO.Stream stream = null;

    private System.Media.SoundPlayer pl;

    private string txt;

    private byte[] bs = new byte[512];

    public frmServer()

    {

    InitializeComponent();

    ass = Assembly.GetExecutingAssembly();

    stream = ass.GetManifestResourceStream("msgServer.msg.wav");

    pl = new System.Media.SoundPlayer(stream);

    }

    //字體選擇

    private void btnFont_Click(object sender, EventArgs e)

    {

    FontDialog font = new FontDialog();

    font.ShowEffects = true;

    font.ShowColor = true;

    font.MinSize = 12;

    font.Font = new Font("楷體_GB2312", 18, FontStyle.Bold);

    font.Color = Color.Blue;

    if (font.ShowDialog() == DialogResult.OK)

    {

    rtxtSend.Font = font.Font;

    rtxtSend.ForeColor = font.Color;

    }

    }

    //開始監(jiān)聽

    private void btnStart_Click(object sender, EventArgs e)

    {

    System.Threading.Thread th1 = new System.Threading.Thread(ToConnect);

    th1.Start();

    }

    //去連接

    private void ToConnect()

    {

    try

    {

    myIP = IPAddress.Parse(txtIP.Text.Trim());//IP

    point = Convert.ToInt32(txtPoint.Text.Trim());//Point

    endPoint = new IPEndPoint(myIP, point); //終端

    socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    socket.Bind(endPoint);//綁定

    socket.Listen(3); //最多3人同時連接

    lblStatus.Text = "服務(wù)器已經(jīng)運行...";

    clientSocket = socket.Accept();//等待接受

    //連接上時

    if (clientSocket.Connected)

    {

    lblStatus.Text = "已經(jīng)建立連接.";

    while (true)

    {

    try

    {

    clientSocket.Receive(bs, bs.Length, 0);

    pl.Play();

    rtxtMsg.AppendText(System.Text.Encoding.Unicode.GetString(bs));

    }

    catch { lblStatus.Text = "連接已經(jīng)斷開."; }

    }

    }

    }

    catch { txtIP.Focus(); txtIP.SelectAll(); MessageBox.Show("IP error OR Point error"); }

    }

    //停止監(jiān)聽

    private void btnStop_Click(object sender, EventArgs e)

    {

    try

    {

    socket.Close(3);

    lblStatus.Text = "監(jiān)聽已經(jīng)停止.";

    }

    catch

    {

    lblStatus.Text = "目前未建立連接.";

    }

    }

    private void frmServer_KeyPress(object sender, KeyPressEventArgs e)

    {

    }

    private void frmServer_KeyDown(object sender, KeyEventArgs e)

    {

    if ((e.Control && e.KeyCode == Keys.Enter) || (e.Alt && e.KeyCode == Keys.S))

    {

    btnSend.PerformClick();//單擊發(fā)送

    }

    }

    //發(fā)送消息

    private void btnSend_Click(object sender, EventArgs e)

    {

    if (rtxtSend.Text.Trim() == "")

    return;

    else if (rtxtSend.Text.Trim().ToLower() == "clear()")

    {

    rtxtMsg.Clear();

    rtxtSend.Text = "";

    return;

    }

    else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[zoom(]+[\d]+[)]$"))

    {

    string str = rtxtSend.Text.ToLower();

    int size = Convert.ToInt32(str.Substring(str.LastIndexOf('(') + 1,

    str.IndexOf(')') - str.LastIndexOf('(') - 1));

    rtxtMsg.Font = new Font("宋體", size,FontStyle.Bold);

    return;

    }

    else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[down(]+[\d]+[)]$"))

    {

    string str = rtxtSend.Text.ToLower();

    string size = str.Substring(str.LastIndexOf('(') + 1,str.IndexOf(')') - str.LastIndexOf('(') - 1);

    if (Convert.ToInt32(size) > rtxtMsg.Text.Length)

    return;

    }

    else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[up(]+[\d]+[)]$"))

    {

    string str = rtxtSend.Text.ToLower();

    string size = str.Substring(str.LastIndexOf('(') + 1,str.IndexOf(')') - str.LastIndexOf('(') - 1);

    }

    else if (rtxtSend.Text.Trim().ToLower() == "exit(0)")

    {

    this.Close();

    return;

    }

    try

    {

    byte[] bs = new byte[512];

    string user = null;

    if (txtUser.Text.Trim() == "在此輸入你的名字" || txtUser.Text.Trim() == "")

    {

    user = "我";

    bs = Encoding.Unicode.GetBytes(string.Format("對方說:({0})\r\n{1}\r\n",DateTime.Now.ToString(), rtxtSend.Text.Trim()));

    }

    else

    {

    bs = Encoding.Unicode.GetBytes(string.Format("{0}說:({1})\r\n{2}\r\n", txtUser.Text.Trim(),DateTime.Now.ToString(), rtxtSend.Text.Trim()));

    user = txtUser.Text.Trim();

    }

    clientSocket.Send(bs, bs.Length, 0);//發(fā)送

    txt = string.Format("{0}說:({1})\r\n{2}\r\n", user, DateTime.Now.ToString(),rtxtSend.Text.Trim());

    int tempLen = rtxtMsg.Text.Length;

    rtxtMsg.AppendText(txt);

    rtxtMsg.Select(tempLen, txt.Length);

    rtxtMsg.SelectionFont = new Font("宋體", 10);

    rtxtMsg.SelectionColor = Color.Red;

    rtxtSend.Clear();

    }

    catch { MessageBox.Show("未建立連接,無法發(fā)送數(shù)據(jù)!"); }

    }

    //關(guān)閉Socket

    private void frmServer_FormClosing(object sender, FormClosingEventArgs e)

    {

    try

    {

    //關(guān)閉連接

    socket.Close(3);

    }

    catch (Exception) { }

    finally

    {

    foreach (Process p in Process.GetProcesses())

    {

    if (p.ProcessName == Application.ProductName)

    p.Kill();

    }

    }

    }

    private void frmServer_Load(object sender, EventArgs e)

    {

    foreach (Process p in Process.GetProcesses())

    {

    if (p.ProcessName == Application.ProductName)//已經(jīng)啟動

    {

    if (p.Id != Process.GetCurrentProcess().Id)//不是當(dāng)前進程

    {

    p.Kill();

    }

    }

    }

    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)

    {

    this.TopMost = checkBox1.Checked;

    }

    }

    }

    客戶端:

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Text;

    using System.Windows.Forms;

    using System.Net;

    using System.Net.Sockets;

    using System.Diagnostics;

    using System.Text.RegularExpressions;

    namespace smgClient

    {

    public partial class frmClient : Form

    {

    private IPAddress IP;//ip

    private EndPoint endpoint;//point

    private Socket socket;//socket

    private System.IO.Stream stream = null;

    private System.Reflection.Assembly ass = null;

    private System.Media.SoundPlayer pl = null;

    private string txt;

    private byte[] bs = new byte[512];

    public frmClient()

    {

    InitializeComponent();

    ass = System.Reflection.Assembly.GetExecutingAssembly();

    stream = ass.GetManifestResourceStream("smgClient.msg.wav");

    pl = new System.Media.SoundPlayer(stream);

    }

    //請求連接

    private void btnRequestConnect_Click(object sender, EventArgs e)

    {

    System.Threading.Thread th = new System.Threading.Thread(this.ToConnect);

    th.Start();

    }

    //連接服務(wù)器

    private void ToConnect()

    {

    try

    {

    IP = IPAddress.Parse(txtIP.Text.Trim());

    int point = Convert.ToInt32(txtPoint.Text.Trim());

    endpoint = new IPEndPoint(IP, point);

    //建立Socket

    socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    //建立連接

    socket.Connect(endpoint);

    //連接成功

    lblStatus.Text = "連接成功.";

    while (true)

    {

    socket.Receive(bs, bs.Length, 0);

    pl.Play();

    rtxtMsg.AppendText(System.Text.Encoding.Unicode.GetString(bs));

    }

    }

    catch (FormatException)

    { MessageBox.Show("IP error OR Point error"); }

    catch (ArgumentNullException)

    { MessageBox.Show("IP error OR Point error"); }

    catch (Exception)

    {

    lblStatus.Text = "連接失敗,原因: 服務(wù)器已停止.";

    }

    }

    //字體

    private void btnFont_Click(object sender, EventArgs e)

    {

    FontDialog font = new FontDialog();

    font.ShowEffects = true;

    font.ShowColor = true;

    font.MinSize = 12;

    font.Font = new Font("楷體_GB2312", 18, FontStyle.Bold);

    font.Color = Color.Blue;

    if (font.ShowDialog() == DialogResult.OK)

    {

    rtxtSend.Font = font.Font;

    rtxtSend.ForeColor = font.Color;

    }

    }

    //關(guān)閉連接

    private void btnCloseConnect_Click(object sender, EventArgs e)

    {

    try

    {

    socket.Close();

    lblStatus.Text = "連接已經(jīng)關(guān)閉.";

    }

    catch

    {

    lblStatus.Text = "目前未建立連接.";

    }

    }

    //發(fā)送消息

    private void btnSend_Click(object sender, EventArgs e)

    {

    if (rtxtSend.Text.Trim() == "")

    return;

    else if (rtxtSend.Text.Trim().ToLower() == "clear()")

    {

    rtxtMsg.Clear();

    rtxtSend.Text = "";

    return;

    }

    else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[zoom(]+[\d]+[)]$"))

    {

    string str = rtxtSend.Text.ToLower();

    int size = Convert.ToInt32(str.Substring(str.LastIndexOf('(') + 1,

    str.IndexOf(')') - str.LastIndexOf('(') - 1));

    rtxtMsg.Font = new Font("宋體", size, FontStyle.Bold);

    return;

    }

    else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[down(]+[\d]+[)]$"))

    {

    string str = rtxtSend.Text.ToLower();

    string size = str.Substring(str.LastIndexOf('(') + 1, str.IndexOf(')') - str.LastIndexOf('(') - 1);

    if (Convert.ToInt32(size) > rtxtMsg.Text.Length)

    return;

    }

    else if (Regex.IsMatch(rtxtSend.Text.Trim().ToLower(), @"^[up(]+[\d]+[)]$"))

    {

    string str = rtxtSend.Text.ToLower();

    string size = str.Substring(str.LastIndexOf('(') + 1, str.IndexOf(')') - str.LastIndexOf('(') - 1);

    }

    else if (rtxtSend.Text.Trim().ToLower() == "exit(0)")

    {

    this.Close();

    return;

    }

    try

    {

    byte[] bs = new byte[512];

    string user = null;

    if (txtUser.Text.Trim() == "在此輸入你的名字" || txtUser.Text.Trim() == "")

    {

    user = "我";

    bs = Encoding.Unicode.GetBytes(string.Format("對方說:({0})\r\n{1}\r\n", DateTime.Now.ToString(),rtxtSend.Text.Trim()));

    }

    else

    {

    bs = Encoding.Unicode.GetBytes(string.Format("{0}說:({1})\r\n{2}\r\n", txtUser.Text.Trim(),DateTime.Now.ToString(),rtxtSend.Text.Trim()));

    user = txtUser.Text.Trim();

    }

    socket.Send(bs, bs.Length, 0);//發(fā)送

    txt = string.Format("{0}說:({1})\r\n{2}\r\n", user, DateTime.Now.ToString(), rtxtSend.Text.Trim());

    int tempLen = rtxtMsg.Text.Length;

    rtxtMsg.AppendText(txt);

    rtxtMsg.Select(tempLen, txt.Length);

    rtxtMsg.SelectionFont = new Font("宋體", 10);

    rtxtMsg.SelectionColor = Color.Red;

    rtxtSend.Clear();

    }

    catch(Exception ex)

    { MessageBox.Show("連接尚未建立!無法發(fā)送數(shù)據(jù)!" + ex.Message); }

    }

    //避開打開多個

    private void frmClient_Load(object sender, EventArgs e)

    {

    foreach (Process p in Process.GetProcesses())

    {

    if (p.ProcessName == Application.ProductName)//有進程

    {

    if (p.Id != Process.GetCurrentProcess().Id)//不是當(dāng)前進程

    {

    p.Kill();

    }

    }

    }

    }

    private void frmClient_FormClosing(object sender, FormClosingEventArgs e)

    {

    try

    {

    socket.Close();

    }

    catch(Exception) { }

    finally

    {

    foreach (Process p in Process.GetProcesses())

    {

    if (p.ProcessName == Application.ProductName)

    p.Kill();

    }

    }

    }

    private void frmClient_KeyDown(object sender, KeyEventArgs e)

    {

    if ((e.Control && e.KeyCode == Keys.Enter) || (e.Alt && e.KeyCode == Keys.S))

    {

    btnSend.PerformClick();

    }

    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)

    {

    this.TopMost = checkBox1.Checked;

    }

    }

    }

    四、TCP協(xié)議的通訊過程

    你大概說的是3步握手吧,這跟傳真機的5部握手很類似。

    下面的資料希望對你有用

    TCP/IP 是很多的不同的協(xié)議組成,實際上是一個協(xié)議組,TCP 用戶數(shù)據(jù)報表協(xié)議(也

    稱作TCP 傳輸控制協(xié)議,Transport Control Protocol??煽康闹鳈C到主機層協(xié)議。這里要先

    強調(diào)一下,傳輸控制協(xié)議是OSI 網(wǎng)絡(luò)的第四層的叫法,TCP 傳輸控制協(xié)議是TCP/IP 傳輸?shù)?/p>

    6 個基本協(xié)議的一種。兩個TCP 意思非相同。)。TCP 是一種可靠的面向連接的傳送服務(wù)。

    它在傳送數(shù)據(jù)時是分段進行的,主機交換數(shù)據(jù)必須建立一個會話。它用比特流通信,即數(shù)據(jù)

    被作為無結(jié)構(gòu)的字節(jié)流。通過每個TCP 傳輸?shù)淖侄沃付樞蛱?,以獲得可靠性。是在OSI

    參考模型中的第四層,TCP 是使用IP 的網(wǎng)間互聯(lián)功能而提供可靠的數(shù)據(jù)傳輸,IP 不停的把

    報文放到網(wǎng)絡(luò)上,而TCP 是負(fù)責(zé)確信報文到達(dá)。在協(xié)同IP 的操作中TCP 負(fù)責(zé):握手過程、

    報文管理、流量控制、錯誤檢測和處理(控制),可以根據(jù)一定的編號順序?qū)Ψ钦m樞虻?/p>

    報文給予從新排列順序。關(guān)于TCP 的RFC 文檔有RFC793、RFC791、RFC1700。

    在TCP 會話初期,有所謂的“三握手”:對每次發(fā)送的數(shù)據(jù)量是怎樣跟蹤進行協(xié)商使

    數(shù)據(jù)段的發(fā)送和接收同步,根據(jù)所接收到的數(shù)據(jù)量而確定的數(shù)據(jù)確認(rèn)數(shù)及數(shù)據(jù)發(fā)送、接收完

    畢后何時撤消聯(lián)系,并建立虛連接。為了提供可靠的傳送,TCP 在發(fā)送新的數(shù)據(jù)之前,以

    特定的順序?qū)?shù)據(jù)包的序號,并需要這些包傳送給目標(biāo)機之后的確認(rèn)消息。TCP 總是用來

    發(fā)送大批量的數(shù)據(jù)。當(dāng)應(yīng)用程序在收到數(shù)據(jù)后要做出確認(rèn)時也要用到TCP。由于TCP 需要

    時刻跟蹤,這需要額外開銷,使得TCP 的格式有些顯得復(fù)雜。下面就讓我們看一個TCP 的

    經(jīng)典案例,這是后來被稱為MITNICK 攻擊中KEVIN 開創(chuàng)了兩種攻擊技術(shù):

    TCP 會話劫持

    SYN FLOOD(同步洪流)

    在這里我們討論的時TCP 會話劫持的問題。

    先讓我們明白TCP 建立連接的基本簡單的過程。為了建設(shè)一個小型的模仿環(huán)境我們假

    設(shè)有3 臺接入互聯(lián)網(wǎng)的機器。A 為攻擊者操縱的攻擊機。B 為中介跳板機器(受信任的服務(wù)

    器)。C 為受害者使用的機器(多是服務(wù)器),這里把C 機器鎖定為目標(biāo)機器。A 機器向B

    機器發(fā)送SYN 包,請求建立連接,這時已經(jīng)響應(yīng)請求的B 機器會向A 機器回應(yīng)SYN/ACK

    表明同意建立連接,當(dāng)A 機器接受到B 機器發(fā)送的SYN/ACK 回應(yīng)時,發(fā)送應(yīng)答ACK 建立

    A 機器與B 機器的網(wǎng)絡(luò)連接。這樣一個兩臺機器之間的TCP 通話信道就建立成功了。

    B 終端受信任的服務(wù)器向C 機器發(fā)起TCP 連接,A 機器對服務(wù)器發(fā)起SYN 信息,使

    C 機器不能響應(yīng)B 機器。在同時A 機器也向B 機器發(fā)送虛假的C 機器回應(yīng)的SYN 數(shù)據(jù)包,

    接收到SYN 數(shù)據(jù)包的B 機器(被C 機器信任)開始發(fā)送應(yīng)答連接建立的SYN/ACK 數(shù)據(jù)包,

    這時C 機器正在忙于響應(yīng)以前發(fā)送的SYN 數(shù)據(jù)而無暇回應(yīng)B 機器,而A 機器的攻擊者預(yù)

    測出B 機器包的序列號(現(xiàn)在的TCP 序列號預(yù)測難度有所加大)假冒C 機器向B 機器發(fā)送

    應(yīng)答ACK 這時攻擊者騙取B 機器的信任,假冒C 機器與B 機器建立起TCP 協(xié)議的對話連

    接。這個時候的C 機器還是在響應(yīng)攻擊者A 機器發(fā)送的SYN 數(shù)據(jù)。

    TCP 協(xié)議棧的弱點:TCP 連接的資源消耗,其中包括:數(shù)據(jù)包信息、條件狀態(tài)、序列

    號等。通過故意不完成建立連接所需要的三次握手過程,造成連接一方的資源耗盡。

    通過攻擊者有意的不完成建立連接所需要的三次握手的全過程,從而造成了C 機器的

    資源耗盡。序列號的可預(yù)測性,目標(biāo)主機應(yīng)答連接請求時返回的SYN/ACK 的序列號時可預(yù)

    測的。(早期TCP 協(xié)議棧,具體的可以參見1981 年出的關(guān)于TCP 雛形的RFC793 文檔)

    TCP 頭結(jié)構(gòu)

    TCP 協(xié)議頭最少20 個字節(jié),包括以下的區(qū)域(由于翻譯不禁相同,文章中給出

    相應(yīng)的英文單詞):

    TCP 源端口(Source Port):16 位的源端口其中包含初始化通信的端口。源端口和

    源IP 地址的作用是標(biāo)示報問的返回地址。

    TCP 目的端口(Destination port):16 位的目的端口域定義傳輸?shù)哪康?。這個端口指

    明報文接收計算機上的應(yīng)用程序地址接口。

    TCP 序列號(序列碼,Sequence Number):32 位的序列號由接收端計算機使用,重

    新分段的報文成最初形式。當(dāng)SYN 出現(xiàn),序列碼實際上是初始序列碼(ISN),而第一個數(shù)

    據(jù)字節(jié)是ISN+1。這個序列號(序列碼)是可以補償傳輸中的不一致。

    TCP 應(yīng)答號(Acknowledgment Number):32 位的序列號由接收端計算機使用,重

    組分段的報文成最初形式。,如果設(shè)置了ACK 控制位,這個值表示一個準(zhǔn)備接收的包的序

    列碼。

    數(shù)據(jù)偏移量(HLEN):4 位包括TCP 頭大小,指示何處數(shù)據(jù)開始。

    保留(Reserved):6 位值域,這些位必須是0。為了將來定義新的用途所保留。

    標(biāo)志(Code Bits):6 位標(biāo)志域。表示為:緊急標(biāo)志、有意義的應(yīng)答標(biāo)志、推、重置

    連接標(biāo)志、同步序列號標(biāo)志、完成發(fā)送數(shù)據(jù)標(biāo)志。按照順序排列是:URG、ACK、PSH、

    RST、SYN、FIN。

    窗口(Window):16 位,用來表示想收到的每個TCP 數(shù)據(jù)段的大小。

    校驗位(Checksum):16 位TCP 頭。源機器基于數(shù)據(jù)內(nèi)容計算一個數(shù)值,收信息機

    要與源機器數(shù)值結(jié)果完全一樣,從而證明數(shù)據(jù)的有效性。

    優(yōu)先指針(緊急,Urgent Pointer):16 位,指向后面是優(yōu)先數(shù)據(jù)的字節(jié),在URG

    標(biāo)志設(shè)置了時才有效。如果URG 標(biāo)志沒有被設(shè)置,緊急域作為填充。加快處理標(biāo)示為緊急

    的數(shù)據(jù)段。

    選項(Option):長度不定,但長度必須以字節(jié)。如果沒有選項就表示這個一字節(jié)

    的域等于0。

    填充:不定長,填充的內(nèi)容必須為0,它是為了數(shù)學(xué)目的而存在。目的是確???/p>

    間的可預(yù)測性。保證包頭的結(jié)合和數(shù)據(jù)的開始處偏移量能夠被32 整除,一般額外的零以保

    證TCP 頭是32 位的整數(shù)倍。

    標(biāo)志控制功能

    URG:緊急標(biāo)志

    緊急(The urgent pointer) 標(biāo)志有效。緊急標(biāo)志置位,

    ACK:確認(rèn)標(biāo)志

    確認(rèn)編號(Acknowledgement Number)欄有效。大多數(shù)情況下該標(biāo)志位是置位的。

    TCP 報頭內(nèi)的確認(rèn)編號欄內(nèi)包含的確認(rèn)編號(w+1,F(xiàn)igure:1)為下一個預(yù)期的序列編號,同

    時提示遠(yuǎn)端系統(tǒng)已經(jīng)成功接收所有數(shù)據(jù)。

    PSH:推標(biāo)志

    該標(biāo)志置位時,接收端不將該數(shù)據(jù)進行隊列處理,而是盡可能快將數(shù)據(jù)轉(zhuǎn)由應(yīng)用

    處理。在處理telnet 或rlogin 等交互模式的連接時,該標(biāo)志總是置位的。

    RST:復(fù)位標(biāo)志

    復(fù)位標(biāo)志有效。用于復(fù)位相應(yīng)的TCP 連接。

    SYN:同步標(biāo)志

    同步序列編號(Synchronize Sequence Numbers)欄有效。該標(biāo)志僅在三次握手建立

    TCP 連接時有效。它提示TCP 連接的服務(wù)端檢查序列編號,該序列編號為TCP 連接初始端

    (一般是客戶端)的初始序列編號。在這里,可以把TCP 序列編號看作是一個范圍從0 到4,

    294,967,295 的32 位計數(shù)器。通過TCP 連接交換的數(shù)據(jù)中每一個字節(jié)都經(jīng)過序列編號。

    在TCP 報頭中的序列編號欄包括了TCP 分段中第一個字節(jié)的序列編號。

    FIN:結(jié)束標(biāo)志

    帶有該標(biāo)志置位的數(shù)據(jù)包用來結(jié)束一個TCP 回話,但對應(yīng)端口仍處于開放狀態(tài),

    準(zhǔn)備接收后續(xù)數(shù)據(jù)。

    服務(wù)端處于監(jiān)聽狀態(tài),客戶端用于建立連接請求的數(shù)據(jù)包(IP packet)按照TCP/IP

    協(xié)議堆棧組合成為TCP 處理的分段(segment)。

    分析報頭信息: TCP 層接收到相應(yīng)的TCP 和IP 報頭,將這些信息存儲到內(nèi)存中。

    檢查TCP 校驗和(checksum):標(biāo)準(zhǔn)的校驗和位于分段之中(Figure:2)。如果檢驗

    失敗,不返回確認(rèn),該分段丟棄,并等待客戶端進行重傳。

    查找協(xié)議控制塊(PCB{}):TCP 查找與該連接相關(guān)聯(lián)的協(xié)議控制塊。如果沒有找

    到,TCP 將該分段丟棄并返回RST。(這就是TCP 處理沒有端口監(jiān)聽情況下的機制) 如果該

    協(xié)議控制塊存在,但狀態(tài)為關(guān)閉,服務(wù)端不調(diào)用connect()或listen()。該分段丟棄,但不返

    回RST。客戶端會嘗試重新建立連接請求。

    建立新的socket:當(dāng)處于監(jiān)聽狀態(tài)的socket 收到該分段時,會建立一個子socket,

    同時還有socket{},tcpcb{}和pub{}建立。這時如果有錯誤發(fā)生,會通過標(biāo)志位來拆除相應(yīng)

    的socket 和釋放內(nèi)存,TCP 連接失敗。如果緩存隊列處于填滿狀態(tài),TCP 認(rèn)為有錯誤發(fā)生,

    所有的后續(xù)連接請求會被拒絕。這里可以看出SYN Flood 攻擊是如何起作用的。

    丟棄:如果該分段中的標(biāo)志為RST 或ACK,或者沒有SYN 標(biāo)志,則該分段丟棄。

    并釋放相應(yīng)的內(nèi)存。

    發(fā)送序列變量

    SND.UNA : 發(fā)送未確認(rèn)

    SND.NXT : 發(fā)送下一個

    SND.WND : 發(fā)送窗口

    SND.UP : 發(fā)送優(yōu)先指針

    SND.WL1 : 用于最后窗口更新的段序列號

    SND.WL2 : 用于最后窗口更新的段確認(rèn)號

    ISS : 初始發(fā)送序列號

    接收序列號

    RCV.NXT : 接收下一個

    RCV.WND : 接收下一個

    RCV.UP : 接收優(yōu)先指針

    IRS : 初始接收序列號

    當(dāng)前段變量

    SEG.SEQ : 段序列號

    SEG.ACK : 段確認(rèn)標(biāo)記

    SEG.LEN : 段長

    SEG.WND : 段窗口

    SEG.UP : 段緊急指針

    SEG.PRC : 段優(yōu)先級

    CLOSED 表示沒有連接,各個狀態(tài)的意義如下:

    LISTEN : 監(jiān)聽來自遠(yuǎn)方TCP 端口的連接請求。

    SYN-SENT : 在發(fā)送連接請求后等待匹配的連接請求。

    SYN-RECEIVED : 在收到和發(fā)送一個連接請求后等待對連接請求的確認(rèn)。

    ESTABLISHED : 代表一個打開的連接,數(shù)據(jù)可以傳送給用戶。

    FIN-WAIT-1 : 等待遠(yuǎn)程TCP 的連接中斷請求,或先前的連接中斷請求的確認(rèn)。

    FIN-WAIT-2 : 從遠(yuǎn)程TCP 等待連接中斷請求。

    CLOSE-WAIT : 等待從本地用戶發(fā)來的連接中斷請求。

    CLOSING : 等待遠(yuǎn)程TCP 對連接中斷的確認(rèn)。

    LAST-ACK : 等待原來發(fā)向遠(yuǎn)程TCP 的連接中斷請求的確認(rèn)。

    TIME-WAIT : 等待足夠的時間以確保遠(yuǎn)程TCP 接收到連接中斷請求的確認(rèn)。

    CLOSED : 沒有任何連接狀態(tài)。

    TCP 連接過程是狀態(tài)的轉(zhuǎn)換,促使發(fā)生狀態(tài)轉(zhuǎn)換的是用戶調(diào)用:OPEN,SEND,

    RECEIVE,CLOSE,ABORT 和STATUS。傳送過來的數(shù)據(jù)段,特別那些包括以下標(biāo)記的數(shù)

    據(jù)段SYN,ACK,RST 和FIN。還有超時,上面所說的都會時TCP 狀態(tài)發(fā)生變化。

    序列號

    請注意,我們在TCP 連接中發(fā)送的字節(jié)都有一個序列號。因為編了號,所以可以

    確認(rèn)它們的收到。對序列號的確認(rèn)是累積性的。TCP 必須進行的序列號比較操作種類包括

    以下幾種:

    ①決定一些發(fā)送了的但未確認(rèn)的序列號。

    ②決定所有的序列號都已經(jīng)收到了。

    ③決定下一個段中應(yīng)該包括的序列號。

    對于發(fā)送的數(shù)據(jù)TCP 要接收確認(rèn),確認(rèn)時必須進行的:

    SND.UNA = 最老的確認(rèn)了的序列號。

    SND.NXT = 下一個要發(fā)送的序列號。

    SEG.ACK = 接收TCP 的確認(rèn),接收TCP 期待的下一個序列號。

    SEG.SEQ = 一個數(shù)據(jù)段的第一個序列號。

    SEG.LEN = 數(shù)據(jù)段中包括的字節(jié)數(shù)。

    SEG.SEQ+SEG.LEN-1 = 數(shù)據(jù)段的最后一個序列號。

    如果一個數(shù)據(jù)段的序列號小于等于確認(rèn)號的值,那么整個數(shù)據(jù)段就被確認(rèn)了。而

    在接收數(shù)據(jù)時下面的比較操作是必須的:

    RCV.NXT = 期待的序列號和接收窗口的最低沿。

    RCV.NXT+RCV.WND:1 = 最后一個序列號和接收窗口的最高沿。

    SEG.SEQ = 接收到的第一個序列號。

    SEG.SEQ+SEG.LEN:1 = 接收到的最后一個序列號。

    以上就是關(guān)于tcp服務(wù)器端流程相關(guān)問題的回答。希望能幫到你,如有更多相關(guān)問題,您也可以聯(lián)系我們的客服進行咨詢,客服也會為您講解更多精彩的知識和內(nèi)容。


    推薦閱讀:

    gptchat的原理(gpt2原理)

    itchat還能用嗎2021(itchat還能用嗎2020)

    kaptcha(Kaptcha怎么讀的)

    寫文案接單平臺

    尾獸排行榜