protected Exception HandleErrorResponse(TCPBinaryReader response)
        {
            if (response.Command != 0x80000000)
                throw new InvalidOperationException("Call to HandleErrorResponse for non-error response");

            var exceptionClassCode = response.ReadInt32();
            var msg = response.ReadString();
            switch(exceptionClassCode)
            {
                case ServerInternalException.CODE: return new ServerInternalException(msg);
                case ServerInvalidArgumentException.CODE: return new ServerInvalidArgumentException(msg);
                case ServerStreamAlreadyChangedException.CODE: return new ServerStreamAlreadyChangedException(msg);
                case InvalidProtocolException.CODE: return new InvalidProtocolException(msg);
                default:
                    return new NotSupportedException("Unknown server exception code: " + exceptionClassCode);
            }
        }
 protected TCPBinaryReader SendReceive(TCPBinaryWriter request)
 {
     lock (m_Lock)
     {
         OpenIfClosed();
         //
         byte[] data;
         var dataSize = request.Finish(out data);
         var stream = m_TcpClient.GetStream();
         stream.Write(data, 0, dataSize);
         stream.Flush();
         //
         var recvData = new TCPBinaryReader(TCPCommunicationSignature.Response, ReadBuffer);
         if (!recvData.IsComplete)
             throw new IOException("Incomplete response received");
         if (recvData.Command == TCPCommunicationSignature.CmdException)
         {
             throw HandleErrorResponse(recvData);
         }
         if (recvData.Command != request.Command && recvData.Command != TCPCommunicationSignature.CmdException)
             throw new InvalidProtocolException("Invalid response command");
         return recvData;
     }
 }