0
|
1 ???using System; |
|
2 using System.IO; |
|
3 using System.Net; |
|
4 using System.Net.Sockets; |
|
5 using System.Threading; |
|
6 |
|
7 namespace UCIS.Net { |
|
8 public class TCPStream : Stream, INetworkConnection { |
|
9 private static long _totalBytesRead = 0; |
|
10 private static long _totalBytesWritten = 0; |
|
11 public static ulong TotalBytesWritten { get { return (ulong)_totalBytesWritten; } set { _totalBytesWritten = (long)value; } } |
|
12 public static ulong TotalBytesRead { get { return (ulong)_totalBytesRead; } set { _totalBytesRead = (long)value; } } |
|
13 |
|
14 private Socket _Socket; |
|
15 private byte _PeekByte; |
|
16 private bool _HasPeekByte; |
|
17 private ulong _BytesWritten; |
|
18 private ulong _BytesRead; |
|
19 private DateTime _StartTime; |
|
20 private bool _Blocking; |
|
21 |
|
22 public event EventHandler Closed; |
|
23 |
|
24 public TCPStream(Socket Socket) { |
|
25 _Socket = Socket; |
|
26 _HasPeekByte = false; |
|
27 _StartTime = DateTime.Now; |
|
28 _Blocking = _Socket.Blocking; |
|
29 } |
|
30 |
|
31 public Socket Socket { |
|
32 get { return _Socket; } |
|
33 } |
|
34 |
|
35 public DateTime CreationTime { |
|
36 get { return _StartTime; } |
|
37 } |
|
38 |
|
39 public bool Blocking { |
|
40 get { return _Blocking; } |
|
41 set { |
|
42 Socket.Blocking = value; |
|
43 _Blocking = value; |
|
44 } |
|
45 } |
|
46 |
|
47 public bool NoDelay { |
|
48 get { return Socket.NoDelay; } |
|
49 set { Socket.NoDelay = value; } |
|
50 } |
|
51 |
|
52 public override bool CanTimeout { |
|
53 get { return true; } |
|
54 } |
|
55 |
|
56 public override int ReadTimeout { |
|
57 get { return Socket.ReceiveTimeout; } |
|
58 set { Socket.ReceiveTimeout = value; } |
|
59 } |
|
60 |
|
61 public override int WriteTimeout { |
|
62 get { return Socket.SendTimeout; } |
|
63 set { Socket.SendTimeout = value; } |
|
64 } |
|
65 |
|
66 public override int ReadByte() { |
|
67 if (_HasPeekByte) { |
|
68 _HasPeekByte = false; |
|
69 return _PeekByte; |
|
70 } else { |
|
71 byte[] Buffer = new byte[1]; |
|
72 if (Read(Buffer, 0, 1) != 1) return -1; |
|
73 return Buffer[0]; |
|
74 } |
|
75 } |
|
76 |
|
77 public override int Read(byte[] buffer, int offset, int size) { |
|
78 int Count = 0; |
|
79 |
|
80 if (size < 1) return 0; |
|
81 if (_HasPeekByte) { |
|
82 buffer[offset] = _PeekByte; |
|
83 _HasPeekByte = false; |
|
84 Count = 1; |
|
85 offset += 1; |
|
86 size -= 1; |
|
87 } |
|
88 |
|
89 try { |
|
90 if (size > 0) Count += Socket.Receive(buffer, offset, size, SocketFlags.None); |
|
91 } catch (SocketException ex) { |
|
92 switch (ex.SocketErrorCode) { |
|
93 case SocketError.WouldBlock: |
|
94 _Socket.Blocking = _Blocking; |
|
95 throw new TimeoutException("The receive operation would block", ex); |
|
96 case SocketError.TimedOut: |
|
97 throw new TimeoutException("The receive operation timed out", ex); |
|
98 case SocketError.ConnectionReset: |
|
99 case SocketError.Disconnecting: |
|
100 case SocketError.NetworkDown: |
|
101 case SocketError.NetworkReset: |
|
102 case SocketError.NetworkUnreachable: |
|
103 case SocketError.NotConnected: |
|
104 Close(); |
|
105 throw new SocketException((int)ex.SocketErrorCode); |
|
106 default: |
|
107 throw new SocketException((int)ex.SocketErrorCode); |
|
108 } |
|
109 } |
|
110 |
|
111 _BytesRead += (ulong)Count; |
|
112 Interlocked.Add(ref _totalBytesRead, (long)Count); |
|
113 return Count; |
|
114 } |
|
115 |
|
116 public int PeekByte() { |
|
117 if (_HasPeekByte) { |
|
118 return _PeekByte; |
|
119 } else { |
|
120 int Result = 0; |
|
121 Result = ReadByte(); |
|
122 if (Result >= 0 && Result <= 255) { |
|
123 _PeekByte = (byte)Result; |
|
124 _HasPeekByte = true; |
|
125 } |
|
126 return Result; |
|
127 } |
|
128 } |
|
129 |
|
130 public int WriteBufferSize { |
|
131 get { return Socket.SendBufferSize; } |
|
132 set { Socket.SendBufferSize = value; } |
|
133 } |
|
134 |
|
135 public int ReadBufferSize { |
|
136 get { return Socket.ReceiveBufferSize; } |
|
137 set { Socket.ReceiveBufferSize = value; } |
|
138 } |
|
139 |
|
140 public override bool CanRead { |
|
141 get { return Socket.Connected && (Blocking || (Socket.Available > 0)); } |
|
142 } |
|
143 |
|
144 public override bool CanSeek { |
|
145 get { return false; } |
|
146 } |
|
147 |
|
148 public override bool CanWrite { |
|
149 get { return Socket.Connected; } |
|
150 } |
|
151 |
|
152 public override void Flush() { |
|
153 //Do nothing |
|
154 //_Socket.NoDelay = true; |
|
155 } |
|
156 |
|
157 public override long Length { |
|
158 get { |
|
159 throw new NotSupportedException(); |
|
160 } |
|
161 } |
|
162 |
|
163 public override long Position { |
|
164 get { |
|
165 throw new NotSupportedException(); |
|
166 } |
|
167 set { |
|
168 throw new NotSupportedException(); |
|
169 } |
|
170 } |
|
171 |
|
172 public override long Seek(long offset, SeekOrigin origin) { |
|
173 throw new NotSupportedException(); |
|
174 } |
|
175 |
|
176 public override void SetLength(long value) { |
|
177 throw new NotSupportedException(); |
|
178 } |
|
179 |
|
180 public override void Write(byte[] buffer, int offset, int size) { |
|
181 int left = size; |
|
182 if (_Socket == null) throw new ObjectDisposedException("socket"); |
|
183 try { |
|
184 while (left > 0) { |
|
185 int sent = _Socket.Send(buffer, offset, left, 0); |
|
186 left -= sent; |
|
187 offset += sent; |
|
188 } |
|
189 } catch (SocketException ex) { |
|
190 switch (ex.SocketErrorCode) { |
|
191 case SocketError.WouldBlock: |
|
192 _Socket.Blocking = _Blocking; |
|
193 throw new TimeoutException("The send operation would block", ex); |
|
194 case SocketError.TimedOut: |
|
195 throw new TimeoutException("The send operation timed out", ex); |
|
196 case SocketError.ConnectionReset: |
|
197 case SocketError.Disconnecting: |
|
198 case SocketError.NetworkDown: |
|
199 case SocketError.NetworkReset: |
|
200 case SocketError.NetworkUnreachable: |
|
201 case SocketError.NotConnected: |
|
202 Close(); |
|
203 throw new SocketException((int)ex.SocketErrorCode); |
|
204 default: |
|
205 throw new SocketException((int)ex.SocketErrorCode); |
|
206 } |
|
207 } |
|
208 _BytesWritten += (ulong)size; |
|
209 Interlocked.Add(ref _totalBytesWritten, (long)size); |
|
210 } |
|
211 |
|
212 public override void Close() { |
|
213 System.Net.Sockets.Socket s = Interlocked.Exchange(ref _Socket, null); |
|
214 try { |
|
215 if (s != null) { |
|
216 try { |
|
217 if (s.Connected) s.Shutdown(SocketShutdown.Both); |
|
218 } catch { } |
|
219 s.Close(); |
|
220 } |
|
221 } finally { |
|
222 base.Close(); |
|
223 if (Closed != null) Closed(this, new EventArgs()); |
|
224 } |
|
225 } |
|
226 |
|
227 public bool Connected { |
|
228 get { |
|
229 if (Socket == null) return false; |
|
230 if (Socket.Connected) return true; |
|
231 Close(); |
|
232 return false; |
|
233 } |
|
234 } |
|
235 |
|
236 public object Tag { get; set; } |
|
237 |
|
238 public ulong BytesWritten { get { return _BytesWritten; } } |
|
239 public ulong BytesRead { get { return _BytesRead; } } |
|
240 public TimeSpan Age { get { return DateTime.Now.Subtract(_StartTime); } } |
|
241 public EndPoint RemoteEndPoint { |
|
242 get { |
|
243 if (_Socket == null || !_Socket.Connected) return null; |
|
244 try { |
|
245 return _Socket.RemoteEndPoint; |
|
246 } catch (SocketException) { |
|
247 return null; |
|
248 } |
|
249 } |
|
250 } |
|
251 //public Object Proxy { get { return null; } } |
|
252 Object INetworkConnection.Handler { get { return Tag; } } |
|
253 } |
|
254 } |