久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C# Socket的TCP通訊

 ThinkTank_引擎 2014-11-20

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的一些心得,,還在不斷學(xué)習(xí)中,,如果上面的講解有什么不到位的或者錯(cuò)誤的,可以交流一下,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多