-
ATCP is a powerful C/S long-TCP connection framework developed by ATATC™. It supports:
- p2p communication (even 2 client of the same IP)
- TCP transition
- RSA encryption/signature
- Message Flags
- Mutil-threads processing
- Load balance
- Local data compression
-
*** Before reading, notice the form of text, they have meanings.**
-
object or class or type
XXX
-
specific name
XXX
-
method and its notes
XXX
XXX
-
-
Download .jar, .java or .py files here.
-
-
When send() is called, the message will be added to the message queue, it won't be sent until the last message gets its result or there's no message before. In several cases, the next message will be sent at the same time as current message. Cases including using Flags.RESULT_NO_NEED, or current message is a result (this can't be caused manually).
MIDs are to bind the result to its original message. Each message that is manually sent has a MID, method onRecved() will be called back when the result is received. Use the MID to recognize the result's original message.
-
-
-
*** indi.atatc.atcp_server.packages.log.Log. This is an singleton object, which stores server logs and all the Input/Output Streams.**
-
public enum DebugLevel { INFO, DEBUG, WARNING, ERROR }
INFO < DEBUG < WARNING < ERROR Log will only print the message to the console if the message's debug level is bigger than or the same as current debug level.
Log.getInstance().debugLevel = Log.DebugLevel.DEBUG;
Set the Log's debug level as DEBUG, then the Log will only print the message whose debug level is from INFO to DEBUG (including INFO and DEBUG).
-
The most important method is log.publish().
Log.getInstance().publish();
The parameter "message" can be either Exception or any type else. If Exception, the debug level must be ERROR. Otherwise, you must fill the parameter "debugLevel". For both cases, you can specify the end of the message, it's "\n" in default.
For example:
GOES TOLog log = Log.getInstance(); log.debugLevel = Log.DebugLevel.DEBUG; log.publish("log message", Log.DebugLevel.INFO); log.publish(new RuntimeException("a runtime exception for test"));
log message
Because ERROR > BEBUG > INFO.
Another sample:
GOES TOLog log = Log.getInstance(); log.debugLevel = Log.DebugLevel.DEBUG; log.publish("log message 1", ", ", Log.DebugLevel.INFO); log.publish("log message 2", Log.DebugLevel.INFO);
log message 1, log message 2
In this case, I specified the end of the first message.
-
Prison is an object which stores many blacklist Columns. Each Column can store objects. There will always be a Column with the name "ip", the IPs failed in judge() won't be added to the Column automatically, you can add them manually in judge().
Get the Prison object:
Log.Prison prison = Log.getInstance().prison;
Main methods: ```java String name = "column 1"; Log.Prison.Column column = new Log.Prison.Column(name); prison.add(column);
Add a blacklist Column to the Prison.
Throw StatusError if there is already a Column which has the same name as the given Column.
Column column1 = prison.getColumnByName("column 1");
Get the Column with the name.
Throw StatusError if there is no such Column in the Prison.
column1.add("element 1 in column 1"); prison.contains("element 1 in column 1"); // will return true;
Return whether any Column contains the element.
prison.clear();
Empty the Prison.
-
Log also provides a static method to get String time.
GOES TOString time = Log.time(); Log.getInstance().publish(time, Log.DebugLevel.INFO);
2020-7-24 15:37:26
「YEAR」-「MONTH (max-12)」-「DAY (max-366)」 「HOUR (max-24)」:「MINUTE (max-60)」:「SECOND (max-60)」
yyyy-MM-dd HH:mm:ss
You can also specify the format:
GOES TOString format = "HH:mm"; String time = Log.time(format); Log.getInstance().publish(time, Log.DebugLevel.INFO);
15:37
Use the same format as SimpleDateFormat.
-
-
*** indi.atatc.atcp_server.packages.data.Values. This is an singleton object which stores global attributes. The attribute names must be String. **
String name = "attribute 1"; Object value = "value of attribute 1"; Values.getInstance().put(name, value);
> Set a new attribute or rewrite the attribute named "attribute 1". ```java String valueOfAttribute1 = (String) Values.getInstance().get("attribute 1");
Get the attribute named "attribute 1".
Method get() will throw AccidentEvents.StatusError when there is no such attribute.
-
There are 6 pre-defined attributes:
Name Default Value Usage "log_path" "log.txt" The path of the log file. "key_length" 2048 The key length of the RSA key pair. "separator_first_grade" "\\\" "separator_second_grade" "@" "separator_third_grade" "#" "separator_flag" ":"
-
-
-
Flags are used to identify the properties of a message. There are 2 types of Flags: system-owned Flags and costume Flags. There are totally five pre-defined (system-owned) Flags: RESULT_NO_NEED, KILL, RES, TO_PID, FROM_PID.
Name String Usage User Available User Visible RESULT_NO_NEED \\res_no_need\\ The message doesn't need a result. The message with this Flag won't be blocked). True False FROM_PID \\from_pid\: PID The message is a p2p message from a PID. False True TO_PID \\to_pid\\: PID The message is a p2p message which expected to be sent to a PID. False False KILL \\kill\\ This is the last message. False False RES \\res\\ This is a result. False False Flags can have values, like Flags.FROM_PID and Flags.TO_PID. The values must be String.
-
Basics.ContainerClass.Flag flag = new Basics.ContainerClass.Flag("costume flag 1");
Create a costume Flag named "costume flag 1".
Basics.ContainerClass.Flag flag = new Basics.ContainerClass.Flag("costume flag 2", "value of costume flag 2");
Create a costume Flag named "costume flag 2" with value "value of costume flag 2".
-
GOES TO
Basics.ContainerClass.Flag flag1 = new Basics.ContainerClass.Flag("flag 1", "I am flag 1"); String valueOfFlag1 = flag1.getValue(); Log.getInstance().publish(valueOfFlag1, Log.DebugLevel.INFO);
I am flag 1
-
-
*** Flags is a serial of Flags. All the pre-defined Flags are also stored inside as static members. **
-
Flags flags = new Flags(Flags.RESULT_NO_NEED, new Basics.ContainerClass.Flag("costume flag 1", "value of costume flag 1"));
Create a new Flags object which contains Flags.RESULT_NO_NEED and a costume Flag.
-
flags.add(new Basics.ContainerClass.Flag("costume flag 2"));
Add a new costume Flag to the Flags object.
-
GOES TO
String valueOfFlag1 = flags.valueOf("costume flag 1"); Log.getInstance().publish(valueOfFlag1, Log.DebugLevel.INFO);
value of costume flag 1
Get the value of Flag "costume flag 1". Method valueOf() will return null if there is no such Flag.
Or,
GOES TOString valueOfFlag1 = flags.valueOf(new Basics.ContainerClass.Flag("costume flag 1")); Log.getInstance().publish(valueOfFlag1, Log.DebugLevel.INFO);
value of costume flag 1
Get the value of Flag "costume flag 1". Method valueOf() will return null if there is no such Flag.
-
GOES TO
boolean contains = flags.contains(new Basics.ContainerClass.Flag("costume flag 1")); Log.getInstance().publish(contains, Log.DebugLevel.INFO);
true
Get whether the Flags object contains Flag Flags.RESULT_NO_NEED.
-
Use toArray() to turn the Flags object into an array. Then use foreach for iteration:
for (Basics.ContainerClass.Flag flag: flags.toArray()) { }
-
-
-
-
*** All the samples are written with JAVA, if you are using Python version, the differences are mentioned in the source code.**
-
-
Create a new Configutation object:
Server.Configuration configuration = new Server.Configuration(); configuration.name = "ATCP Test"; // the server's name configuration.port = 1024; // server port, it's 4747 in default configuration.project = "ATCP"; // the project to which the server belongs
-
Server server = new Server(2000, configuration) { @Override public Process onConnected(Connection connection) { return new Process(this, connection) { @Override protected void onSent(MID mid) { } @Override protected void onRecved(MID mid, String result, Flags flags) { } @Override protected String process(String msg, Flags flags) { } }; } };
Override 1 abstract method:
abstract Process onConnected(Connection connection)
This method should return a Process object which will be used to handle the client's requests.
There are 5 callback methods in a Server object:
void onStart()
Called when
void onStarted()
Called when
abstract Process onConnected(Connection connection)
Called when
void onInterrupt()
Called when
void onInterrupted()
Called when
*** Attention, make sure that you have complete all the settings here because you can never meet this Server object again anymore.**
Use
Process = new Process(this, connection) { @Override protected void onSent(MID mid) {} @Override protected void onRecved(MID mid, String result, Flags flags) {} @Override protected String process(String msg, Flags flags) { return "recved" + msg; } };
to create a new Process object. There are 9 callback methods during a Process object's lifecycle:
void onStart()
Called when Thread has been started.
void onStarted()
> Called when the connection parameters have been determined. ```java void onSend(MID mid)
Called when a message is about to be sent.
abstract void onSent(MID mid)
Called when a message has been sent.
abstract void onRecved(MID mid, String result, Flags flags)
Called when a result is sent back to the server.
abstract String process(String msg, Flags flags);
Called when the server receives a message. This method usually should return a String, if you don't want to return anything, just return "".
void onClosed()
Called when the Process is about to end.
void onDiscard()
Called when the Process has ended.
void onDiscard()
Called when the Process object is about to be destroyed.
-
You can disable any additional function like RSA encryption, message blocking, multi-threads processing. If you change these attributes after the Process has been started (generally you can't), it won't work.
-
server.setRSAOn(true/false);
Boolean Affect true (default) Use RSA encryption and signature to keep every message safe. false All the messages will be sent in plaintext. Make sure you have a secure environment before you disable this function.
-
server.setMessageBlockingOn(true/false);
Boolean Affect true (default) There won't be 2 messages being handled by the remote at the same time. false The message will be sent and handled by the remote as long as the user calls send(). Generally, this function is ineffective to the main function. Disable this function to improve the performance, but might cause some bugs.
-
server.setMultiThreadsOn(true/false);
Boolean Affect true Every message will be handled in several threads if able. false (default) Every message will be handled in the same thread. This function is disabled in default. Enable it if you have a lot of computations for each client.
-
server.setErrorHandlingOn(true/false);
Boolean Affect true (default) Catch every known exception automatically. false Catch every known exception and throw an AccidentEvent with the origin message. Never disable this function unless in tests. If disabled, all will be thrown directly. Disable function might cause more exceptions.
-
-
Use
LoopListener loopListener = new LoopListener() { // ToDo: override this method @Override public boolean when() { if (...) return true; // return true to execute else return false; // return false to pass } // ToDo: Override this method @Override public void run() { // run sth } };
to create a new LoopListener. If when() returns true, run() will be called. A LoopListener can be added to a Server or a Process. Generally, you should send or do anything but settings inside a LoopListener.
-
Override judge() in the Server object.
Server server = new Server(configuration) { //Todo: override this method @Override public boolean judge(Log log, IP ip) { if (...) return true; // return true to allow the ip to connect else return false; // return false to discard this connection } @Override public Process onConnected(Connection connection) { return new Process(this, connection) { @Override protected void onSent(ID.MID mid) {} @Override protected void onRecved(ID.MID mid, String result, Flags flags) {} @Override protected String process(String msg, Flags flags) { return "recved msg: " + msg; } }; } };
-
server.start();
The server will run in the main thread, if you need it non-blocking in a child thread, fill the parameter with Server.Mode.MT.
server.start(Server.Mode.MT);
There are 3 modes to start the server.
Name Full Name Usage MT Multi-threads Run the server in a child thread. T Test Run the server as a test (only accept from IP that starts with 192.168 or localhost). MT_T Multi-threads test Run the server as a test (only accept from IP that starts with 192.168 or localhost) in a child thread. -
ActionCallback is an interface of periodic callback method. Specifying the periodic callback methods when handling a message instead of recognising by MID inside the default callback methods is much simpler and more practical (at least I think so).
Create a new ActionCallback interface:
Process.ActionCallback actionCallback = new Process.ActionCallback() { @Override public void onSend() {} @Override public void onSent() {} @Override public void onRecved(String result, Flags flags) {} };
Override 3 abstract methods:
abstract void onSent(MID mid) abstract String process(String msg, Flags flags) abstract void onRecved(MID mid, String result, Flags flags)
It's easy to find out that these methods in an ActionCallback interface are part of the callback methods of a Process object, and its function and lifecycle are consistent with those in a Process object.
process.specifyActionCallback(mid, actionCallback);
-
server.interrupt();
This method will directly stop all the process and stop listening the port immediately without blocking.
-
server.stop();
This method will stop listening the port. As long as all the process have ended, the Server will no longer be maintained.
-
-
This repository has been archived by the owner on May 30, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
ATATCTech/ATCP
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
 |  | |||
 |  | |||
 |  | |||
 |  | |||
 |  | |||
 |  | |||
Repository files navigation
About
A TCP long connection architecture.
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published