Success Comunicating With External App Using TCPSocket

Thanks to @DanRathbun’s help I’ve managed to implement a much cleaner solution using the Http class rather than a ruby socket.

Works like a charm!!!

Here is the ruby class I created.
class Communicator  
  
  def initialize(connectionstring)
    @connectionstring = connectionstring
    @connected = false
    start_listener
  end
  
  def start_listener
    @connected = true
    @listener = Sketchup::Http::Request.new(@connectionstring, Sketchup::Http::GET)
    @listener.headers = {'Listen'=>'SketchUp'}
    @listener.start do |request, response|
      puts response.body
      if (response.body == "")
        puts "Lost connection or couldn't connect to server."
        close
      else
        start_listener
      end     
    end
  end
  
  def send(msg,key = "msg")
    if key == "Listen" then key == "msg" end #don't let users start a listen by mistake
    
    @request = Sketchup::Http::Request.new(@connectionstring, Sketchup::Http::GET)
    @request.headers = {key=>msg}
    @request.start do |request, response|
      
      #puts "body: #{response.body}"
    end
  end
  
  def close()
    if @request then @request.cancel end
    if @listener then @listener.cancel end
    @connected = false
  end  
  
  def isconnected?
    return @connected
  end
  
end

To start the connection simply use the class like this:

com = Communicator.new("http://localhost:11235/")

To send a message simply do this:

com.send 'My message to server.'

Messages from server are out put to console as they are received.

Here is the C# class if anyone is interested.
 public class WebServer
    {
        public EventHandler OnDataAvailable;
        private readonly HttpListener _listener = new HttpListener();
        private Stack<string> sendmsgs = new Stack<string>();
        public TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();

        public WebServer(string host)
        {
            if (!HttpListener.IsSupported)
                throw new NotSupportedException(
                    "Needs Windows XP SP2, Server 2003 or later.");
            _listener.Prefixes.Add(host);
            _listener.Start();
        }

        public void Run()
        {
            ThreadPool.QueueUserWorkItem((o) =>
            {
                try
                {
                    while (_listener.IsListening)
                    {
                        ThreadPool.QueueUserWorkItem((c) =>
                        {
                            var ctx = c as HttpListenerContext;
                            try
                            {
                                string rstr = "";
                                if (ctx.Request.Headers.AllKeys[0] == "Listen")
                                {
                                    while (_listener.IsListening)
                                    {
                                        if (sendmsgs.Count > 0)
                                        {
                                            rstr = sendmsgs.Pop();
                                            break;
                                        }
                                    }
                                }
                                else rstr = RecieveMessage(ctx.Request);
                                byte[] buf = Encoding.UTF8.GetBytes(rstr);
                                ctx.Response.ContentLength64 = buf.Length;
                                ctx.Response.OutputStream.Write(buf, 0, buf.Length);
                            }
                            catch {  } // suppress any exceptions
                            finally
                            {
                                // always close the stream
                                ctx.Response.OutputStream.Close();
                            }
                        }, _listener.GetContext());
                    }
                }
                catch { } // suppress any exceptions
            });
        }

        public void SendMsg(string msg)
        {
            sendmsgs.Push(msg);
        }

        private string RecieveMessage(HttpListenerRequest request)
        {
            string msg = request.Headers[request.Headers.AllKeys[0]].ToString();
            Task task = new Task(() => OnDataAvailable?.Invoke(new string[] { request.Headers.AllKeys[0], msg}, EventArgs.Empty));
            task.Start(scheduler);
            task.Wait();
            return "read";
        }

        public void Stop()
        {
            _listener.Stop();
            _listener.Close();
        }
    }
1 Like