天堂国产午夜亚洲专区-少妇人妻综合久久蜜臀-国产成人户外露出视频在线-国产91传媒一区二区三区

當(dāng)前位置:主頁 > 論文百科 > 核心期刊 >

你得學(xué)會并且學(xué)得會的Socket編程基礎(chǔ)知識

發(fā)布時間:2016-08-07 16:16

  本文關(guān)鍵詞:socket編程,由筆耕文化傳播整理發(fā)布。


你得學(xué)會并且學(xué)得會的socket編程基礎(chǔ)知識

這一篇文章,我將圖文并茂地介紹Socket編程的基礎(chǔ)知識,我相信,如果你按照步驟做完實(shí)驗(yàn),一定可以對socket編程有更好地理解。

本文源代碼,可以通過這里下載

 

第一步:創(chuàng)建解決方案

image

第二步:創(chuàng)建服務(wù)端程序

這里可以選擇“Console Application”這個類型,比較方便調(diào)試

image

然后編寫如下代碼,實(shí)現(xiàn)服務(wù)器的基本功能

using System; using System.Collections.Generic; using System.Linq; using System.Text; //額外導(dǎo)入的兩個命名空間 using System.Net.Sockets; using System.Net; namespace SocketServer { class Program { Main(string[] args) { //創(chuàng)建一個新的Socket,這里我們使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //將該socket綁定到主機(jī)上面的某個端口 //方法參考: socket.Bind(new IPEndPoint(IPAddress.Any, 4530)); //啟動監(jiān)聽,并且設(shè)置一個最大的隊(duì)列長度 //方法參考:(v=VS.100).aspx socket.Listen(4); Console.WriteLine("Server is ready!"); Console.Read(); } } }

 

現(xiàn)在可以啟動調(diào)試一下看看效果如何,正常情況下應(yīng)該會看到一個提示,因?yàn)槲覀冃枰赥CP 4530端口進(jìn)行監(jiān)聽,所以防火墻會有提示。

image

點(diǎn)擊“Allow access”

image

這樣,我們的服務(wù)器就可以開始監(jiān)聽了。但是這有什么用呢?是的,沒有什么用。

我們還需要為服務(wù)器添加一些功能,例如接受傳入的請求,給客戶端發(fā)送消息,或者從客戶端接收消息等等

第三步:接受傳入的請求

我們需要通過Accept,或者(BeginAccept)來接受傳入的請求,請注意下面代碼中的紅色部分

 

using System; using System.Collections.Generic; using System.Linq; using System.Text; //額外導(dǎo)入的兩個命名空間 using System.Net.Sockets; using System.Net; namespace SocketServer { class Program { Main(string[] args) { //創(chuàng)建一個新的Socket,這里我們使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //將該socket綁定到主機(jī)上面的某個端口 //方法參考: socket.Bind(new IPEndPoint(IPAddress.Any, 4530)); //啟動監(jiān)聽,并且設(shè)置一個最大的隊(duì)列長度 //方法參考:(v=VS.100).aspx socket.Listen(4); //開始接受客戶端連接請求 //方法參考: socket.BeginAccept(new AsyncCallback((ar) => { //這就是客戶端的Socket實(shí)例,我們后續(xù)可以將其保存起來 var client = socket.EndAccept(ar); //給客戶端發(fā)送一個歡迎消息 client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at "+DateTime.Now.ToString())); }), null); Console.WriteLine("Server is ready!"); Console.Read(); } } }

 

wow,看起來不錯對吧,我們趕緊做一個客戶端來測試一下吧

 

第四步:創(chuàng)建客戶端

我們還是使用一個Console Application

image

添加如下的代碼,并且創(chuàng)建客戶端連接

using System; using System.Collections.Generic; using System.Linq; using System.Text; //導(dǎo)入的命名空間 using System.Net.Sockets; namespace SocketClient { class Program { Main(string[] args) { //創(chuàng)建一個Socket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //連接到指定服務(wù)器的指定端口 //方法參考: socket.Connect("localhost", 4530); Console.WriteLine("connect to the server"); Console.Read(); } } }

依次選擇SocketServer和SocketClient這兩個項(xiàng)目,分別將其啟動為調(diào)試狀態(tài)(右鍵菜單,Debug=>Start new instance)

image

我們看到兩個程序都工作正常。

但是,在客戶端怎么沒有收到服務(wù)器發(fā)過來的消息呢?那是因?yàn),我們沒有在客戶端提供這方面的功能。

 

第五步:在客戶端中實(shí)現(xiàn)接受消息的方法using System; using System.Collections.Generic; using System.Linq; using System.Text; //導(dǎo)入的命名空間 using System.Net.Sockets; namespace SocketClient { class Program { Main(string[] args) { //創(chuàng)建一個Socket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //連接到指定服務(wù)器的指定端口 //方法參考: socket.Connect("localhost", 4530); //實(shí)現(xiàn)接受消息的方法 var buffer = socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback((ar) => { //方法參考: var length = socket.EndReceive(ar); //讀取出來消息內(nèi)容 var message = Encoding.Unicode.GetString(buffer, 0, length); //顯示消息 Console.WriteLine(message); }), null); Console.WriteLine("connect to the server"); Console.Read(); } } }

請注意以上紅色的部分,我們用了BeginReceive方法進(jìn)行異步的消息偵聽,如果收到了,我們就打印出來

image

看起來已經(jīng)實(shí)現(xiàn)了我們需求了:服務(wù)器給客戶端發(fā)了一個消息,而客戶端也已經(jīng)收到了。

但是,這遠(yuǎn)遠(yuǎn)不夠,因?yàn)樗鼈冎g的通訊不僅僅是一次性的,那么如果服務(wù)器要不斷地給客戶端發(fā)消息,例如每隔兩秒鐘就發(fā)送一個消息,如何實(shí)現(xiàn)呢?

 

第六步:實(shí)現(xiàn)服務(wù)器定期向客戶端發(fā)消息using System; using System.Collections.Generic; using System.Linq; using System.Text; //額外導(dǎo)入的兩個命名空間 using System.Net.Sockets; using System.Net; namespace SocketServer { class Program { Main(string[] args) { //創(chuàng)建一個新的Socket,這里我們使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //將該socket綁定到主機(jī)上面的某個端口 //方法參考: socket.Bind(new IPEndPoint(IPAddress.Any, 4530)); //啟動監(jiān)聽,并且設(shè)置一個最大的隊(duì)列長度 //方法參考:(v=VS.100).aspx socket.Listen(4); //開始接受客戶端連接請求 //方法參考: socket.BeginAccept(new AsyncCallback((ar) => { //這就是客戶端的Socket實(shí)例,我們后續(xù)可以將其保存起來 var client = socket.EndAccept(ar); //給客戶端發(fā)送一個歡迎消息 client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at "+DateTime.Now.ToString())); //實(shí)現(xiàn)每隔兩秒鐘給服務(wù)器發(fā)一個消息 //這里我們使用了一個定時器 var timer = new System.Timers.Timer(); timer.Interval = 2000D; timer.Enabled = true; timer.Elapsed += (o, a) => { client.Send(Encoding.Unicode.GetBytes("Message from server at " +DateTime.Now.ToString())); }; timer.Start(); }), null); Console.WriteLine("Server is ready!"); Console.Read(); } } }

 

我們還要實(shí)現(xiàn)在客戶端一直監(jiān)聽消息的機(jī)制,而不是一次性接收.請注意下面紅色的部分

 

using System; using System.Collections.Generic; using System.Linq; using System.Text; //導(dǎo)入的命名空間 using System.Net.Sockets; namespace SocketClient { class Program { Main(string[] args) { //創(chuàng)建一個Socket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //連接到指定服務(wù)器的指定端口 //方法參考: socket.Connect("localhost", 4530); Console.WriteLine("connect to the server"); //實(shí)現(xiàn)接受消息的方法 //方法參考: socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage),socket); Console.Read(); } [1024]; ReceiveMessage(IAsyncResult ar) { try { var socket = ar.AsyncState as Socket; //方法參考: var length = socket.EndReceive(ar); //讀取出來消息內(nèi)容 var message = Encoding.Unicode.GetString(buffer, 0, length); //顯示消息 Console.WriteLine(message); //接收下一個消息(因?yàn)檫@是一個遞歸的調(diào)用,所以這樣就可以一直接收消息了) socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); } catch(Exception ex){ Console.WriteLine(ex.Message); } } } }

重新調(diào)試起來,看起來的效果如下圖所示

image

我們繼續(xù)做下面的實(shí)驗(yàn),一步一步地研究Socket通訊中可能遇到的一些問題

請先關(guān)閉掉客戶端這個程序,而不要關(guān)閉服務(wù)端程序,這時會發(fā)現(xiàn)一個錯誤

image

這個錯誤很容易理解,因?yàn)榭蛻舳艘呀?jīng)關(guān)閉,也就是客戶端那個Socket已經(jīng)不存在了,服務(wù)器還繼續(xù)向它發(fā)送消息當(dāng)然會出錯。所以,從可靠性方面的考慮,我們必須在發(fā)送消息之前檢測Socket的活動狀態(tài)

 

第七步:檢測客戶端的活動狀態(tài)using System; using System.Collections.Generic; using System.Linq; using System.Text; //額外導(dǎo)入的兩個命名空間 using System.Net.Sockets; using System.Net; namespace SocketServer { class Program { Main(string[] args) { //創(chuàng)建一個新的Socket,這里我們使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //將該socket綁定到主機(jī)上面的某個端口 //方法參考: socket.Bind(new IPEndPoint(IPAddress.Any, 4530)); //啟動監(jiān)聽,并且設(shè)置一個最大的隊(duì)列長度 //方法參考:(v=VS.100).aspx socket.Listen(4); //開始接受客戶端連接請求 //方法參考: socket.BeginAccept(new AsyncCallback((ar) => { //這就是客戶端的Socket實(shí)例,我們后續(xù)可以將其保存起來 var client = socket.EndAccept(ar); //給客戶端發(fā)送一個歡迎消息 client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at "+DateTime.Now.ToString())); //實(shí)現(xiàn)每隔兩秒鐘給服務(wù)器發(fā)一個消息 //這里我們使用了一個定時器 var timer = new System.Timers.Timer(); timer.Interval = 2000D; timer.Enabled = true; timer.Elapsed += (o, a) => { //檢測客戶端Socket的狀態(tài) if(client.Connected) { try { client.Send(Encoding.Unicode.GetBytes("Message from server at " + DateTime.Now.ToString())); } catch(SocketException ex) { Console.WriteLine(ex.Message); } } else { timer.Stop(); timer.Enabled = false; Console.WriteLine("Client is disconnected, the timer is stop."); } }; timer.Start(); }), null); Console.WriteLine("Server is ready!"); Console.Read(); } } }

上面代碼的邏輯很清楚,但有時候還是會觸發(fā)那個SocketException。為什么呢?這是因?yàn)槲覀兊腡imer是每隔兩秒鐘檢查一次,那么就很可能有一種情況,我們檢查的時候,它還是連接狀態(tài),消息發(fā)出去之后,它斷開了。這種情況肯定是存在的。所以要用Try..catch的結(jié)構(gòu)

 

目前我們實(shí)現(xiàn)的場景很簡單,服務(wù)器只管發(fā)消息,客戶端只管收消息。但實(shí)際工作中,可能希望服務(wù)器和客戶端都能收發(fā)消息。請看下一節(jié)

 

第八步:實(shí)現(xiàn)雙向收發(fā)消息

先看服務(wù)端的修改

 

using System; using System.Collections.Generic; using System.Linq; using System.Text; //額外導(dǎo)入的兩個命名空間 using System.Net.Sockets; using System.Net; namespace SocketServer { class Program { Main(string[] args) { //創(chuàng)建一個新的Socket,這里我們使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //將該socket綁定到主機(jī)上面的某個端口 //方法參考: socket.Bind(new IPEndPoint(IPAddress.Any, 4530)); //啟動監(jiān)聽,并且設(shè)置一個最大的隊(duì)列長度 //方法參考:(v=VS.100).aspx socket.Listen(4); //開始接受客戶端連接請求 //方法參考: socket.BeginAccept(new AsyncCallback((ar) => { //這就是客戶端的Socket實(shí)例,我們后續(xù)可以將其保存起來 var client = socket.EndAccept(ar); //給客戶端發(fā)送一個歡迎消息 client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at "+DateTime.Now.ToString())); //實(shí)現(xiàn)每隔兩秒鐘給服務(wù)器發(fā)一個消息 //這里我們使用了一個定時器 var timer = new System.Timers.Timer(); timer.Interval = 2000D; timer.Enabled = true; timer.Elapsed += (o, a) => { //檢測客戶端Socket的狀態(tài) if(client.Connected) { try { client.Send(Encoding.Unicode.GetBytes("Message from server at " + DateTime.Now.ToString())); } catch(SocketException ex) { Console.WriteLine(ex.Message); } } else { timer.Stop(); timer.Enabled = false; Console.WriteLine("Client is disconnected, the timer is stop."); } }; timer.Start(); //接收客戶端的消息(這個和在客戶端實(shí)現(xiàn)的方式是一樣的) client.BeginReceive(buffer,0,buffer.Length,SocketFlags.None,new AsyncCallback(ReceiveMessage),client); }), null); Console.WriteLine("Server is ready!"); Console.Read(); } [1024]; ReceiveMessage(IAsyncResult ar) { try { var socket = ar.AsyncState as Socket; //方法參考: var length = socket.EndReceive(ar); //讀取出來消息內(nèi)容 var message = Encoding.Unicode.GetString(buffer, 0, length); //顯示消息 Console.WriteLine(message); //接收下一個消息(因?yàn)檫@是一個遞歸的調(diào)用,所以這樣就可以一直接收消息了) socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); } catch(Exception ex){ Console.WriteLine(ex.Message); } } } }

可以看出來,為了讓服務(wù)器可以接受消息,,其實(shí)并不需要什么特別的設(shè)計(jì),與客戶端接受消息其實(shí)可以是一樣的

 

再來看看客戶端的修改

using System; using System.Collections.Generic; using System.Linq; using System.Text; //導(dǎo)入的命名空間 using System.Net.Sockets; namespace SocketClient { class Program { Main(string[] args) { //創(chuàng)建一個Socket var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //連接到指定服務(wù)器的指定端口 //方法參考: socket.Connect("localhost", 4530); Console.WriteLine("connect to the server"); //實(shí)現(xiàn)接受消息的方法 //方法參考: socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); //接受用戶輸入,將消息發(fā)送給服務(wù)器端 while(true) { var message = "Message from client : " + Console.ReadLine(); var outputBuffer = Encoding.Unicode.GetBytes(message); socket.BeginSend(outputBuffer, 0, outputBuffer.Length, SocketFlags.None, null, null); } } [1024]; ReceiveMessage(IAsyncResult ar) { try { var socket = ar.AsyncState as Socket; //方法參考: var length = socket.EndReceive(ar); //讀取出來消息內(nèi)容 var message = Encoding.Unicode.GetString(buffer, 0, length); //顯示消息 Console.WriteLine(message); //接收下一個消息(因?yàn)檫@是一個遞歸的調(diào)用,所以這樣就可以一直接收消息了) socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); } catch(Exception ex) { Console.WriteLine(ex.Message); } } } }

我在這里做了一個死循環(huán),用戶可以不斷地輸入,這些消息會被發(fā)送給服務(wù)器。如下圖所示

image

【備注】因?yàn)榉⻊?wù)器每隔兩秒鐘會發(fā)送新消息過來,所以在輸入的時候,動作要稍快一點(diǎn)啦

 

本文最后探討一個問題,就是如何讓我們的服務(wù)器可以支持多個客戶端

 

第九步:支持多個客戶端

這個步驟只需要修改服務(wù)端程序即可

using System; using System.Collections.Generic; using System.Linq; using System.Text; //額外導(dǎo)入的兩個命名空間 using System.Net.Sockets; using System.Net; namespace SocketServer { class Program { Main(string[] args) { //創(chuàng)建一個新的Socket,這里我們使用最常用的基于TCP的Stream Socket(流式套接字) var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //將該socket綁定到主機(jī)上面的某個端口 //方法參考: socket.Bind(new IPEndPoint(IPAddress.Any, 4530)); //啟動監(jiān)聽,并且設(shè)置一個最大的隊(duì)列長度 //方法參考:(v=VS.100).aspx socket.Listen(4); //開始接受客戶端連接請求 //方法參考: socket.BeginAccept(new AsyncCallback(ClientAccepted), socket); Console.WriteLine("Server is ready!"); Console.Read(); } ClientAccepted(IAsyncResult ar) { var socket = ar.AsyncState as Socket; //這就是客戶端的Socket實(shí)例,我們后續(xù)可以將其保存起來 var client = socket.EndAccept(ar); //給客戶端發(fā)送一個歡迎消息 client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at " + DateTime.Now.ToString())); //實(shí)現(xiàn)每隔兩秒鐘給服務(wù)器發(fā)一個消息 //這里我們使用了一個定時器 var timer = new System.Timers.Timer(); timer.Interval = 2000D; timer.Enabled = true; timer.Elapsed += (o, a) => { //檢測客戶端Socket的狀態(tài) if(client.Connected) { try { client.Send(Encoding.Unicode.GetBytes("Message from server at " + DateTime.Now.ToString())); } catch(SocketException ex) { Console.WriteLine(ex.Message); } } else { timer.Stop(); timer.Enabled = false; Console.WriteLine("Client is disconnected, the timer is stop."); } }; timer.Start(); //接收客戶端的消息(這個和在客戶端實(shí)現(xiàn)的方式是一樣的) client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), client); //準(zhǔn)備接受下一個客戶端請求 socket.BeginAccept(new AsyncCallback(ClientAccepted), socket); } [1024]; ReceiveMessage(IAsyncResult ar) { try { var socket = ar.AsyncState as Socket; //方法參考: var length = socket.EndReceive(ar); //讀取出來消息內(nèi)容 var message = Encoding.Unicode.GetString(buffer, 0, length); //顯示消息 Console.WriteLine(message); //接收下一個消息(因?yàn)檫@是一個遞歸的調(diào)用,所以這樣就可以一直接收消息了) socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket); } catch(Exception ex){ Console.WriteLine(ex.Message); } } } }

最后調(diào)試起來看到的效果如下圖

image

 

本文源代碼,可以通過這里下載

posted on


  本文關(guān)鍵詞:socket編程,由筆耕文化傳播整理發(fā)布。



本文編號:87617

資料下載
論文發(fā)表

本文鏈接:http://sikaile.net/wenshubaike/jyzy/87617.html


Copyright(c)文論論文網(wǎng)All Rights Reserved | 網(wǎng)站地圖 |

版權(quán)申明:資料由用戶bf065***提供,本站僅收錄摘要或目錄,作者需要刪除請E-mail郵箱bigeng88@qq.com
色涩一区二区三区四区| 国产目拍亚洲精品区一区| 日韩欧美综合在线播放| 日韩成人高清免费在线| 国产精品一区二区三区黄色片| 欧美日本精品视频在线观看| 日韩精品视频高清在线观看| 日韩欧美二区中文字幕| 国产一区二区三区香蕉av| 丁香六月婷婷基地伊人| 免费精品一区二区三区| 国产亚洲中文日韩欧美综合网| 国产老熟女乱子人伦视频| 搡老熟女老女人一区二区| 午夜小视频成人免费看| 中文字幕乱码免费人妻av| 熟女少妇一区二区三区蜜桃| 又大又紧又硬又湿又爽又猛| 国产成人在线一区二区三区| 中日韩免费一区二区三区| 中文字幕精品少妇人妻| 国产精品免费视频久久| 九九热在线免费在线观看| 视频一区日韩经典中文字幕| 最新国产欧美精品91| 欧美日韩精品综合一区| 免费高清欧美一区二区视频| 午夜精品黄片在线播放| 日本一本在线免费福利| 国产精品第一香蕉视频| 人妻精品一区二区三区视频免精| 欧美日韩亚洲巨色人妻| 1024你懂的在线视频| 厕所偷拍一区二区三区视频| 日本东京热加勒比一区二区| 亚洲中文字幕有码在线观看| 偷拍美女洗澡免费视频| 小草少妇视频免费看视频| 国产成人精品视频一二区| 国产又色又爽又黄又大| 91免费精品国自产拍偷拍|