C# 如何實現簡單的Socket通訊(附示例)
上週由於有個專案需要用到網路通訊這塊,然後就花了點時間研究了一下,本來想上週就寫出來的,但是突然要忙,所以等到現在。
話說對於網路通訊,以前寫C++的時候,天天面對著執行緒和Socket,所以換成C#也就沒那麼怕了,雖然C++下也沒有掌握的多好,但畢竟只是一個小Demo,只作為了解一下過程。
自己寫了一個服務端和一個客戶端,剛開始比較簡單,只是能達到連通,收發資訊的目的,但是很粗糙。而後稍加改進呢~加上了多執行緒,所以能感覺更科學一些,不過自己真的很菜,程式碼寫的不是很好看,下面分兩個版本給大家表出來,希望幫助剛接觸C#網路通訊的朋友。
對了,還要說一點的就是,我這個小Demo是用控制檯程式寫的為什麼選擇控制檯?我也不清楚,可能是因為有個main函式的原因,在一個檔案裡就能搞定吧~有點懶。
簡單連通版:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
//Server端 //建立一個socket物件,三個引數分別代表: //AddressFamily.InterNetwork: IPV4協議,SocketType.Stream:流型別,ProtocolType.Tcp:TCP方式連線 Socket ss = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//獲取當前機器的IP地址,在C#中用IPAddress這個類去存放IP地址 IPAddress ipa = Dns.GetHostByName(Dns.GetHostName()).AddressList[0]; //IPEndPoint是用來把IP地址和埠號整合在一起的一個型別,在C#中叫做“網路端點” //我這裡假設伺服器開的埠號是11000,這個是自己隨意設定的。不是唯一 IPEndPoint iep = new IPEndPoint(ipa, 11000);
//之前建立的Socket與我們本機的IP和所設的埠號繫結 ss.Bind(iep); //進行監聽,也就是說我們開始偵聽網路上對本機IP和11000這個埠進行連線的資訊了 //引數列表官方定義為:掛起連線佇列的最大長度。這個稍後單獨說。 ss.Listen(50); byte [] bMessage = new byte [1024*10];
string sMsg = "Can I help you ?" ;
//當ss這個用於監聽的socket收到一個連線請求之後,會接受對方請求,並建立一個新的連線 //而新的這個s就是接下來用於真正通訊的socket了。 Socket s = ss.Accept(); while ( true )
{ try
{
//bMessage = System.Text.Encoding.BigEndianUnicode.GetBytes(sMsg.ToCharArray());
//s.Send(bMessage);
//bMessage = null;
//顧名思義啦,這是一個接收資訊的方法,把通過網路傳過來的流存入byte陣列中去。
//之所以把它寫在這裡是因為我的設計之初是,當socket連通成功之後,Client端會首先給Server端發一個資訊。
s.Receive(bMessage);
//用於把byte轉成string的一個方法,注意我用的是Unicode,通常我們還可以用UTF8,ASCII編解碼
//之前最坑的是當時不知道在C#下如何轉,在網上看到了一個用BigEndianUnicode編碼的,
//當時沒有想太多就使了,結果就是解出來各種亂碼的樣子,這塊跟大夥提一下
sMsg = System.Text.Encoding.Unicode.GetString(bMessage);
Console.WriteLine( "Client(" + DateTime.Now.ToShortTimeString() + "):" + sMsg);
//接下來就是輸入一個字串,並把其轉成byte陣列,然後Send出去。
bMessage = System.Text.Encoding.Unicode.GetBytes(Console.ReadLine().ToCharArray());
s.Send(bMessage);
}
catch (System.Exception ex)
{
}
} |
這塊說一下.Listen(backlog)方法裡的引數到底是表示什麼東東,其實之前我也不太明白,也是寫博的時候現去查的,就看到了一個比較靠譜的說法。
大概意思就是:當我們把IP和埠號暴露在網路當中,就是讓其他IP去進行連線,而我們不能保證某一段時刻只有一個IP來進行連線請求,也就是說在同一時間段範圍內,可能有多個連線請求,這個時候我們就需要用一個佇列來維護請求連線的先後順序。在說的細緻一點呢,就是連線的過程不會是一瞬時間完成的,我們都知道TCP協議是要經過三次握手的,而在這個過程中,就有可能別的IP來進行連線請求,所以這個backlog就是表示這個佇列的長度的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
//Client端 //同伺服器端一樣,需要建立一個socket Socket ss = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//這塊主要就是把你想連線的目標主機IP地址進行一下解析,並存入IPAddress型別的一個例項當中 IPAddress myIP = IPAddress.Parse( "192.168.xxx.xxx" );
//這也同伺服器是一個意思,把IP和埠號整合在一個網路端點中 IPEndPoint ipe = new IPEndPoint(myIP, 11000);
byte [] bMessage = null ;
string sMsg = "hello world" ;
try { //這是客戶端的一個方法,表示連線的物件就是引數的網路端點中的IP地址和埠號
//但是注意這裡不需要返回一個新的socket作為通訊socket
//而是進行連線的這個ss就是將來一直維持此次連線的socket,直到該通道關閉或斷開
ss.Connect(ipe);
bMessage = System.Text.Encoding.Unicode.GetBytes(sMsg.ToCharArray());
//send方法的返回值表示已傳送到socket的位元組數,就像我在server端說的那樣
//這個Demo的設計思路就是連通後,客戶端先向伺服器端傳送一個資訊
int count = ss.Send(bMessage);
if (count > 0)
{
while ( true )
{
//bMessage = null;
ss.Receive(bMessage);
sMsg = System.Text.Encoding.Unicode.GetString(bMessage);
Console.WriteLine( "Server(" + DateTime.Now.ToShortTimeString() + "):" + sMsg);
bMessage = System.Text.Encoding.Unicode.GetBytes(Console.ReadLine().ToCharArray());
ss.Send(bMessage);
}
}
} catch (ArgumentNullException ae)
{ } catch (SocketException se)
{ Console.WriteLine( "SocketException : {0}" , se.ToString());
} catch (Exception e)
{ } |
這樣一個簡單的C#下的socket通訊就寫完了,說實話,我也只是懂個大概,現在很少會去深究什麼了,只是到了需要的程度,才會去做一個研究,另外大家注意我這裡用了try...catch,大家留意一下,我記得可能是必加的。
下面表一下另外一個稍稍改進版的,客戶端沒有變,主要是改服務端的程式碼。
哎呀,剛剛看了一下,感覺寫的好垃圾,都不好意思表上來了。其實我當時寫這個增進版是想了解一下C#下的多執行緒來著(時間有點久我給忘了,以為能歸到socket通訊這塊呢),正好socket通訊可以利用到多執行緒,就省得自己再去想象一個環境了,所以這個增進版主要是想說關於多執行緒的一些東西,這個我之後單獨寫一篇來講吧,就不在這篇裡表了。
不過我給大家說一下大概思路,利用多執行緒就是想能在Console環境下隨時進行訊息的傳送和接收,而不是收一條才能發一條這樣子。另外,我也擴充了一下,就是可以多臺客戶端對伺服器端進行請求連線,這樣就變成一對多的關係了,主要實現就是在伺服器端開一個專門用於監聽連線請求的執行緒,然後接受請求後對每個socket單獨再開一個執行緒這樣子。
具體的實現,我會在下一篇《C# 多執行緒如何傳遞兩個以上引數的實現方法》中使用這個擴充套件版的socket通訊作為例子來表給大家。
相關文章
- c#實現最簡單的socket通訊C#
- 簡單的Socket通訊
- C# 通過socket實現UDP 通訊C#UDP
- socket 完成簡單的通訊
- Java的Socket通訊簡單例項Java單例
- C# 簡單的聊天大廳功能及原始碼(socket通訊)C#原始碼
- 簡單通訊錄的實現
- C# 實現socket通訊程式(伺服器端)C#伺服器
- C#中使用Socket實現簡單Web伺服器C#Web伺服器
- php實現一個簡單的socketPHP
- 簡單的Java實現Netty進行通訊JavaNetty
- socket實現簡單ssh服務
- C# superSocket簡單示例C#
- 智慧家居簡單實現---使用ESP8266簡單實現和APP通訊APP
- vue 實現原理及簡單示例實現Vue
- oracle的訊息簡單示例Oracle
- C# NModbus RTU通訊實現C#
- 如何用Java Socket實現一個簡單的Redis客戶端JavaRedis客戶端
- QT使用 http 協議通訊的實現示例QTHTTP協議
- AgileEAS.NET SOA 中介軟體平臺.Net Socket通訊框架-簡單例子-實現簡單的服務端客戶端訊息應答框架單例服務端客戶端
- Socket最簡單的客戶端與服務端通訊-Java客戶端服務端Java
- 使用Scala模擬簡單的RPC通訊,Socket程式設計RPC程式設計
- iOS基於Socket.io即時通訊IM實現,WebRTC實現視訊通話iOSWeb
- C#實現聯通簡訊Sgip協議程式原始碼C#協議原始碼
- shell的圖形化實現簡單示例
- WinForm的Socket實現簡單的聊天室 IMORM
- socket通訊
- 使用go net實現簡單的redis通訊協議YWSVGoRedis協議
- socket通訊的建立
- php的socket通訊PHP
- 如何優雅的實現訊息通訊?
- TCP和UDP實現簡單一對一通訊TCPUDP
- linux網路程式設計之用socket實現簡單客戶端和服務端的通訊(基於TCP)Linux程式設計客戶端服務端TCP
- C#網路程式設計-簡單的通訊原始碼C#程式設計原始碼
- unix socket通訊
- 完整版通訊錄(實現簡單具體易上手!!)
- Thinking in Java--使用NIO實現非阻塞Socket通訊ThinkingJava
- websocket+node實現一個最簡單的即時通訊功能Web