Mercurial > hg > ucis.core
comparison Net/TCPStream.cs @ 0:3ab940a0c7a0
Initial commit
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Tue, 11 Sep 2012 16:28:53 +0200 |
parents | |
children | d0117dc37c34 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3ab940a0c7a0 |
---|---|
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 } |