Now
we switch to the highest level of abstraction that we provides. To use the
library, the client must first establish a TCP connection, and then constructs
a Connection object.
public Connection(Socket socket, ConnectionType connectionType)
Since
the connection is shared, one cannot send/receive data through the Connection
directly, instead, one create Channels. On the client side (i.e. initiator), he
can simply create a channel by calling Connect.
public Channel ConnectChannel()
Unlike
TCP, the call is synchronous because the connection is already established.
Currently we do not check if the other side is ready to accept this connection,
we simply assumes the server eventually will. This could be improved in the future.
On
the other hand, the server side will need to wait for a Channel establishment
request, this is done by calling Accept
public IAsyncResult BeginAcceptChannel(AsyncCallback callback, object state)
public Channel EndAcceptChannel(IAsyncResult ar)
This
call is necessarily asynchronous not because it involves I/O, but because it
blocks on waiting.
Channel
itself is just a Stream. This design make it very easy for other stream
processing code (e.g. serialization) to use the library without modification.
In addition, it provides a teardown that stop sending data to model TCP one-way
shutdown.
public void StopSending()
public IAsyncResult BeginStopSending(AsyncCallback callback, object state)
public void EndStopSending(IAsyncResult ar)
public Task StopSendingAsync()
The connect() issue does backfire. For VNC - the client does not send anything after connect. In this model - it does not send any message to the another side of the tunnel, so the client just keep waiting.
ReplyDeleteA simple fix is made by simply sending an empty packet - note that the empty packet indicate a close, so special care has to be taken to make sure the another side does not close the channel on the first zero sized packet.