TcpClient.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // System.Net.Sockets.TcpClient.cs
  2. //
  3. // Author:
  4. // Phillip Pearson ([email protected])
  5. //
  6. // Copyright (C) 2001, Phillip Pearson
  7. // http://www.myelin.co.nz
  8. //
  9. // NB: This is untested (probably buggy) code - take care if using it
  10. using System;
  11. using System.Net;
  12. namespace System.Net.Sockets
  13. {
  14. /// <remarks>
  15. /// A slightly more abstracted way to create an
  16. /// outgoing network connections than a Socket.
  17. /// </remarks>
  18. public class TcpClient : IDisposable
  19. {
  20. // private data
  21. private NetworkStream stream;
  22. private bool active;
  23. private Socket client;
  24. private bool disposed = false;
  25. // constructor
  26. /// <summary>
  27. /// Some code that is shared between the constructors.
  28. /// </summary>
  29. private void Init ()
  30. {
  31. active = false;
  32. client = new Socket(AddressFamily.InterNetwork,
  33. SocketType.Stream, ProtocolType.Tcp);
  34. }
  35. /// <summary>
  36. /// Constructs a new TcpClient with no connection set up
  37. /// </summary>
  38. public TcpClient ()
  39. {
  40. Init();
  41. client.Bind(new IPEndPoint(IPAddress.Any, 0));
  42. }
  43. /// <summary>
  44. /// Constructs a new TcpClient with a specified local endpoint.
  45. /// Use this if you want to have your connections originating
  46. /// from a certain port, or a certain IP (on a multi homed
  47. /// system).
  48. /// </summary>
  49. /// <param name="local_end_point">The aforementioned local endpoint</param>
  50. public TcpClient (IPEndPoint local_end_point)
  51. {
  52. Init();
  53. client.Bind(local_end_point);
  54. }
  55. /// <summary>
  56. /// Constructs a new TcpClient and connects to a specified
  57. /// host on a specified port. A quick way to set up a network
  58. /// connection.
  59. /// </summary>
  60. /// <param name="hostname">The host to connect to, e.g.
  61. /// 192.168.0.201 or www.myelin.co.nz</param>
  62. /// <param name="port">The port to connect to, e.g. 80 for HTTP</param>
  63. public TcpClient (string hostname, int port)
  64. {
  65. Init();
  66. client.Bind(new IPEndPoint(IPAddress.Any, 0));
  67. Connect(hostname, port);
  68. }
  69. /// <summary>
  70. /// A flag that is 'true' if the TcpClient has an active connection
  71. /// </summary>
  72. protected bool Active
  73. {
  74. get { return active; }
  75. set { active = value; }
  76. }
  77. /// <summary>
  78. /// The socket that all network comms passes through
  79. /// </summary>
  80. [MonoTODO]
  81. protected Socket Client
  82. {
  83. get { return client; }
  84. set { client = value; } //TODO: should we be able to set the socket like this?
  85. }
  86. /// <summary>
  87. /// Internal function to allow TcpListener.AcceptTcpClient
  88. /// to work (it needs to be able to set protected property
  89. /// 'Client')
  90. /// </summary>
  91. /// <param name="s"></param>
  92. internal void SetTcpClient (Socket s)
  93. {
  94. Client = s; // client or Client? They are the same at the moment
  95. }
  96. /// <summary>
  97. /// If set, the socket will remain open after it has been
  98. /// instructed to close, in order to send data that remains
  99. /// in the buffer.
  100. /// </summary>
  101. public LingerOption LingerState
  102. {
  103. get {
  104. return (LingerOption)client.GetSocketOption(
  105. SocketOptionLevel.Socket,
  106. SocketOptionName.Linger);
  107. }
  108. set {
  109. client.SetSocketOption(
  110. SocketOptionLevel.Socket,
  111. SocketOptionName.Linger, value);
  112. }
  113. }
  114. /// <summary>
  115. /// <p>If set, outbound data will be sent at once rather than collected
  116. /// until enough is available to fill a packet.</p>
  117. ///
  118. /// <p>This is the TCP_NODELAY sockopt from BSD sockets and WinSock.
  119. /// For more information, look up the Nagle algorithm.</p>
  120. /// </summary>
  121. public bool NoDelay
  122. {
  123. get {
  124. return (bool)client.GetSocketOption(
  125. SocketOptionLevel.Socket,
  126. SocketOptionName.NoDelay);
  127. }
  128. set {
  129. client.SetSocketOption(
  130. SocketOptionLevel.Socket,
  131. SocketOptionName.NoDelay, value);
  132. }
  133. }
  134. /// <summary>
  135. /// How big the receive buffer is (from the connection socket)
  136. /// </summary>
  137. public int ReceiveBufferSize
  138. {
  139. get {
  140. return (int)client.GetSocketOption(
  141. SocketOptionLevel.Socket,
  142. SocketOptionName.ReceiveBuffer);
  143. }
  144. set {
  145. client.SetSocketOption(
  146. SocketOptionLevel.Socket,
  147. SocketOptionName.ReceiveBuffer, value);
  148. }
  149. }
  150. /// <summary>
  151. /// How long before the socket will time out on a
  152. /// Receive() call
  153. /// </summary>
  154. public int ReceiveTimeout
  155. {
  156. get {
  157. return (int)client.GetSocketOption(
  158. SocketOptionLevel.Socket,
  159. SocketOptionName.ReceiveTimeout);
  160. }
  161. set {
  162. client.SetSocketOption(
  163. SocketOptionLevel.Socket,
  164. SocketOptionName.ReceiveTimeout, value);
  165. }
  166. }
  167. /// <summary>
  168. /// How big the send buffer is (from the connection socket)
  169. /// </summary>
  170. public int SendBufferSize
  171. {
  172. get {
  173. return (int)client.GetSocketOption(
  174. SocketOptionLevel.Socket,
  175. SocketOptionName.SendBuffer);
  176. }
  177. set {
  178. client.SetSocketOption(
  179. SocketOptionLevel.Socket,
  180. SocketOptionName.SendBuffer, value);
  181. }
  182. }
  183. /// <summary>
  184. /// How long before the socket will time out on a
  185. /// Send() call
  186. /// </summary>
  187. public int SendTimeout
  188. {
  189. get {
  190. return (int)client.GetSocketOption(
  191. SocketOptionLevel.Socket,
  192. SocketOptionName.SendTimeout);
  193. }
  194. set {
  195. client.SetSocketOption(
  196. SocketOptionLevel.Socket,
  197. SocketOptionName.SendTimeout, value);
  198. }
  199. }
  200. // methods
  201. /// <summary>
  202. /// Closes the socket and disposes of all managed resources.
  203. ///
  204. /// Throws SocketException if something goes wrong while
  205. /// closing the socket.
  206. /// </summary>
  207. public void Close ()
  208. {
  209. Dispose(true);
  210. }
  211. /// <summary>
  212. /// Connects to a specified remote endpoint
  213. ///
  214. /// Throws SocketException if something goes wrong while
  215. /// connecting.
  216. /// </summary>
  217. /// <param name="remote_end_point">The aforementioned endpoint</param>
  218. public void Connect (IPEndPoint remote_end_point)
  219. {
  220. client.Connect(remote_end_point);
  221. stream = new NetworkStream(client, true);
  222. active = true;
  223. }
  224. /// <summary>
  225. /// Connects to an IP address on a port
  226. ///
  227. /// Throws SocketException if something goes wrong while
  228. /// connecting.
  229. /// </summary>
  230. /// <param name="address">The IP address (get it from Dns.GetHostByName)</param>
  231. /// <param name="port">The port to connect to, e.g. 80 for HTTP</param>
  232. public void Connect (IPAddress address, int port)
  233. {
  234. Connect(new IPEndPoint(address, port));
  235. }
  236. /// <summary>
  237. /// Resolves a fully qualified domain name to an IP address
  238. /// and connects to it on a specified port
  239. ///
  240. /// Throws SocketException if something goes wrong while
  241. /// connecting.
  242. /// </summary>
  243. /// <param name="hostname">The hostname, e.g. www.myelin.co.nz</param>
  244. /// <param name="port">The port, e.g. 80 for HTTP</param>
  245. [MonoTODO]
  246. public void Connect (string hostname, int port)
  247. {
  248. IPHostEntry host = Dns.GetHostByName(hostname);
  249. /* TODO: This will connect to the first IP address returned
  250. from GetHostByName. Is that right? */
  251. Connect(new IPEndPoint(host.AddressList[0], port));
  252. }
  253. /// <summary>
  254. /// Gets rid of all managed resources
  255. /// </summary>
  256. public void Dispose()
  257. {
  258. Dispose(true);
  259. GC.SuppressFinalize(this);
  260. }
  261. /// <summary>
  262. /// Gets rid of all unmanaged resources
  263. /// </summary>
  264. /// <param name="disposing">If this is true, it gets rid of all
  265. /// managed resources as well</param>
  266. protected virtual void Dispose (bool disposing)
  267. {
  268. if (disposed == false) {
  269. if (active) {
  270. // This closes the socket as well, as the NetworkStream
  271. // owns the socket.
  272. stream.Close();
  273. active = false;
  274. }
  275. disposed = true;
  276. }
  277. }
  278. /// <summary>
  279. /// Destructor - just calls Dispose()
  280. /// </summary>
  281. ~TcpClient ()
  282. {
  283. Dispose(false);
  284. }
  285. /// <returns>A NetworkStream object connected to the
  286. /// connection socket</returns>
  287. public NetworkStream GetStream()
  288. {
  289. return stream;
  290. }
  291. }
  292. }