From 3e31981eeed1fcc2544f70cba881cfe5d1d07b96 Mon Sep 17 00:00:00 2001 From: Lucas Bajolet Date: Fri, 2 May 2014 15:04:58 -0400 Subject: [PATCH] lib/socket: Socket now subclass of BufferedIStream and OStream Signed-off-by: Lucas Bajolet --- examples/socket_client.nit | 17 ++++---- examples/socket_server.nit | 7 ++-- lib/mpd.nit | 8 ++-- lib/socket/socket.nit | 99 +++++++++++++++++++++++++------------------- 4 files changed, 73 insertions(+), 58 deletions(-) diff --git a/examples/socket_client.nit b/examples/socket_client.nit index d7659e7..d9ac5ff 100644 --- a/examples/socket_client.nit +++ b/examples/socket_client.nit @@ -26,10 +26,13 @@ end var s = new Socket.stream_with_host(args[0], args[1].to_i) print "[HOST ADDRESS] : {s.address}" -print "[HOST] : {s.host.as(not null)}" -print "[PORT] : {s.port.to_s}" -print "Connecting ... {s.connect.to_s}" -print "Writing ... {s.write("Hello server !").to_s}" -print "[Response from server] : {s.read.to_s}" -print "Closing ... {s.close.to_s}" - +print "[HOST] : {s.host}" +print "[PORT] : {s.port}" +print "Connecting ... {s.connected}" +if s.connected then + print "Writing ... Hello server !" + s.write("Hello server !") + print "[Response from server] : {s.read(100)}" + print "Closing ..." + s.close +end diff --git a/examples/socket_server.nit b/examples/socket_server.nit index 9df9d79..8754ce2 100644 --- a/examples/socket_server.nit +++ b/examples/socket_server.nit @@ -26,8 +26,6 @@ end var socket = new Socket.stream_with_port(args[0].to_i) print "[PORT] : {socket.port.to_s}" -print "Binding ... {socket.bind.to_s}" -print "Listening ... {socket.listen(3).to_s}" var clients = new Array[Socket] var max = socket @@ -45,9 +43,10 @@ loop if fs.readset.is_set(socket) then var ns = socket.accept print "Accepting {ns.address} ... " - print "[Message from {ns.address}] : {ns.read}" + print "[Message from {ns.address}] : {ns.read(100)}" ns.write("Goodbye client.") - print "Closing {ns.address} ... {ns.close.to_s}" + print "Closing {ns.address} ..." + ns.close end end diff --git a/lib/mpd.nit b/lib/mpd.nit index fd8fa5d..cf9b677 100644 --- a/lib/mpd.nit +++ b/lib/mpd.nit @@ -39,7 +39,7 @@ class MPDConnection sys.nanosleep(0,5000) - var rep = p.read + var rep = p.read(1024) assert not rep.is_empty if not rep.has_prefix("OK") then print "MPD responded {rep}" @@ -61,7 +61,7 @@ class MPDConnection socket.write(msg) sys.nanosleep(0,5000) - var rep = socket.read + var rep = socket.read(1024) if not rep.has_prefix("OK") then print "Error: MPD responded {rep}" socket.close @@ -82,7 +82,7 @@ class MPDConnection # get current status socket.write("status\n") - var rep = socket.read + var rep = socket.read(1024) for l in rep.split_with("\n") do var words = l.split_with(" ") if words.length > 1 then @@ -153,7 +153,7 @@ class MPDConnection var time: nullable Int = null socket.write("currentsong\n") - var rep = socket.read + var rep = socket.read(1024) for l in rep.split_with("\n") do var words = l.split_with(" ") if words.length > 1 then diff --git a/lib/socket/socket.nit b/lib/socket/socket.nit index 8919dbc..4a5129e 100644 --- a/lib/socket/socket.nit +++ b/lib/socket/socket.nit @@ -21,6 +21,9 @@ import socket_c # Portal for communication between two machines class Socket + super BufferedIStream + super OStream + # IPv4 address the socket is connected to # Formatted as xxx.xxx.xxx.xxx var address: String @@ -38,18 +41,16 @@ class Socket # Underlying C socket private var addrin: FFSocketAddrIn - # Guard for errors - # If the socket could not be created or if the socket was destroyed - # before a call needing the socket was made - # this flag will be set to false. - var still_alive = true # Note : HUGE SUCCESS + redef var end_reached = false # Creates a socket connection to host `thost` on port `port` init stream_with_host(thost: String, tport: Int) do + _buffer = new FlatBuffer + _buffer_pos = 0 socket = new FFSocket.socket( new FFSocketAddressFamilies.af_inet, new FFSocketTypes.sock_stream, new FFSocketProtocolFamilies.pf_null ) if socket.address_is_null then - still_alive = false + end_reached = true return end socket.setsockopt(new FFSocketOptLevels.socket, new FFSocketOptNames.reuseaddr, 1) @@ -58,14 +59,17 @@ class Socket address = addrin.address host = hostname.h_name port = addrin.port + if not end_reached then end_reached = not connect end # Creates a server socket on port `tport` init stream_with_port(tport: Int) do + _buffer = new FlatBuffer + _buffer_pos = 0 socket = new FFSocket.socket( new FFSocketAddressFamilies.af_inet, new FFSocketTypes.sock_stream, new FFSocketProtocolFamilies.pf_null ) if socket.address_is_null then - still_alive = false + end_reached = true return end socket.setsockopt(new FFSocketOptLevels.socket, new FFSocketOptNames.reuseaddr, 1) @@ -73,11 +77,15 @@ class Socket address = addrin.address port = addrin.port host = null + bind + listen(max) end # Creates a client socket, this is meant to be used by accept only private init primitive_init(h: FFSocketAcceptResult) do + _buffer = new FlatBuffer + _buffer_pos = 0 socket = h.socket addrin = h.addrIn address = addrin.address @@ -102,12 +110,10 @@ class Socket # fun ready_to_read(timeout: Int): Bool do - if not still_alive then return false + if _buffer_pos < _buffer.length then return true + if eof then return false var events = new Array[FFSocketPollValues] events.push(new FFSocketPollValues.pollin) - events.push(new FFSocketPollValues.pollrdnorm) - events.push(new FFSocketPollValues.pollpri) - events.push(new FFSocketPollValues.pollrdband) return poll_in(events, timeout).length != 0 end @@ -115,64 +121,71 @@ class Socket # fun connected: Bool do - if not still_alive then return false + if eof then return false var events = new Array[FFSocketPollValues] events.push(new FFSocketPollValues.pollhup) events.push(new FFSocketPollValues.pollerr) return poll_in(events, 0).length == 0 end + redef fun is_writable do return not end_reached + # Establishes a connection to socket addrin # - # REQUIRES : self.still_alive - fun connect: Bool do - assert still_alive + # REQUIRES : not self.end_reached + private fun connect: Bool + do + assert not end_reached return socket.connect(addrin) >= 0 end - # Write a message to connected socket - # - # Returns `true` if the `msg` was sent, `false` otherwise - # - # If not socket.sill_alive, false will be returned - fun write(msg: String): Bool do - if not still_alive then return false - return socket.write(msg) >= 0 + # If socket.end_reached, nothing will happen + redef fun write(msg: Text) + do + if end_reached then return + socket.write(msg.to_s) end - # Read from connected socket - # - # If the socket is disconnected, an empty string will be returned - fun read: String do - if not still_alive then return "" - return socket.read + fun write_ln(msg: Text) + do + if end_reached then return + write(msg.to_s) + write("\n") end - # Close connection - # - # Returns : `true` if the close was successful, `false` otherwise - fun close: Bool do - if not still_alive then return true + redef fun fill_buffer + do + _buffer.clear + _buffer_pos = 0 + if not connected then return + var read = socket.read + if read.length == 0 then + close + end_reached = true + end + _buffer.append(read) + end + + redef fun close do + if end_reached then return if socket.close >= 0 then - still_alive = false - return true + end_reached = true end - return false end # Associates the socket to a local address and port # # Returns : `true` if the socket could be bound, `false` otherwise - fun bind: Bool do - if not still_alive then return false + private fun bind: Bool do + if end_reached then return false return socket.bind(addrin) >= 0 end # Sets the socket as ready to accept incoming connections, `size` is the maximum number of queued clients # # Returns : `true` if the socket could be set, `false` otherwise - fun listen(size: Int): Bool do - if not still_alive then return false + private fun listen(size: Int): Bool do + if end_reached then return false return socket.listen(size) >= 0 end @@ -181,9 +194,9 @@ class Socket # # Returns : the socket for communication with the client # - # REQUIRES : self.still_alive + # REQUIRES : not self.end_reached fun accept: Socket do - assert still_alive + assert not end_reached return new Socket.primitive_init(socket.accept) end -- 1.7.9.5