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