網絡編程之即時通信程序(聊天室)------(一)通信流程簡介及通信協議定制


      在開始講之前,我想先跟大家描述一下,這個所謂的通信程序具體是一個什么樣的東西。該通信程序類似一個弱版本的qq,登錄時需要進行注冊,登錄成功后,可以實現即時的通信,群聊,私聊,同時還可傳文件。先上個圖

服務端:                                                             客戶端登錄:                                       客戶端主界面:

        所謂的即時的通信程序,也就是利用TCP和UDP的傳輸協議,進行信息、文件的傳輸。那什么是TCP,什么是UDP呢?

     TCPTransmission Control Protocol(傳輸控制協議)的簡稱,是TCP/IP體系中面向連接的運輸層協議,在網絡中提供全雙工的和可靠的服務。TCP協議的主要特點是:基於連接的協議,數據傳輸比較穩定,且可以保證數據按順序的准時達。                                                                                                      

    UDP 是User Datagram Protocol(用戶數據報協議)的簡稱,是 OSI 參考模型中一種無連接的傳輸層協議,提供面向事務的簡單不可靠信息傳送服務。UDP協議的主要特點是:基於無連接協議,數據傳送迅速,反應快,同時缺點也很明顯,就是數據傳輸不穩定,不能保證數據到達的順序,可能會有數據的缺失。                                   

    我們所熟悉的QQ就是一種基於TCP和UDP兩種協議結合的一種即時通信程序,在我們進行會話、聊天的時候,采用UDP協議,通過服務器中轉方式。大家都知道,UDP 協議是不可靠協議,它只管發送,不管對方是否收到的,但它的傳輸很高效。但是,作為聊天軟件,怎么可以采用這樣的不可靠方式來傳輸消息呢?於是,騰訊采用了上層協議來保證可靠傳輸:如果客戶端使用UDP協議發出消息后,服務器收到該包,需要使用UDP協議發回一個應答包。如此來保證消息可以無遺漏傳輸。之所以會發生在客戶端明明看到“消息發送失敗”但對方又收到了這個消息的情況,就是因為客戶端發出的消息服務器已經收到並轉發成功,但客戶端由於網絡原因沒有收到服務器的應答包引起的。在我們進行文件傳輸的時候使用的是基於TCP的數據傳輸協議,因為要保證傳輸數據的順序到達,同時還要保證不能有數據的丟失。

     在我們的.NET平台下如果想要實現即時的通信就需要借助於Socket網絡編程,Socket(網絡套接字)是網絡通信的基本構件,它是可以被命名和尋址的通信端口,使用中,每個Socket 都有對應的類型和一個與之相關的進程。在開始介紹Socket創建即時通信之前我們需要先了解下使用TCP進行即時通信的操作流程:

 

下邊我會結合這個流程圖,一步一步跟大家講通信的具體流程。

1、創建服務端套接字,監聽本機的IP和一個特定的端口,把本機作為服務端。(下面的只是一個簡單的演示實例)

int  port = 11615;//監聽端口,最好設置的大一些,避免和一些特定的端口沖突
IPAddress ipAdd=IPAddress.Parse(“192.168.245.1”);//監聽IP,我們通過Dns.GetByHostName().Arrylist[],動態獲得本機的IP,這里僅是示例。
TcpListener listener=new TcpListener(ipAdd, port);//創建監聽對象

2、監聽服務器端口,等待客戶端連接請求      

listener.Start();

3、創建客戶端的套接字,並向遠程服務端發送連接請求     

TcpClient tcpClient=new TcpClient();
int  port = 11615;
IPAddress ipAdd=IPAddress.Parse(“192.168.245.1”);
        tcpClient.Connect(ipAdd, port);

 

 

4、服務端確認與客戶端的連接,並創建與該客戶端對應的Socket對象

Socket clientSocket= listener.AcceptSocket();

5、客戶端獲取與服務器通信的流通道

NetworkStream stream = tcpClient.GetStream();

6、客戶端通過流通道與服務器端進行數據傳輸

6.1、客戶端向服務器端發送數 

string  hello=“Hello World!”;
byte [] buffer=Encoding.Default.GetBytes(hello);
stream.Write(buffer,0,buffer.Length); 

  6.2、客戶端接收從服務器端發來的數據

byte [] buffer=new byte[1024];
int length= stream.Read(buff,0,buff.Length);
string msg = Encoding.Default.GetString(buffer,0,length);

7、服務端接受客戶端請求

7.1、服務端向客戶端發送數據

string  hello=“Hello World!”;
byte [] buffer=Encoding.Default.GetBytes(hello);
stream.Write(buffer,0,buffer.Length);

7.2、服務端接收從客戶器端發來的數據

byte [] buffer=new byte[1024];
int length= stream.Read(buff,0,buff.Length);
string msg = Encoding.Default.GetString(buffer,0,length);

8、服務端斷開與客戶端的連接

clientSocket.Close();

9、客戶端斷開與服務端的連接

tcpClient.Close();

10、服務端關閉服務套接字

tcpClient.Close();

       大體的通信流程就是這樣子,但是到具體的實際應用中還有不同 ,因為我們要涉及到多個客戶端之間的交互,而服務端只是相當於一個中間的媒介,接收客戶端傳遞的消息,並將消息轉發給另一個客戶端,如果有多個客戶端,同時進行通信,而這個時候就需要用到多線程進行通信的管理和控制。

具體的流程如下:

      首先,我們在需要服務端創建一個TCPLister對象,啟用一個線程,專門負責監聽客戶端的請求。

      其次,只要有一個客戶端進行請求 ,則TCPLister對象會馬上創建一個專門負責通信的Socket與客戶端請求的套接字,

      同時再啟用一個新的線程專門負責與客戶端進行通信。

      在客戶端,我們只需要創建一個TCPClient對象,啟用一個新的線程來專門的負責信息的接受即可。

      在具體的通過過程中,我們還需要定制一些列的消息通信協議,在消息內部用“|”管道符將其內容進行分割,通過對協議的解析我們可以對不同的消息做不同的處理。在本應用才程序中,具體的通信協議如下:

      在服務端接收協議如下:

命令格式

接收到客戶端發送的通信流的字節數組中的首字節Msg[0]

說明

1、如果Msg[0]則說明發送的是文件,則遍歷在線用戶列表,像用戶在線用戶逐一發送該字節數組

2、如果Msg[0]!=0,則說明發送過來的信息字符串,則直接進行Encoding將字節數組轉換為字符串,並對字符串進行如下的分析,根據不同的分析結果執行不同的命令。

ON|發送者的用戶名|

1、該命令在客戶端與服務器端建立連接后由客戶端自動發送

2、服務器端收到該命令后,將“用戶名”添加到在線用戶列表並向所有在線用戶發送消息“***上線啦!"

Off|發送者的用戶名|

1、該命令是在用戶上線、或者離開時執行的,用於向客戶端發送在線人員名單,客戶端接受到該信息后就會對在線列表進行更新。

MSG|接收者姓名|發送者姓名|發送內容|

MSGALL|發送者的用戶名|發送內容|

1、該命令是用戶點擊發送消息按鈕時,發送的信息,前提是用戶必須選定要發送的對象

2、服務端收到該消息后,對消息進行解析,從中取得接受者用戶名,並從在線列表中取得相應的通訊Socket,將“發送者用戶名說“發送內容“這樣格式的消息發送回客戶端

3、如果是MSGALL,則為群發消息,服務器端收到該命令后,將遍歷在線用戶列表的用戶,並逐一向在線用戶發送”發送者的用戶名說‘發送內容’”這樣的信息發送給所有的在線用戶

       

          在客戶端接收協議如下:

                             

命令格式

說明

接受服務端發送的通信流字節數組中的首字節Msg[0]

如果Msg[0]==0則說明服務端發送的是文件,直接新建文件流從接收到的字節數組中的第二個字節開始讀取,讀取長度為字節數組長度減一個字節,並在本地保存文件。

如果Msg[0]!=0則說明服務端發送的是消息字符串,然后再根據下面的命令格式進行解析,進而做出不同的操作

OnLine|剛登錄的用戶名|

客戶端收到該命令后,在聊天串口中看到“****”上線了的通知!

Off|用戶1、用戶2、用戶3、|

該命令是在服務器端收到客戶端發來的Off和On命令,回發給客戶端的命令,然后客戶端解析命令,更新在線人員列表。

  

        以上這些就是該即時通信程序的通信格式,在下一節中,我會帶領大家一步一步的構建該即時通信程序的服務端,在構建的過程中會逐步向大家演示TCPLister的應用,以及相關的涉及的多線程的知識。

       好了,這一節就到這里了,希望能給大家帶來些許幫助,同時也希望大家多多指點。                                                                                                                 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM