Socket.hx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package sys.net;
  2. import cs.system.net.IPEndPoint;
  3. import cs.system.net.sockets.AddressFamily;
  4. import cs.system.net.sockets.NetworkStream;
  5. import cs.system.net.sockets.ProtocolType;
  6. import cs.system.net.sockets.SocketFlags;
  7. import cs.system.net.sockets.SocketShutdown;
  8. import cs.system.net.sockets.SocketType;
  9. import cs.system.threading.Thread;
  10. import haxe.io.Bytes;
  11. import haxe.io.Error;
  12. import haxe.io.Input;
  13. import haxe.io.Output;
  14. /**
  15. A TCP socket class : allow you to both connect to a given server and exchange messages or start your own server and wait for connections.
  16. **/
  17. @:coreapi
  18. class Socket {
  19. private var sock : cs.system.net.sockets.Socket = null;
  20. /**
  21. The stream on which you can read available data. By default the stream is blocking until the requested data is available,
  22. use [setBlocking(false)] or [setTimeout] to prevent infinite waiting.
  23. **/
  24. public var input(default,null) : haxe.io.Input;
  25. /**
  26. The stream on which you can send data. Please note that in case the output buffer you will block while writing the data, use [setBlocking(false)] or [setTimeout] to prevent that.
  27. **/
  28. public var output(default,null) : haxe.io.Output;
  29. /**
  30. A custom value that can be associated with the socket. Can be used to retreive your custom infos after a [select].
  31. ***/
  32. public var custom : Dynamic;
  33. /**
  34. Creates a new unconnected socket.
  35. **/
  36. public function new() : Void {
  37. sock = new cs.system.net.sockets.Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
  38. sock.Blocking = true;
  39. }
  40. /**
  41. Closes the socket : make sure to properly close all your sockets or you will crash when you run out of file descriptors.
  42. **/
  43. public function close() : Void {
  44. sock.Close();
  45. input = null;
  46. output = null;
  47. }
  48. /**
  49. Read the whole data available on the socket.
  50. **/
  51. public function read() : String {
  52. return input.readAll().toString();
  53. }
  54. /**
  55. Write the whole data to the socket output.
  56. **/
  57. public function write( content : String ) : Void {
  58. output.writeString( content );
  59. }
  60. /**
  61. Connect to the given server host/port. Throw an exception in case we couldn't sucessfully connect.
  62. **/
  63. public function connect( host : Host, port : Int ) : Void {
  64. sock.Connect( host.ipAddress, port );
  65. if (sock.Connected) {
  66. this.output = new cs.io.NativeOutput( new NetworkStream(sock) );
  67. this.input = new cs.io.NativeInput( new NetworkStream(sock) );
  68. } else {
  69. throw "Connection failed.";
  70. }
  71. }
  72. /**
  73. Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use [accept()] to accept incoming connections.
  74. **/
  75. public function listen( connections : Int ) : Void {
  76. sock.Listen( connections );
  77. }
  78. /**
  79. Shutdown the socket, either for reading or writing.
  80. **/
  81. public function shutdown( read : Bool, write : Bool ) : Void {
  82. if ( read && write ) {
  83. sock.Shutdown( SocketShutdown.Both );
  84. input = null;
  85. output = null;
  86. } else if ( read ) {
  87. sock.Shutdown( SocketShutdown.Receive );
  88. input = null;
  89. } else if ( write ) {
  90. sock.Shutdown( SocketShutdown.Send );
  91. output = null;
  92. }
  93. }
  94. /**
  95. Bind the socket to the given host/port so it can afterwards listen for connections there.
  96. **/
  97. public function bind( host : Host, port : Int ) : Void {
  98. sock = new cs.system.net.sockets.Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
  99. sock.Bind( new IPEndPoint(host.ipAddress, port) );
  100. }
  101. /**
  102. Accept a new connected client. This will return a connected socket on which you can read/write some data.
  103. **/
  104. public function accept() : Socket {
  105. var r = new Socket();
  106. r.sock = sock.Accept();
  107. r.output = new cs.io.NativeOutput( new NetworkStream(r.sock) );
  108. r.input = new cs.io.NativeInput( new NetworkStream(r.sock) );
  109. return r;
  110. }
  111. /**
  112. Return the informations about the other side of a connected socket.
  113. **/
  114. public function peer() : { host : Host, port : Int } {
  115. var remoteIP = cast(sock.RemoteEndPoint, IPEndPoint);
  116. return { host: new Host(remoteIP.Address.ToString()), port: remoteIP.Port };
  117. }
  118. /**
  119. Return the informations about our side of a connected socket.
  120. **/
  121. public function host() : { host : Host, port : Int } {
  122. var localIP = cast(sock.LocalEndPoint, IPEndPoint);
  123. return { host: new Host(localIP.Address.ToString()), port: localIP.Port };
  124. }
  125. /**
  126. Gives a timeout after which blocking socket operations (such as reading and writing) will abort and throw an exception.
  127. **/
  128. public function setTimeout( timeout : Float ) : Void {
  129. sock.ReceiveTimeout = sock.SendTimeout = Math.round(timeout * 1000);
  130. }
  131. /**
  132. Block until some data is available for read on the socket.
  133. **/
  134. public function waitForRead() : Void {
  135. var end = Date.now().getTime() + ((sock.ReceiveTimeout <= 0) ? Math.POSITIVE_INFINITY : sock.ReceiveTimeout);
  136. while ( sock.Available == 0 && Date.now().getTime() < end) {
  137. Thread.Sleep(5);
  138. }
  139. }
  140. /**
  141. Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediatly by throwing a haxe.io.Error.Blocking value.
  142. **/
  143. public function setBlocking( b : Bool ) : Void {
  144. sock.Blocking = b;
  145. }
  146. /**
  147. Allows the socket to immediatly send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
  148. **/
  149. public function setFastSend( b : Bool ) : Void {
  150. sock.NoDelay = b;
  151. }
  152. /**
  153. Wait until one of the sockets groups is ready for the given operation :
  154. [read] contains sockets on which we want to wait for available data to be read,
  155. [write] contains sockets on which we want to wait until we are allowed to write some data to their output buffers,
  156. [others] contains sockets on which we want to wait for exceptional conditions.
  157. [select] will block until one of the condition is met, in which case it will return the sockets for which the condition was true.
  158. In case a [timeout] (in seconds) is specified, select might wait at worse until the timeout expires.
  159. **/
  160. static public function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, ?timeout : Float) : { read: Array<Socket>,write: Array<Socket>,others: Array<Socket> } {
  161. throw "Not implemented yet.";
  162. return null;
  163. }
  164. }