欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# Socket的TCP通訊的實(shí)例代碼

 更新時(shí)間:2016年12月20日 11:23:56   作者:James-ping  
本篇文章主要介紹了C# Socket的TCP通訊,socket通訊方式有兩種:同步和異步,詳細(xì)的介紹了這兩種方法,有興趣的可以了解一下。

Socket的TCP通訊

一、 socket的通訊原理

服務(wù)器端的步驟如下。

(1)建立服務(wù)器端的Socket,開始偵聽整個(gè)網(wǎng)絡(luò)中的連接請(qǐng)求。

(2)當(dāng)檢測(cè)到來自客戶端的連接請(qǐng)求時(shí),向客戶端發(fā)送收到連接請(qǐng)求的信息,并建立與客戶端之間的連接。

(3)當(dāng)完成通信后,服務(wù)器關(guān)閉與客戶端的Socket連接。

客戶端的步驟如下。

(1)建立客戶端的Socket,確定要連接的服務(wù)器的主機(jī)名和端口。

(2)發(fā)送連接請(qǐng)求到服務(wù)器,并等待服務(wù)器的回饋信息。

(3)連接成功后,與服務(wù)器進(jìn)行數(shù)據(jù)的交互。

(4)數(shù)據(jù)處理完畢后,關(guān)閉自身的Socket連接。

二、 socket的通訊方式

socket通訊方式有兩種:同步和異步

同步工作方式:

用TCP協(xié)議進(jìn)行編程時(shí)程序執(zhí)行到發(fā)送、接收和監(jiān)聽語句的時(shí)候,在未完成工作前不再繼續(xù)往下執(zhí)行,即處于阻塞狀態(tài),直到該語句完成某個(gè)工作后才繼續(xù)執(zhí)行下一條語句。

異步工作方式

程序執(zhí)行到發(fā)送、接收和監(jiān)聽語句的時(shí)候,不論工作是否完成,都會(huì)繼續(xù)往下執(zhí)行。

三、 socket的C#實(shí)現(xiàn)

1.1.      同步:

服務(wù)端客戶端通信

在與服務(wù)端的連接建立以后,我們就可以通過此連接來發(fā)送和接收數(shù)據(jù)。端口與端口之間以流(Stream)的形式傳輸數(shù)據(jù),因?yàn)閹缀跞魏螌?duì)象都可以保存到流中,所以實(shí)際上可以在客戶端與服務(wù)端之間傳輸任何類型的數(shù)據(jù)。對(duì)客戶端來說,往流中寫入數(shù)據(jù),即為向服務(wù)器傳送數(shù)據(jù);從流中讀取數(shù)據(jù),即為從服務(wù)端接收數(shù)據(jù)。對(duì)服務(wù)端來說,往流中寫入數(shù)據(jù),即為向客戶端發(fā)送數(shù)據(jù);從流中讀取數(shù)據(jù),即為從客戶端接收數(shù)據(jù)。

服務(wù)端:

(1)服務(wù)端對(duì)端口進(jìn)行偵聽:

服務(wù)器端建立一個(gè)socket,設(shè)置好本機(jī)的ip和監(jiān)聽的端口與socket進(jìn)行綁定,開始監(jiān)聽連接請(qǐng)求,當(dāng)接收到連接請(qǐng)求后,發(fā)送確認(rèn),同客戶端建立連接,開始與客戶端進(jìn)行通信。

TcpListener listener =new TcpListener(new IPEndPoint(IPAddress.Parse(ip), port));//ip為服務(wù)器IP地址,port為監(jiān)聽的端口

Listener.Start();//開啟監(jiān)聽

(2)檢測(cè)來自客戶端的連接請(qǐng)求

TcpClient remoteClient = listener.AcceptTcpClient();
//接收客戶端 這里體現(xiàn)了同步的含義,如果客戶端對(duì)該服務(wù)端發(fā)起連接的時(shí)候,程序在這里就會(huì)等待(阻塞),直到有客戶端的連接請(qǐng)求為止

(3)建立和連接的客戶端的數(shù)據(jù)流(傳輸數(shù)據(jù))

NetworkStream streamToClient = remoteClient.GetStream();

該數(shù)據(jù)流只要是用來接收和發(fā)送數(shù)據(jù),同步也分多客戶端和單個(gè)客戶端,如果分的詳細(xì)一點(diǎn)的話,還有客戶端的一條以及多條數(shù)據(jù)的情況,如果是單個(gè)客戶端的多條數(shù)據(jù)的話,連接客戶端之后,在建立數(shù)據(jù)流的前面添加一個(gè)循環(huán)就可以了,如果是多個(gè)客戶端的話,在(2)前面加個(gè)循環(huán)就可以了。為了接收數(shù)據(jù)的效率,建議不管是同步還是異步,服務(wù)端都做成線程,詳細(xì)見Demo

(4)接收客戶端發(fā)送過來的數(shù)據(jù)(用緩存來接收)

byte[] buffer = new byte[BufferSize]; // BufferSize為緩存的大小

 int bytesRead; 

 try

 {

  lock (streamToClient)//為了保證數(shù)據(jù)的完整性以及安全性 鎖定數(shù)據(jù)流

   {

     bytesRead = streamToClient.Read(buffer, 0, BufferSize);

} 

(5)向連接的客戶端發(fā)送數(shù)據(jù)

lock (streamToClient)

           {

           streamToClient.Write(buffer, 0, buffer.Length);//buffer為發(fā)送的字符數(shù)組         

} 

 (6)釋放數(shù)據(jù)流和TcpClient(以便下次的數(shù)據(jù)以及客戶端的收發(fā))

streamToClient.Dispose();//釋放數(shù)據(jù)流中的數(shù)據(jù)

 remoteClient.Close();//釋放TcpClient實(shí)例 

客戶端

(1)   連接服務(wù)器

TcpClient tcp = new TcpClient();

tcp.Connect(IP,Port);//根據(jù)服務(wù)器的IP地址和偵聽的端口連接

if (tcp.Connected)

{

//連接成功的消息機(jī)制 詳細(xì)見DEMO

ShowGetData("成功連接上了服務(wù)器:", this.strIP.Text.ToString());
 

 } 

這里需要注意的是,不管是使用有參數(shù)的構(gòu)造函數(shù)與服務(wù)器連接,或者是通過Connect()方法與服務(wù)器建立連接,都是同步方法(或者說是阻塞的,英文叫block)。它的意思是說,客戶端在與服務(wù)端連接成功、從而方法返回,或者是服務(wù)端不存、從而拋出異常之前,是無法繼續(xù)進(jìn)行后繼操作的。這里還有一個(gè)名為BeginConnect()的方法,用于實(shí)施異步的連接,這樣程序不會(huì)被阻塞,可以立即執(zhí)行后面的操作,這是因?yàn)榭赡苡捎诰W(wǎng)絡(luò)擁塞等問題,連接需要較長(zhǎng)時(shí)間才能完成。網(wǎng)絡(luò)編程中有非常多的異步操作,凡事都是由簡(jiǎn)入難,關(guān)于異步操作,我們后面再討論,現(xiàn)在只看同步操作。

(2)   建立連接服務(wù)端的數(shù)據(jù)流

NetworkStream streamToServer = tcp.GetStream(); 

(3)   接收和發(fā)送數(shù)據(jù)

//發(fā)送字符串

byte[] buffer = Encoding.Unicode.GetBytes(msg); //msg為發(fā)送的字符串  

 try

     {

       lock (streamToServer)
      {

      streamToServer.Write(buffer, 0, buffer.Length);   // 發(fā)往服務(wù)器

       }

     //接收字符串
       buffer = new byte[BufferSize];
       lock (streamToServer)

      {

        bytesRead = streamToServer.Read(buffer, 0, BufferSize);

      }

} 

1.2.      異步

相對(duì)于同步,異步中的連接,接收和發(fā)送數(shù)據(jù)的方法都不一樣,都有一個(gè)回調(diào)函數(shù),就是即使不能連接或者接收不到數(shù)據(jù),程序還是會(huì)一直執(zhí)行下去,如果連接上了或者接到數(shù)據(jù),程序會(huì)回到這個(gè)回調(diào)函數(shù)的地方重新往下執(zhí)行。詳細(xì)見下面:

服務(wù)器:

1、 開啟偵聽接口

private TcpListener listener;        //監(jiān)聽類

listener = new TcpListener(new IPEndPoint(IPAddress.Parse(ip), port));

listener.Start();//開啟偵聽,對(duì)連接的客戶端的數(shù)目沒有限制

或者

listener.Start(int i);// 開啟偵聽,最多只能連接i個(gè)客戶端數(shù)目 

2、 接收客戶端

listener.BeginAcceptSocket(clientConnect, listener);//異步接受客戶端的連接請(qǐng)求  clientConnect為連接的回調(diào)函數(shù)

     /// <summary>

    /// 接收回調(diào)函數(shù)

    /// </summary>

    /// <param name="ar"></param>

    private void clientConnect(IAsyncResult ar)

    {

    try

      {
        TcpListener listener = (TcpListener)ar.AsyncState;
        //接受客戶的連接,得到連接的Socket
        Socket client = listener.EndAcceptSocket(ar);

      }

      catch { }

    } 

3、 接收客戶端發(fā)送的數(shù)據(jù)

/// <summary> 

/// 異步接收數(shù)據(jù)

 /// </summary>

 private void receiveData(Socket client)

{

   // 調(diào)用異步方法 BeginReceive 來告知 socket 如何接收數(shù)據(jù)
  IAsyncResult iar = client.BeginReceive(buffer, 0, BagSize, SocketFlags.None, out errorCode, receiveCallback, buffer);

      }

   }

    /// <summary>

    /// 接收數(shù)據(jù)回調(diào)函數(shù)

    /// </summary> 

    /// <param name="ar"></param>

    private void receiveCallback(IAsyncResult ar)

    {     
        //接收到的數(shù)據(jù)長(zhǎng)度.
        int receLen = 0;

        try

        {
          receLen = client.EndReceive(ar, out errorCode);        

if (receLen > 0)

         {
           OnReceiveData(client);//接收到數(shù)據(jù)之后的處理函數(shù)

          }
        }
       catch {   }

      }
      else { }

    } 

4、接收成功之后,回發(fā)數(shù)據(jù)給客戶端

/// <summary>

/// 異步發(fā)送報(bào)文
/// </summary>

 /// <param name="data"></param>
 private void OnReceiveData (Socket socket)

{
     string strLogin = “succeed recived”;

byte[] data = Encoding.ASCII.GetBytes(strLogin);

 socket.BeginSend(data, 0, data.Length, SocketFlags.None, out errorCode, sendCallBack, socket);//異步發(fā)送數(shù)據(jù)

     }

      else

      { }

    }

/// <summary>

 /// 異步發(fā)送回調(diào)事件

 /// </summary>

 /// <param name="ar"></param>

private void sendCallBack(IAsyncResult ar)

    {

socket.EndSend(ar, out errorCode);

     } 

客戶端

1、連接服務(wù)器

private TcpClient tcpcz = null

 tcpcz = new TcpClient()

 tcpcz.BeginConnect(ipaddress, Convert.ToInt32(port), new AsyncCallback(ConnectCallback), tcpcz);//根據(jù)服務(wù)器的IP地址和端口號(hào) 異步連接服務(wù)器

 /// <summary>

/// 異步連接的回調(diào)函數(shù)

 /// </summary>

 /// <param name="ar"></param>

 private void ConnectCallback(IAsyncResult ar)

    {

      TcpClient t = (TcpClient)ar.AsyncState;

      try

      {

        if (t.Connected)

        {

          t.EndConnect(ar);//函數(shù)運(yùn)行到這里就說明連接成功

        }

        else

        {

        }

      }

      catch () {  }

    } 

2、發(fā)送和接收字符串

NetworkStream stream = tcp.GetStream();//創(chuàng)建于服務(wù)器連接的數(shù)據(jù)流

        //發(fā)送字符串

  string strLogin = “this is socket example”;

  byte[] data = Encoding.ASCII.GetBytes(strLogin);

 stream.BeginWrite(data, 0, data.Length, new AsyncCallback(SendCallback),stream);//異步發(fā)送數(shù)據(jù)

 //接收字符串

  byte[] result = new byte[tcp.Available]; // tcp.Available為接受的字符串大小

  try

 {

   stream.BeginRead(result, 0, result.Length, new AsyncCallback(ReadCallback), stream);//異步接受服務(wù)器回報(bào)的字符串

  }

    catch { }

    string strResponse = Encoding.ASCII.GetString(result).Trim();//從服務(wù)器接受到的字符串

 }

  }

     catch ()

     {

     }

   } 

以上是這一段時(shí)間對(duì)socket的一些心得,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#開發(fā)微信門戶及應(yīng)用(4) 關(guān)注用戶列表及詳細(xì)信息管理

    C#開發(fā)微信門戶及應(yīng)用(4) 關(guān)注用戶列表及詳細(xì)信息管理

    這篇文章主要為大家詳細(xì)介紹了C#開發(fā)微信門戶及應(yīng)用第四篇,關(guān)注用戶列表及詳細(xì)信息管理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • C#部署數(shù)據(jù)庫及IIS站點(diǎn)

    C#部署數(shù)據(jù)庫及IIS站點(diǎn)

    這篇文章主要為大家詳細(xì)介紹了C#部署數(shù)據(jù)庫及IIS站點(diǎn)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Unity3D實(shí)現(xiàn)警報(bào)燈

    Unity3D實(shí)現(xiàn)警報(bào)燈

    這篇文章主要為大家詳細(xì)介紹了Unity3D實(shí)現(xiàn)警報(bào)燈效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-01-01
  • C#調(diào)用HTTP POST請(qǐng)求上傳圖片的示例代碼

    C#調(diào)用HTTP POST請(qǐng)求上傳圖片的示例代碼

    現(xiàn)在很多B/S系統(tǒng)的開發(fā)都是通過API方式來進(jìn)行的,一般服務(wù)端會(huì)開放一個(gè)API接口,客戶端調(diào)用API接口來實(shí)現(xiàn)圖片或文件上傳的功能,感興趣的可以了解一下
    2021-05-05
  • 適用于WebForm Mvc的Pager分頁組件C#實(shí)現(xiàn)

    適用于WebForm Mvc的Pager分頁組件C#實(shí)現(xiàn)

    這篇文章主要為大家分享了適用于WebForm Mvc的Pager分頁組件,由C#實(shí)現(xiàn),感興趣的小伙伴們可以參考一下
    2016-04-04
  • C#關(guān)鍵字async/await用法

    C#關(guān)鍵字async/await用法

    在本篇文章里小編給大家整理的是關(guān)于C#關(guān)鍵字async/await用法及相關(guān)實(shí)例,需要的朋友們學(xué)習(xí)下。
    2019-12-12
  • C# Unicode編碼解碼的實(shí)現(xiàn)

    C# Unicode編碼解碼的實(shí)現(xiàn)

    本文主要介紹了C# Unicode編碼解碼的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • C#中委托和事件的區(qū)別詳解

    C#中委托和事件的區(qū)別詳解

    C# 中的委托(Delegate)類似于 C 或 C++ 中函數(shù)的指針。事件是在委托類型變量前加上 event 關(guān)鍵字,其本質(zhì)是用來對(duì)委托類型的變量進(jìn)行封裝,類似于類的屬性對(duì)字段的封裝。本文就來聊聊C#中委托和事件的區(qū)別,感興趣的可以了解一下
    2022-11-11
  • C#實(shí)現(xiàn)讀取和設(shè)置文件與文件夾的權(quán)限

    C#實(shí)現(xiàn)讀取和設(shè)置文件與文件夾的權(quán)限

    這篇文章主要為大家詳細(xì)介紹了如何使用C#實(shí)現(xiàn)讀取和設(shè)置文件與文件夾的權(quán)限,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • C#中自定義高精度Timer定時(shí)器的實(shí)例教程

    C#中自定義高精度Timer定時(shí)器的實(shí)例教程

    這篇文章主要介紹了C#中自定義高精度Timer定時(shí)器的實(shí)例教程,多線程的Timer編寫需要注意線程安全的問題,需要的朋友可以參考下
    2016-04-04

最新評(píng)論