tcp-gateway

High performance TCP Gateway base on Netty 4 ,for request data or push message.

Installation

Clone this repository, and add it as a dependent maven project.

Usage

Create a Tcp Server

Config spring-tcp-server.xml to start server

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                   http://www.springframework.org/schema/beans/spring-beans.xsd"
       default-autowire="byName">

    <!-- tcp server config start. -->
    <bean id="tcpServer" class="com.linkedkeeper.tcp.connector.tcp.server.TcpServer" init-method="init"
          destroy-method="shutdown">
        <!-- port is tcp server port -->
        <property name="port" value="2000"/>
    </bean>
    <bean id="tcpSessionManager" class="com.linkedkeeper.tcp.connector.tcp.TcpSessionManager">
        <property name="maxInactiveInterval" value="500"/>
        <!-- you can add listener to listen session event, include session create, destroy and so on. -->
        <property name="sessionListeners">
            <list>
                <ref bean="logSessionListener"/>
            </list>
        </property>
    </bean>
    <!-- logSessionListener is related tcpSessionManager, those listener should implements SessionListener -->
    <bean id="logSessionListener" class="com.linkedkeeper.tcp.connector.api.listener.LogSessionListener"/>
    <!-- tcp sender is a container that can send message to client from server -->
    <bean id="tcpSender" class="com.linkedkeeper.tcp.remoting.TcpSender">
        <constructor-arg ref="tcpConnector"/>
    </bean>
    <!-- server config is combine the config, don't modify -->
    <bean id="serverConfig" class="com.linkedkeeper.tcp.connector.tcp.config.ServerTransportConfig">
        <constructor-arg ref="tcpConnector"/>
        <constructor-arg ref="proxy"/>
        <constructor-arg ref="notify"/>
    </bean>
    <!-- tcp connector is container that manage the connection between server and client -->
    <bean id="tcpConnector" class="com.linkedkeeper.tcp.connector.tcp.TcpConnector" init-method="init"
          destroy-method="destroy"/>
    <!-- notify proxy is proxy that implement send notify to client -->
    <bean id="notify" class="com.linkedkeeper.tcp.notify.NotifyProxy">
        <constructor-arg ref="tcpConnector"/>
    </bean>
    <!-- default tcp server config end. -->

    <!-- this proxy is your proxy that can receive message from client -->
    <bean id="proxy" class="com.linkedkeeper.tcp.server.TestSimpleProxy"/>
</beans>

Above config is default, you don't have to change it. But you can change port.

Create Test Proxy to receive message from client

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.linkedkeeper.tcp.connector.tcp.codec.MessageBuf;
import com.linkedkeeper.tcp.data.Login;
import com.linkedkeeper.tcp.data.Protocol;
import com.linkedkeeper.tcp.invoke.ApiProxy;
import com.linkedkeeper.tcp.message.MessageWrapper;
import com.linkedkeeper.tcp.message.SystemMessage;

public class TestSimpleProxy implements ApiProxy {

    public MessageWrapper invoke(SystemMessage sMsg, MessageBuf.JMTransfer message) {
        ByteString body = message.getBody();

        if (message.getCmd() == 1000) {
            try {
                Login.MessageBufPro.MessageReq messageReq = Login.MessageBufPro.MessageReq.parseFrom(body);
                if (messageReq.getCmd().equals(Login.MessageBufPro.CMD.CONNECT)) {
                    return new MessageWrapper(MessageWrapper.MessageProtocol.CONNECT, message.getToken(), null);
                }
            } catch (InvalidProtocolBufferException e) {
                e.printStackTrace();
            }
        } else if (message.getCmd() == 1002) {
            try {
                Login.MessageBufPro.MessageReq messageReq = Login.MessageBufPro.MessageReq.parseFrom(body);
                if (messageReq.getCmd().equals(Login.MessageBufPro.CMD.HEARTBEAT)) {
                    MessageBuf.JMTransfer.Builder resp = Protocol.generateHeartbeat();
                    return new MessageWrapper(MessageWrapper.MessageProtocol.HEART_BEAT, message.getToken(), resp);
                }
            } catch (InvalidProtocolBufferException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

Input Parameters:

final int timeout = 10 * 1000; final int NOTIFY = 3;

public boolean send(long seq, String sessionId, int cmd, ByteString body) throws Exception { boolean success = false; MessageBuf.JMTransfer.Builder builder = generateNotify(sessionId, seq, cmd, body); if (builder != null) { MessageWrapper wrapper = new MessageWrapper(MessageWrapper.MessageProtocol.NOTIFY, sessionId, builder); int ret = notify.notify(seq, wrapper, timeout); if (ret == Constants.NOTIFY_SUCCESS) { success = true; } else if (ret == Constants.NOTIFY_NO_SESSION) { / no session on this machine / success = true; } } else { / no session in the cache / success = true; } return success; }

/**

/**

protected MessageBuf.JMTransfer.Builder generateNotify(String sessionId, long seq, int cmd, ByteString body) throws Exception { Map<String, Object> map = testSessionMap.get(sessionId);

MessageBuf.JMTransfer.Builder builder = MessageBuf.JMTransfer.newBuilder();
builder.setVersion(String.valueOf(map.get(VERSION)));
builder.setDeviceId(String.valueOf(map.get(DEVICE_ID)));
builder.setCmd(cmd);
builder.setSeq(seq);
builder.setFormat(NOTIFY);
builder.setFlag(0);
builder.setPlatform(String.valueOf(map.get(PLATFORM)));
builder.setPlatformVersion(String.valueOf(map.get(PLATFORM_VERSION)));
builder.setToken(String.valueOf(map.get(TOKEN)));
builder.setAppKey(String.valueOf(map.get(APP_KEY)));
builder.setTimeStamp(String.valueOf(map.get(TIMESTAMP)));
builder.setSign(String.valueOf(map.get(SIGN)));
builder.setBody(body);

return builder;

}

## Tcp Client 
support iOS, android, C++ languages 
### Serialize protobuf
#### java
```bat 
/protobuf/protoc --proto_path=/protobuf/ --java_out=/protobuf/MessageBuf.proto

object-c

protoc --plugin=/protobuf/protoc-gen-objc MessageBuf.proto --object_out="/protobuf/"

Notes. You can add QQ group to download protobuf compiler