天天看點

C# Socket系列二 簡單的建立 socket 通信

看了系列一 我們開啟了對socket tcp的監聽狀态,那麼這一章我們來講解怎麼建立socket的通信代碼

我建立一個類 TSocketBase

<a href="http://www.cnblogs.com/soundcode/p/7238616.html#">?</a>

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

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

<code>public</code> <code>abstract</code> <code>class</code> <code>TSocketBase</code>

<code>    </code><code>{</code>

<code>        </code><code>//封裝socket</code>

<code>        </code><code>internal</code> <code>Socket _Socket;</code>

<code>        </code><code>//回調</code>

<code>        </code><code>private</code> <code>AsyncCallback aCallback;</code>

<code>        </code><code>//接受資料的緩沖區</code>

<code>        </code><code>private</code> <code>byte</code><code>[] Buffers;</code>

<code>        </code><code>//辨別是否已經釋放</code>

<code>        </code><code>private</code> <code>volatile</code> <code>bool</code> <code>IsDispose;</code>

<code>        </code><code>//10K的緩沖區空間</code>

<code>        </code><code>private</code> <code>int</code> <code>BufferSize = 10*1024;</code>

<code>        </code><code>//收取消息狀态碼</code>

<code>        </code><code>private</code> <code>SocketError ReceiveError;</code>

<code>        </code><code>//發送消息的狀态碼</code>

<code>        </code><code>private</code> <code>SocketError SenderError;</code>

<code>        </code><code>//每一次接受到的位元組數</code>

<code>        </code><code>private</code> <code>int</code> <code>ReceiveSize = 0;</code>

<code>        </code><code>//接受空消息次數</code>

<code>        </code><code>private</code> <code>byte</code> <code>ZeroCount = 0;</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>Receive(</code><code>byte</code><code>[] rbuff);</code>

<code>        </code><code>public</code> <code>void</code> <code>SetSocket()</code>

<code>        </code><code>{</code>

<code>            </code><code>this</code><code>.aCallback =</code><code>new</code> <code>AsyncCallback(</code><code>this</code><code>.ReceiveCallback);</code>

<code>            </code><code>this</code><code>.IsDispose =</code><code>false</code><code>;</code>

<code>            </code><code>this</code><code>._Socket.ReceiveBufferSize =</code><code>this</code><code>.BufferSize;</code>

<code>            </code><code>this</code><code>._Socket.SendBufferSize =</code><code>this</code><code>.BufferSize;</code>

<code>            </code><code>this</code><code>.Buffers =</code><code>new</code> <code>byte</code><code>[</code><code>this</code><code>.BufferSize];</code>

<code>        </code><code>}</code>

<code>        </code><code>/// &lt;summary&gt;</code>

<code>        </code><code>/// 關閉并釋放資源</code>

<code>        </code><code>/// &lt;/summary&gt;</code>

<code>        </code><code>/// &lt;param name="msg"&gt;&lt;/param&gt;</code>

<code>        </code><code>public</code> <code>void</code> <code>Close(</code><code>string</code> <code>msg)</code>

<code>            </code><code>if</code> <code>(!</code><code>this</code><code>.IsDispose)</code>

<code>            </code><code>{</code>

<code>                </code><code>this</code><code>.IsDispose =</code><code>true</code><code>;</code>

<code>                </code><code>try</code>

<code>                </code><code>{</code>

<code>                    </code><code>try</code>

<code>                    </code><code>{</code>

<code>                        </code><code>this</code><code>._Socket.Close();</code>

<code>                    </code><code>}</code>

<code>                    </code><code>catch</code>

<code>                    </code><code>IDisposable disposable =</code><code>this</code><code>._Socket;</code>

<code>                    </code><code>if</code> <code>(disposable !=</code><code>null</code><code>)</code>

<code>                        </code><code>disposable.Dispose();</code>

<code>                    </code><code>this</code><code>.Buffers =</code><code>null</code><code>;</code>

<code>                    </code><code>GC.SuppressFinalize(</code><code>this</code><code>);</code>

<code>                </code><code>}</code>

<code>                </code><code>catch</code> <code>(Exception)</code>

<code>            </code><code>}</code>

<code>        </code><code>/// 遞歸接收消息方法</code>

<code>        </code><code>internal</code> <code>void</code> <code>ReceiveAsync()</code>

<code>            </code><code>try</code>

<code>                </code><code>if</code> <code>(!</code><code>this</code><code>.IsDispose &amp;&amp;</code><code>this</code><code>._Socket.Connected)</code>

<code>                    </code><code>this</code><code>._Socket.BeginReceive(</code><code>this</code><code>.Buffers, 0,</code><code>this</code><code>.BufferSize, SocketFlags.None,</code><code>out</code> <code>SenderError,</code>

<code>                        </code><code>this</code><code>.aCallback,</code><code>this</code><code>);</code>

<code>                    </code><code>CheckSocketError(ReceiveError);</code>

<code>            </code><code>catch</code> <code>(System.Net.Sockets.SocketException)</code>

<code>                </code><code>this</code><code>.Close(</code><code>"連結已經被關閉"</code><code>);</code>

<code>            </code><code>catch</code> <code>(System.ObjectDisposedException)</code>

<code>        </code><code>/// 接收消息回調函數</code>

<code>        </code><code>/// &lt;param name="iar"&gt;&lt;/param&gt;</code>

<code>        </code><code>private</code> <code>void</code> <code>ReceiveCallback(IAsyncResult iar)</code>

<code>                    </code><code>//接受消息</code>

<code>                    </code><code>ReceiveSize = _Socket.EndReceive(iar,</code><code>out</code> <code>ReceiveError);</code>

<code>                    </code><code>//檢查狀态碼</code>

<code>                    </code><code>if</code> <code>(!CheckSocketError(ReceiveError) &amp;&amp; SocketError.Success == ReceiveError)</code>

<code>                        </code><code>//判斷接受的位元組數</code>

<code>                        </code><code>if</code> <code>(ReceiveSize &gt; 0)</code>

<code>                        </code><code>{</code>

<code>                            </code><code>byte</code><code>[] rbuff =</code><code>new</code> <code>byte</code><code>[ReceiveSize];</code>

<code>                            </code><code>Array.Copy(</code><code>this</code><code>.Buffers, rbuff, ReceiveSize);</code>

<code>                            </code><code>this</code><code>.Receive(rbuff);</code>

<code>                            </code><code>//重置連續收到空位元組數</code>

<code>                            </code><code>ZeroCount = 0;</code>

<code>                            </code><code>//繼續開始異步接受消息</code>

<code>                            </code><code>ReceiveAsync();</code>

<code>                        </code><code>}</code>

<code>                        </code><code>else</code>

<code>                            </code><code>ZeroCount++;</code>

<code>                            </code><code>if</code> <code>(ZeroCount == 5)</code>

<code>                            </code><code>{</code>

<code>                                </code><code>this</code><code>.Close(</code><code>"錯誤連結"</code><code>);</code>

<code>                            </code><code>}</code>

<code>                </code><code>catch</code> <code>(System.Net.Sockets.SocketException)</code>

<code>                    </code><code>this</code><code>.Close(</code><code>"連結已經被關閉"</code><code>);</code>

<code>                </code><code>catch</code> <code>(System.ObjectDisposedException)</code>

<code>        </code><code>/// 錯誤判斷</code>

<code>        </code><code>/// &lt;param name="socketError"&gt;&lt;/param&gt;</code>

<code>        </code><code>/// &lt;returns&gt;&lt;/returns&gt;</code>

<code>        </code><code>private</code> <code>bool</code> <code>CheckSocketError(SocketError socketError)</code>

<code>            </code><code>switch</code> <code>((socketError))</code>

<code>                </code><code>case</code> <code>SocketError.SocketError:</code>

<code>                </code><code>case</code> <code>SocketError.VersionNotSupported:</code>

<code>                </code><code>case</code> <code>SocketError.TryAgain:</code>

<code>                </code><code>case</code> <code>SocketError.ProtocolFamilyNotSupported:</code>

<code>                </code><code>case</code> <code>SocketError.ConnectionAborted:</code>

<code>                </code><code>case</code> <code>SocketError.ConnectionRefused:</code>

<code>                </code><code>case</code> <code>SocketError.ConnectionReset:</code>

<code>                </code><code>case</code> <code>SocketError.Disconnecting:</code>

<code>                </code><code>case</code> <code>SocketError.HostDown:</code>

<code>                </code><code>case</code> <code>SocketError.HostNotFound:</code>

<code>                </code><code>case</code> <code>SocketError.HostUnreachable:</code>

<code>                </code><code>case</code> <code>SocketError.NetworkDown:</code>

<code>                </code><code>case</code> <code>SocketError.NetworkReset:</code>

<code>                </code><code>case</code> <code>SocketError.NetworkUnreachable:</code>

<code>                </code><code>case</code> <code>SocketError.NoData:</code>

<code>                </code><code>case</code> <code>SocketError.OperationAborted:</code>

<code>                </code><code>case</code> <code>SocketError.Shutdown:</code>

<code>                </code><code>case</code> <code>SocketError.SystemNotReady:</code>

<code>                </code><code>case</code> <code>SocketError.TooManyOpenSockets:</code>

<code>                    </code><code>this</code><code>.Close(socketError.ToString());</code>

<code>                    </code><code>return</code> <code>true</code><code>;</code>

<code>            </code><code>return</code> <code>false</code><code>;</code>

<code>        </code><code>/// 發送消息方法</code>

<code>        </code><code>internal</code> <code>int</code> <code>SendMsg(</code><code>byte</code><code>[] buffer)</code>

<code>            </code><code>int</code> <code>size = 0;</code>

<code>                </code><code>if</code> <code>(!</code><code>this</code><code>.IsDispose)</code>

<code>                    </code><code>size =</code><code>this</code><code>._Socket.Send(buffer, 0, buffer.Length, SocketFlags.None,</code><code>out</code> <code>SenderError);</code>

<code>                    </code><code>CheckSocketError(SenderError);</code>

<code>            </code><code>buffer =</code><code>null</code><code>;</code>

<code>            </code><code>return</code> <code>size;</code>

<code>    </code><code>}</code>

  

上面我們事先了socket的異步接受消息,和同步發送消息已經關閉釋放資源代碼

接受消息net底層提供的接受消息的方法有很多,為什麼我們要選擇上面所寫的呢?那是為了相容U3D,silverlight, wpf, wp, wf,等程式可執行,不在重複做相同工作。

現在我們來建立一個實作類 TSocketClient

<code>public</code> <code>class</code> <code>TSocketClient : TSocketBase</code>

<code>        </code><code>/// 是否是伺服器端的資源</code>

<code>        </code><code>private</code> <code>bool</code> <code>isServer =</code><code>false</code><code>;</code>

<code>        </code><code>/// 用戶端主動請求伺服器</code>

<code>        </code><code>/// &lt;param name="ip"&gt;&lt;/param&gt;</code>

<code>        </code><code>/// &lt;param name="port"&gt;&lt;/param&gt;</code>

<code>        </code><code>public</code> <code>TSocketClient(</code><code>string</code> <code>ip =</code><code>"127.0.0.1"</code><code>,</code><code>int</code> <code>port = 9527)</code>

<code>            </code><code>isServer =</code><code>false</code><code>;</code>

<code>            </code><code>this</code><code>._Socket =</code><code>new</code> <code>System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);</code>

<code>            </code><code>this</code><code>._Socket.Connect(ip, port);</code>

<code>            </code><code>this</code><code>.SetSocket();</code>

<code>            </code><code>this</code><code>.ReceiveAsync();</code>

<code>        </code><code>/// 這個是伺服器收到有效連結初始化</code>

<code>        </code><code>/// &lt;param name="socket"&gt;&lt;/param&gt;</code>

<code>        </code><code>public</code> <code>TSocketClient(Socket socket)</code>

<code>            </code><code>isServer =</code><code>true</code><code>;</code>

<code>            </code><code>this</code><code>._Socket = socket;</code>

<code>        </code><code>/// 收到消息後</code>

<code>        </code><code>/// &lt;param name="rbuff"&gt;&lt;/param&gt;</code>

<code>        </code><code>public</code> <code>override</code> <code>void</code> <code>Receive(</code><code>byte</code><code>[] rbuff)</code>

<code>            </code><code>Console.WriteLine(</code><code>"Receive Msg:"</code> <code>+ System.Text.UTF8Encoding.Default.GetString(rbuff));</code>

<code>            </code><code>if</code> <code>(isServer)</code>

<code>                </code><code>this</code><code>.SendMsg(System.Text.UTF8Encoding.Default.GetBytes(</code><code>"Holle Client!"</code><code>));</code>

因為是測試示例,是以我把伺服器和用戶端實作類寫成了,隻是用來不同的構造函數來區分,是用戶端還是伺服器的辨別

接下來我們測試一下代碼

C# Socket系列二 簡單的建立 socket 通信
C# Socket系列二 簡單的建立 socket 通信
C# Socket系列二 簡單的建立 socket 通信
C# Socket系列二 簡單的建立 socket 通信
C# Socket系列二 簡單的建立 socket 通信

運作結果看出,我們連接配接成功并且發送消息成功。