At what point during Java NIO Socket is there a socket connection on the server or client side, ready to send data?

I'm working with Java NIO and this is my first time setting up a working TCP connection (I've only done UDP up to this point and a simple TCP test program a long time ago).

At the moment, I'm not sure when I can reliably start sending data to clients so that they know there is an active connection on the other end (if something doesn't go wrong).


Let's assume everything is non-blocking.

CUSTOMER:

1) Open a new unbound socket channel so it can be set as asynchronous

s = SocketChannel.open()

      

2) Set it as non-blocking

s.configureBlocking(false)

      

  • Do we need to contact here? Or is it just if we want to access a local port?

3) Try to connect to the server that is listening

s.connect(someAddr)

      

  • If this returns true, javadocs says the connection is established. Does this mean I don't need to call finishConnect ()? From what I've read, this is for local connections, but it doesn't say if remote connections can return true immediately or not.

  • Is this where the client sends the SYN to the server?


SERVER:

4) The server receives an incoming connection through some serverSocketChannel.accept()

which we assume is not blocking and will pretend in this case, it returns a valid socket object (not null).

  • Does this mean that as soon as the server receives the connection, it will accept the connection (assuming everything went well) and send back a SYN-ACK?

CUSTOMER:

5) finishConnect()

Is the client now calling ?

  • When does the client know when to continue calling finishConnect ()? Am I just looping for X seconds right after calling s.connect(...)

    from step (3)?

  • Is this when it sends ACK? Should I loop for X seconds until it returns true ... and kills the "half-formed connection" if it doesn't respond within X seconds due to something wrong?

  • Does the s.isConnected()

    connection () return true in step (3) or does the Connect () function terminate?


I'm not sure if I'm doing this correctly, and I'm also not sure at what point is it safe for the server to send, or the client to send ... is it in (4) for the server and (5) for the client?

Do I need the client to send a heartbeat packet after the connection has been made to the server so my application knows to start sending data? I don't know how the server will know that it is fully connected, as I cannot figure out how the server will know when the final confirmation is done ... except that the client knows that the connection has been established and it sends some- then the data of the "first packet".

The only way the server can know is to somehow figure out when it receives the ACK packet, but I don't see a Java way letting me know at this time.

NOTE. I may be lacking knowledge, I may have said some wrong things if you can point out where they are wrong. I would be more than happy to update my post to be truly correct.

Links guided by my knowledge / creation of this post:

TCP protocol

SocketChannel Javadocs

+3


source to share


3 answers


Do I need to contact here? Or is it just if we want to access a local port?

You don't need to bind the SocketChannel client.

s.connect(someAddr)

      

If this returns true, the javadocs say the connection has been established. Does this mean I don't need to call finishConnect ()?

Right.

From what I've read, this is for local connections, but it doesn't say if remote connections can return true immediately or not.

It can return true at any time, you should check.

Is this where the client sends the SYN to the server?

Yes.

The server receives an incoming connection via some serverSocketChannel.accept (), which we assume is not blocking and will pretend in this case it is returning a valid socket object (not null). Does this mean that as soon as the server receives the connection, it accepts the connection (assuming everything went well) and sends back a SYN-ACK?

Not. SYN-ACK has already been sent by the TCP / IP stack. This is independent of when the application code calls accept ().

Does the client now call finishConnect ()?

Again, this is independent of when the server application is received. The TCP handshake is completed by the server kernel. The client should call finishConnnect () if connect () did not return true and the subsequent select () indicates that the channel is now connecting.

Note that finishConnect () may return true, in which case you just continue, or false, in which case you just wait for OP_CONNECT or throw an exception, in which case it failed and you must close the channel.

When does the client know when to continue calling finishConnect ()? Am I just looping for X seconds right after calling s.connect (...) from step (3)?

See above.



Is this when it sends ACK?

Not. All this is done by the kernel asynchronosusly

Should I loop for X seconds until it returns true ... and kills the "half-developed connection" if it doesn't respond within X seconds due to something wrong?

No, see above.

Does s.isConnected () return true for the connection () in step (3), or does the next connection terminate Connect ()?

Both: They are mutually exclusive.

I'm not sure if I'm doing this correctly, and I'm also not sure at what point is it safe for the server to send, or the client to send ... is it in (4) for the server and (5) for the client?

The server can send as soon as it has a receive socket. The client can submit as soon as connect () or finishConnect () returns true.

Do I need the client to send a heartbeat packet after the connection has been made to the server so that my application is well aware of when to start sending data?

Not.

I don't know how the server will know that it is fully connected, as I cannot figure out how the server will know when the final confirmation is complete ... other than that the client knows the connection is established and it sends some data type of the "first packet".

See above. The idea of ​​sending a package to see if you can send a package doesn't make sense.

The only way to know the server is to somehow figure out when it will receive the ACK packet

The server already has an ACK packet when accept () returns.

NOTE. Perhaps I am lacking knowledge ...

What you are ignoring is the presence of a listening listen queue on the server.

+2


source


Warning. I have programmed sockets using sockets, not sockets. This answer is based on reading the SocketChannel Javadoc, knowing that socket channels use sockets behind the scenes and are familiar with sockets.

As per the javadoc, if connect () returns true, the connection is established and you don't need to call finishConnect (). Imagine that finishConnect () is a way to check the status of a connection establishment, not a function that does anything needed to establish a connection.



On the server, if accept () returns a SocketChannel, a connection attempt was received from the client. The SYN ACK from the server was most likely sent, although the Java documentation does not specifically indicate this to allow future optimizations. Most likely the connection is considered "established" by Java, although you can call finishConnect () to be sure; perhaps Java waits until the server receives the client's ACK before it thinks the connection is fully established. Note that the Javadoc indicates that the returned SocketChannel will initially be in blocking mode, even if the ServerSocketChannel was in non-blocking mode.

On the client side, you can start sending data as soon as connect () or finishConnect () returns true. On the server side, you can start sending data when finishConnect () returns true; it may happen that the call to finishConnect () is redundant and accept () returns a SocketChannel with an established connection - as I would write it, but I haven't used SocketChannels enough to be sure. You don't need to send a heartbeat during connection establishment, and this is likely to be a waste of effort, since TCP itself handles all connection-related things, including a three-way handshake (SYN, SYN-ACK, ACK), to establish a connection.

+2


source


You need to use a selector to wait for the CONNECT and ACCEPT events.

NIO is not that hard. But the Java NIO API is a little more complex than it needs to be. Good luck trying yourself :)


The exact mapping between Java API calls and TCP handshake steps is not very clear. However, I would consider this in the next model (it doesn't really matter if that's not exactly what's actually happening)

 connect() 
                     -- SYN -->
                    <-- ACK --
                    <-- SYN --  
 CONNECT event
 finishConnect()        
                     -- ACK -->
                                   ACCEPT event
                                   accept()

      

sequences:

  • client application calls connect(serverAddress)

    - client sends SYN to server

if connect()

returns true, the socket channel can be used immeasurably. however, I have never seen this in practice, not even on local loopback connections.

  • the server receives a SYN client; replies with ACK / SYN

  • the client receives the ACK / SYN server.

  • the CONNECT event is added to the client application.

  • cilent app then calls finishConnect()

    - client sends ACK to server

Will finishConnect()

not return false here due to the previous CONNECT event. This can throw an exception.

The client now thinks that the TCP handshake is complete. The client socket channel can be used immediately.

  • the server receives the client's ACK. the server thinks the TCP handshake is complete. the connection is placed in the backlog.
  • the ACCEPT event is added to the server application.

  • the server application then calls accept()

    . The returned socket channel can be used immediately.

0


source







All Articles