📜 ⬆️ ⬇️

Java Network Client Development

Sometimes there are situations when it is necessary to use network interaction, however, there is no client for the protocol of interest, or this client is paid (proprietary), or it does its own development. In this article I will describe how to create your client for network interaction. I will describe the general steps necessary for this.


The first thing of course is the specification of the protocol, but since I want to show only a way to solve this problem, I will not need it. The specification is needed in order to create a description of the messages that will be sent via the network. The most reasonable thing would be to take the structure of messages beyond the limits of the code in order to dynamically change their structure. The best descriptor for various kinds of structures is XML. In order not to suffer with the reading of the XML dictionary (so we will call it), let's create a schema description using XSD:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" > <xsd:complexType name="FieldDescription"> <xsd:attribute name="name" type="xsd:string" /> <xsd:attribute name="defaultValue" type="xsd:string" /> </xsd:complexType> <xsd:complexType name="SequenceDescription"> <xsd:sequence> <xsd:element name="fieldDescription" type="FieldDescription" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="sequenceDescription" type="SequenceDescription" minOccurs="0" maxOccurs="unbounded" /> </xsd:sequence> <xsd:attribute name="sequenceName" type="xsd:string" /> </xsd:complexType> <xsd:complexType name="MessageDescription"> <xsd:sequence> <xsd:element name="sequenceDescription" type="SequenceDescription" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="fieldDescription" type="FieldDescription" minOccurs="0" maxOccurs="unbounded" /> </xsd:sequence> <xsd:attribute name="messageName" type="xsd:string" /> </xsd:complexType> <xsd:element name="DictionaryDescription"> <xsd:complexType> <xsd:sequence> <xsd:element name="messageDescription" type="MessageDescription" minOccurs="1" maxOccurs="unbounded" /> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> 

')
For example, this scheme allows you to describe the complex, hierarchical structure of messages. Now it is necessary to understand what the message itself is. In essence, this is a map of fields and their meanings. Let's declare the following messaging interface:

 public interface IMessage { /** * Add field to message * @param name name of field (not null) * @param value value of field */ void addField(final String name, final Object value); /** * Remove field from message * @param name name of field (not null) */ void removeField(final String name); /** * Get message field by name * @param name name of field (not null) * @return value of field */ Object getField(final String name); /** * Check that field is set * @param name field name * @return true if field set, else false */ boolean isFieldSet(final String name); /** * Get set of message fields * @return set of message fields */ Set<String> getFieldNames(); /** * Get copy of message * @return new IMessage with copied fields */ IMessage cloneMessage(); /** * Compare messages by fields * @param message message for comparing * @return true/false */ boolean compare(final IMessage message); } 


By implementing all of its methods, we get a class that we will use in our code to receive and send messages. But as you probably noticed, it is far from the structure that we laid in the scheme, so we will need a coder / decoder.

 public interface ICodec { /** * Encode list of IMessage to byte array * @param messages input messages * @return array of byte */ byte[] encode(List<IMessage> messages); /** * Decode array of byte to list of IMessage * @param bytes input array * @return list of IMessage */ List<IMessage> decode(byte[] bytes); } 


The final implementation of this interface should receive in the constructor an instance of the IDictionary interface, the task of which is to read the structure according to the scheme from XML into instances of classes created according to the scheme. The following code snippet needs to be inserted into ant to do this. This fragment defines the class creation tusk for a scheme using jaxb.

 <path id="jaxbcp"> <pathelement location="libs/jaxblibs/jaxb-api.jar" /> <pathelement location="libs/jaxblibs/jaxb-impl.jar" /> <pathelement location="libs/jaxblibs/jaxb-xjc.jar" /> <pathelement location="libs/jaxblibs/jsr173_1.0_api.jar" /> </path> <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask" classpathref="jaxbcp" / <xjc schema="xsd/schema.xsd" destdir="${gen.dir}" package="your.package.name"> <produces dir="${gen.dir}" includes="*" /> </xjc> 


Read the xml dictionary with the following code:

 try { jc = JAXBContext.newInstance(new Class[]{DictionaryDescription.class}); u = jc.createUnmarshaller(); File f = new File (path); JAXBElement<DictionaryDescription> root = u.unmarshal(new StreamSource(f), DictionaryDescription.class); DictionaryDescription s = root.getValue(); } catch (JAXBException e) { logger.error("Error during parsing dictionary", e); } 


Now everything is ready, except for the client. Let's create an interface for it.

 interface Client { void init(Map parameters); void connect(); void disconnect(); void sendMessage(IMessage msg); void addReceiveListener(IReceiveListener listener); void removeReceiveListener(IReceiveListener listener); } 


Apply the subscriber / watcher pattern to process received messages. IReceiveListener will be the subscriber interface. The onMessageReceived method will contain a handler for receiving the message. With this interface you can implement a large range of subscribers. For example: proxy (redirector), saving to file / database / memory, to implement a simulator that will automatically respond to incoming messages.

 public interface WMQReceiveListener { /** * Handler of message * @param message message */ public void onMessageReceived(byte[] message); } 


That's all, the skeleton of its connectivity layer is created. Then you can build it up to implement all your business logic.

Source: https://habr.com/ru/post/135625/


All Articles