[C# 網路編程系列]專題五:TCP編程

來源:互聯網
上載者:User

前言

 

前面專題的例子都是基於應用程式層上的HTTP協議的介紹, 現在本專題來介紹下傳輸層協議——TCP協議,主要介紹下TCP協議的工作過程和基於TCP協議的一個簡單的通訊程式,下面就開始本專題的本文了。

 

一、TCP的工作過程

首先TCP是一種連線導向的,可靠的,基於位元組流的傳輸層通訊協定。TCP的工作過程可以分為三個階段:一、串連的建立;  二、傳輸資料; 三、中斷連線,下面就對這三個過程分別介紹下:

1.1 串連的建立

TCP的串連建立就像打電話一樣, 我們打電話時,撥一個號碼的號碼並不是立即就可以接通的,期間會有一個“嘟 嘟”的呼叫過程, 這就好比是TCP協議的串連的建立階段。當我們用TCP編寫的程式,必須先建立TCP串連。TCP協議的串連建立通過三向交握來完成的,下面是在網上找的一張TCP三向交握的圖片:

 

下面就對這三向交握簡單的介紹:

第一次握手:建立串連時,用戶端發送SYN包(seq=x)到伺服器,並進入SYN_Send狀態,等待伺服器確認

第二次握手:伺服器收到SYN包,必須確認客戶的SYN(ACK=x+1),同時自己也發送一個SYN包(SEQ=y),即SYN+ACK包,此時伺服器進入SYN_Recv狀態

第三向交握:用戶端收到伺服器的SYN+ACK包,向伺服器發送確認包ACK(ACK=y+1),此包發送完畢,用戶端和伺服器進入Established(建立)狀態,完成三向交握。

簡單理解三向交握就是發送一個檢驗包給對方然後互相確認,雙方都接到確認的一個訊號時,這時候雙方就建立了串連(就像我們打電話時,如果沒人說話時就會說下 “喂”,說這句“喂” 也就是希望得到對方的一個確認,雖然這裡雙方已經建立了串連的,這裡只是更形象的說明下三向交握的過程)。

1.2 傳輸資料

雙方建立了串連,即在雙方建立了一個通訊通道(就像一座橋一樣,在兩端建立了一個通路,用橋來比喻通訊通道主要是因為最近有一則新聞:哈爾濱陽明灘大橋坍塌事件),建立串連之後,當然是傳輸我們需要傳輸的資料到對方的,這裡就開始簡單介紹下傳輸資料的過程。

利用TCP傳輸資料時,資料是以位元組流的形式進行傳輸,用戶端與伺服器端建立串連後,發送方需要先將發送的資料轉換為位元組流,然後將其發送給對方,發送資料時,可以通過程式不斷地將資料流陸續寫入TCP的發送緩衝中,然後TCP自動從發送緩衝中提取一定量的資料,將其組成TCP報文段發送到IP層,再通過IP層(也就是網路層)之下的網路介面發送出去;接受端從IP層接收到TCP報文段後,將其暫時儲存在接受緩衝中,然後我們通過程式依次讀取接受緩衝中的資料,從而達到相互連信的目的(簡單的說就發送方把資料轉換為資料流,再把資料流儲存在發送緩衝中,然後傳輸層低層的協議從發送緩衝中讀取資料把資料發送出去,然後接收端從底層接受到資料把資料存放區在接收端的緩衝中,然後我們寫的程式只是從緩衝中依次讀取資料,然後顯示出來,在用戶端我們寫代碼做的事情是把資料寫入Write寫入發送端的緩衝中,然後伺服器端(接收端)用Read方法在自己的緩衝中讀取資料,用一句話概括,TCP的傳輸就是對資料的寫——讀操作)括弧中的內容只是我個人理解,因為這樣我感覺理解起來比較容易,對於剛開始接觸TCP的朋友可以這樣理解,然後再一句句話去擴充。

1.3 中斷連線

發送完資料之後,最後就是中斷連線了,下面是網上斷開的串連的一張圖片(斷開一個串連需要經過四次握手):

 

TCP的工作過程就分為上面三個過程,TCP編程是作為上層應用編程的基礎,就像之前專題中基於HTTP協議的Web伺服器,Web瀏覽器,其傳輸層都用的是TCP協議進行傳輸的,還有基於FTP(檔案傳輸通訊協定),IMAP(互動式郵件存取協議) POP3(郵局協議的第3個版本) 和SMTP(簡易郵件傳輸通訊協定)的網路應用其傳輸層都用的是TCP協議,而不是UDP等其他傳輸層協議。

 

 

二、基於TCP協議的簡單通訊程式

這裡簡單實現了一個用戶端與伺服器間的通訊程式,核心代碼為:

用戶端串連伺服器端代碼:

 private void btnConnect_Click(object sender, EventArgs e)        {            // 通過一個線程發起請求,多線程            Thread connectThread = new Thread(ConnectToServer);            connectThread.Start();        }        // 串連伺服器方法,建立串連的過程        private void ConnectToServer()        {            try            {                // 調用委託                statusStripInfo.Invoke(showStatusCallBack, "正在串連...");                if (tbxserverIp.Text == string.Empty || tbxPort.Text == string.Empty)                {                    MessageBox.Show("請先輸入伺服器的IP地址和連接埠號碼");                }                IPAddress ipaddress = IPAddress.Parse(tbxserverIp.Text);                tcpClient = new TcpClient();                             tcpClient.Connect(ipaddress, int.Parse(tbxPort.Text));                                               // 延時操作                Thread.Sleep(1000);                if (tcpClient != null)                {                    statusStripInfo.Invoke(showStatusCallBack, "串連成功");                    networkStream = tcpClient.GetStream();                    reader = new BinaryReader(networkStream);                    writer =new BinaryWriter(networkStream);                }                             }            catch            {                statusStripInfo.Invoke(showStatusCallBack,"串連失敗");                Thread.Sleep(1000);                statusStripInfo.Invoke(showStatusCallBack,"就緒");            }        }

用戶端發送訊息的代碼:

// 發送訊息        private void btnSend_Click(object sender, EventArgs e)        {            Thread sendThread = new Thread(SendMessage);            sendThread.Start(tbxMessage.Text);        }        private void SendMessage(object state)        {            statusStripInfo.Invoke(showStatusCallBack, "正在發送...");            try            {                writer.Write(state.ToString());                Thread.Sleep(5000);                writer.Flush();                statusStripInfo.Invoke(showStatusCallBack, "完畢");                tbxMessage.Invoke(resetMessageCallBack, null);                lstbxMessageView.Invoke(showMessageCallback, state.ToString());            }            catch            {                if (reader != null)                {                    reader.Close();                }                if (writer != null)                {                    writer.Close();                }                if (tcpClient != null)                {                    tcpClient.Close();                }                statusStripInfo.Invoke(showStatusCallBack, "斷開了串連");            }        }

伺服器端接受開始監聽用戶端請求的代碼:

 // 開始監聽        private void btnStart_Click(object sender, EventArgs e)        {                       tcpLister = new TcpListener(ipaddress,Port);            tcpLister.Start();            // 啟動一個線程來接受請求            Thread acceptThread =new Thread(acceptClientConnect);            acceptThread.Start();        }        // 接受請求        private void acceptClientConnect()        {            statusStripInfo.Invoke(showStatusCallBack,"正在監聽");            Thread.Sleep(1000);            try            {                statusStripInfo.Invoke(showStatusCallBack,"等待串連");                tcpClient = tcpLister.AcceptTcpClient();                if (tcpLister != null)                {                    statusStripInfo.Invoke(showStatusCallBack,"接受到串連");                    networkStream = tcpClient.GetStream();                    reader = new BinaryReader(networkStream);                    writer = new BinaryWriter(networkStream);                }            }            catch            {                statusStripInfo.Invoke(showStatusCallBack, "停止監聽");                Thread.Sleep(1000);                statusStripInfo.Invoke(showStatusCallBack, "就緒");            }        }

現在看看啟動並執行結果:
首先先啟動伺服器然後點開始監聽,此時線程會堵塞,直到接受到一個串連請求位置

然後運行用戶端,在IP地址和連接埠處輸入伺服器端的IP地址和連接埠號碼,點擊串連伺服器按鈕後的介面如下:

通過接受按鈕和發送按鈕來實現雙方的通訊,實現介面如下:

 

三、總結

到這裡本專題的內容將的差不多了, 本專題主要介紹了基於TCP協議工作過程和在net平台下自訂了一個簡單通訊的程式,希望本專題可以給那些初次接觸TCP協議的朋友一些協助,(大牛們應該直接可以閃過的),在後面的專題我將和大家分享UDP編程,講完UDP編程後將結合這兩章的內容實現一個類似QQ的即時聊天的工具,希望這些對大家有協助,如果大家有任何問題和有感興趣的專題需要瞭解的,可以給我留言,在之後的文章都會和大家來分享。

 

 

覺得看了後有協助的朋友麻煩推薦下,也給我繼續下去的動力,如果大家有什麼感興趣的專題也可以留言告訴我,我會通過學習後也會相繼和大家分享。

下面是本程式原始碼:

 http://files.cnblogs.com/zhili/%E7%AE%80%E5%8D%95%E9%80%9A%E4%BF%A1%E7%A8%8B%E5%BA%8F.zip

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.