0

The TCP server I am hitting (trying to use the built in node TLS Socket) expects a handshaking process of send/receives in a certain order (send, on receive of success, send more messages, on success, send more, etc). The receive messages does not have anything to let me know which send it is responding to, so I am not able to easily use the streaming nature of the built in TCP Node library.

Any ideas of what the best way to handle this case in Node?

example (python), and this is example of the process:

    s.send("hello")
    s.send("send this 1")
    reply = s.recv()
    message = reply[0]
    if message == OK:
        print('Got OK for hello')
        s.send("send this 2")
        reply = s.recv()
        message = reply[0]
        if message == OK:
          print('Got it')
    else:
        raise Exception('Failed to send hello')
CSharpAtl
  • 7,374
  • 8
  • 39
  • 53
  • How do other clients of this service handle this? Do you have any code to share? – Jake Holzinger Jul 18 '19 at 21:26
  • We'd have to know more about the send/receive protocol you're trying to implement. Since TCP is low level, if your other side is TCP based (which apparently it is), then there is certainly a way to code this side, but we can't help you without knowing what the protocol is. What is the server you're connecting to? What protocol does it use? – jfriend00 Jul 18 '19 at 21:30
  • 1
    FYI, the built-in TCP library works the way TCP works (nothing in particular to do with node.js). If you need to implement a protocol on top of TCP and want help with that, you will have to show us what the protocol is and we can help with how you would implement that in node.js. So, right now, this question is incomplete. It doesn't contain enough info for us to be able to help you. Perhaps what you need is a state machine. – jfriend00 Jul 18 '19 at 21:52
  • yes, there is a protocol, and that is what I am trying to figure out how to do with the streaming on the socket. There is a protocol...send, then receive, if ok, then send more....etc. – CSharpAtl Jul 18 '19 at 22:00
  • Sounds like you need a higher level protocol. We can't really help you choose one without knowing more about what you're trying to do. – Brad Jul 18 '19 at 22:09
  • I added an example of a protocol that i am trying to do. Are there some libraries out there that will allow for me to send, then wait on receive, then send more ? – CSharpAtl Jul 18 '19 at 22:12
  • You will need to build your own state machine so that when bytes arrive, you can look at the current state and decide what to do with the bytes that just arrived. That's how you program something like this with non-blocking, asynchronous I/O (as in node.js). When you send something that is expecting a response, you set the state on the state machine accordingly. A socket would have it's own state machine, which in Javascript can be an object stored in a custom property on the `socket` object itself. Any more detailed direction would need to know the exact protocol you're trying to implement. – jfriend00 Jul 18 '19 at 22:17
  • @jfriend00, I added a small example in the question. – CSharpAtl Jul 18 '19 at 22:21
  • 1
    The psuedo code is nice, but it's still not clear how the client and server are expected to communicate. Are messages prefixed with the length of data? Are they delimited by a special character? You claim this is a send-recv protocol, but the first thing you do is send two consecutive messages. What is the expectation here? Is it one request per response or are we missing additional details? – Jake Holzinger Jul 18 '19 at 23:02
  • I understand how TCP works. I am just asking if there is an easy way to do sends and blocking receives without having to track everything. My code was just used to show what I want...send, then wait on receive, then maybe another send, then another receive. I know it is not functioning code. – CSharpAtl Jul 19 '19 at 14:24

1 Answers1

1

When you have non-blocking I/O and you want to do something such as send data, read specific response from that send you need to set up some appropriate state so that when the next set of data come in, you know exactly what it belongs to and therefore you know what to do with it.

There are a number of ways to do that I can think of:

  1. Create a general purpose state machine where you send data and read data and whenever you read data, you can tell what state the socket is in and therefore what you are supposed to do with the data you read.

  2. Create a temporal set of listeners where you send data, then add a temporal listener (you can use .once()) for incoming data that is specially designed to process it the way you are expecting this response to be. When the data arrives, you make sure that listener is removed.

Your pseudo-code example does not show enough info for anyone to make a more concrete suggestion. TCP, by its very nature is stream driven. It doesn't have any built-in sense of a message or a packet. So, what you show doesn't even show the most basic level of any TCP protocol which is how to know when you've received an entire response.

Even your reply = s.recv() shown in some other language isn't practical in TCP (no matter the language) because s.recv() needs to know when it's got a complete message/chunk/whatever it is that you're waiting to receive. TCP delivers data in order sent, but does not have any sense of a particular packet of information that goes together. You have to supply that on top of the TCP layer. Common techniques used for delineating messages are :

  1. Some message delimiter (like a carriage return or line feed or a zero byte or some other tag - all of which are known not to occur inside the message itself)
  2. Sending a length first so the reader knows exactly how many bytes to read.
  3. Wrapping messages in some sort of container where the start and end of the container are made clear by the structure of the container (note options 1 and 2 above are just specific implementations of such a container). For example, the webSocket protocol uses a very specific container model that includes some length data and other info.

I was thinking of showing you an example using socket.once('data', ...) to listen for the specific response, but even that won't work properly without knowing how to delineate an incoming message so one knows when you've received a complete incoming message.

So, one of your first steps would be to implement a layer on top of TCP that reads data and knows how to break it into discrete messages (knows both when a complete message has arrived and how to break up multiple messages that might be arriving) and then emits your own event on the socket when a whole message has arrived. Then, and only then, can you start to implement the rest of your state machine using the above techniques.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thank you for your answer. I completely understand the chunking/end of message needed. I was just trying to know if there was a way in Node to easily do a send then wait on a receive, then do another send based on the received data. It sounds like there is not one. – CSharpAtl Jul 19 '19 at 14:02
  • @CSharpAtl - If you had the other things in place (to define messages), then you could probably use buffering, promises and `async/await` to write something like you want. – jfriend00 Jul 19 '19 at 15:05
  • What do you mean "define messages"? What some of the receives was a single byte that represents "success"? Without tracking every step in the `on.("data")` handler (as some are many steps, like sending files and with that file lengths), how do I do it? – CSharpAtl Jul 19 '19 at 16:08
  • By "define messages", I mean knowing exactly what you're waiting for as the response so you know when you have a full response. Since you've shared NONE of the actual protocol you're dealing with, all we can do is speak in generalities. We can't offer any real code because we don't know how the protocol works. Without more information about the specific protocol, I have nothing more to add and am not feeling productive with further interaction on the topic. With promises and `async/await` and full knowledge of the protocol, what you want can likely be done. – jfriend00 Jul 19 '19 at 16:12
  • ok, I am not sure why the exact protocol is needed, as I am just talking in general. A custom protocol that sends bytes and receives bytes, those received bytes are checked, and if what is expected was received, other sends would occur. Thank you all for you information, but from what I am reading it is something I will have to track myself. – CSharpAtl Jul 19 '19 at 17:25