Client/server - How to separate protocol from netw

2019-07-30 07:42发布

问题:

I want to implement and unit test (not necessarily TDD) a client application which communicates with a TCP server using in a certain application protocol.

I've seen in places such as here (1) and here (2) that protocol code should be preferably decoupled from the network code so I each one can be unit-tested separately.

However I'm failing to understand how should I design and implement those parts.

The first link talks about a MyProtocolHandler class with methods HelloMessage() and HowdyMessage(). Does that mean a protocol handler is expected to have two methods for generating a message and for processing the response? How will I use them? One more thing, there should be different ProtocolHandler classes for each message/response pair or only one for all of them?

The second link talks about a Reader and a Writer. Again, I can't undersand how should I use them.

Those two are just examples. The main question is, how can I decouple the logic from the network and unit test them? I have to say I haven't tried anything yet; I'm used to writing coupled code only and don't know where to begin.

回答1:

Those are different ways to approach the task. The network stack is design as different layers in which each layer provides "well defined" functionalities to the upper layer and it provides those functionalities through API's.

So if you want to implement your own application layer protocol running on TCP or also on SSL (which in turn will probably run on TCP) you will use the socket interface. The way you design that part is the same way you would design any application. In general you want to separate your application logic from the protocol, call it A, logic. Your protocol A will be in charge of sending a message to the server using sockets (write and read), read message from the server, deal with timeouts (for example when expecting a response from the server that never arrives), deal with socket errors, message format, message parsing, etc. Protocol A will hide all those problems from your application.

Your application will only deal with the API functions provided by your protocol: like HelloMessage, it will call that method and inside, HelloMessage will deal with sockets, message format, etc.

Now your protocol A can be implemented by only one class or a set of classes. If it is a set of classes I'd recommend you to make them part of the same package.

Elaborating more on how to implement it, I would suggest two options: 1) You have a Reader and Writer class that are wrappers of a socket. Then your Protocol classes use these readers and writers and you can test it without having a network with a child Reader and Writer that doesn't use sockets. 2) This is more complex, you can have a Communication class that might receive messages to send through a message queue and it can also send up received messages using another message queue. The Communication class know how to deal with connections or sockets (depending on the level of abstraction). It knows how to open connections, handle timeouts, etc. This is a better design but way too complex.

I hope this helps.