Author Topic: [RESOURCE] TCP Object Guide and Reference (Needs Refining)  (Read 2659 times)

How to do...
TCP Objects (Guide)

Written by Wrapperup

Edited by Wrapperup and Eagle517


Example code snips will have their proper author's credited.

NOTE: This thread may need some refinement. The code has not been tested, if you come acrost any problem with the guide or reference, please make a reply. Thanks.



Since no one has made a tutorial on it (I made sure by using the magic Search button) and there are MANY uses for TCP Objects, I decided it was time to make it happen.

Network coding is a HUGE topic to cover, and I will not cover it all. Research it yourself. I will only go over the basics of how to send data from point A to point B.

This tutorial expects that you know TorqueScript (Obviously)

In this tutorial I'll explain...

What is a TCP Object and why should I use them?

How do I use them?

Client sided functions.
Server sided functions.

Client Tutorial.
Server Tutorial.


Examples of TCP Objects.







      What is a TCP Object and why should I use them?

TCP stands for "Transmission Control Protocol".
TCP Objects are used for a variety of things such as connecting to a remote or local server, sending data back and forth, ect.

You can also use them to make a TCP Server, handle connections and send data back and forth with a client.
Here is a few examples of why you should use TCP Objects


Connecting to a website, grab data, and do whatever with the data.

Download files and/or images (Example: Updating an add-on or script).

Remote controlling your Blockland server.

Communicate between two or more applications (Python to Torque, Torque to Python, ect).

Connecting to a chat server and chatting with people.

Storing and retrieving data from a database online.


These are just a few of the possibilities of TCP Objects.

The main purpose of TCP Objects is to communicate with a remote or local server, i.e. a chat server where you can chat with friends.



      How do I use them?

Now that you know what you could use TCP Objects for, it's time to actually use one.

TCP was designed to be connection based. In order to send data, we must connect to our TCP server/client.
Data sent between both the server and client can be anything you want.

However, when sending a chunk of data, when you are finished sending the data/chunk of data, you need to add a "Return Carriage".

Here we will explain the "Return Carriage", which is defined with \r, and is usually followed with a line break (\n)
This will tell the server/client that it is finished sending the current chunk of data.

The reason we use a return carriage is because the client nor the server know's when the data transmission is finished.
If it decided to take a guess on when the data ends, it can lead to corruption.

So it is ALWAYS a good idea to add \r\n to the end of your data transmission (it will be shown below in the reference)

I will refer below each function of a TCP Object and what it does.

client side functions
Code: [Select]
new TCPObject(myTCP); //Create a TCP Object so we can connect to remote or local hosts.

//Methods
myTCP.connect(%ip @ ":" @ %port); // Replace %ip with the domain or IP you are trying to connect to and %port with the port (websites usually use port 80).
myTCP.disconnect(); //Disconnects you obviously.

myTCP.send(%data @ "\r\n"); //Sends data that you supply to the remote or local host. Will end the chunk of data being sent.

//Callbacks
function myTCP::onConnected(%this)
{
        //You connected to the server successfully!
}

function myTCP::onLine(%this,%line)
{
        //%line contains data that was sent to us.
}

function myTCP::onConnectFailed(%this)
{
        //You couldn't connect to the server.
}

function myTCP::onDisconnect(%this)
{
        //When you are disconnected via server or by disconnecting from the client.
}

function myTCP::onDNSFailed(%this)
{
        //DNS Failure
}

function myTCP::onDNSResolved(%this)
{
        //DNS was resolved.
}

function myTCP::onBinChunk(%this,%chunk)
{
        //Used when handling binary data (ie. downloading an add-on)
}

Server side functions
Code: [Select]
new TCPObject(myTCPServer); //Create a TCP Object so we can accept clients

//Methods
myTCPServer.listen(%port); //Listens for connections on the specified port.

//Callbacks
function myTCP::onConnectRequest(%this, %ip, %socket)
{
        //Whenever a remote or local client connects to this server.
        //Handle connected clients here.
}

function myTCP::onLine(%this,%line)
{
        //%line contains data that was sent to us.
}

I will go step by step on how we can connect to the server, retrieve information, and disconnect.

Lets start with the client side (Since it is easier to make than server side)

Using 2 computers (MUST BE LOCAL OR THE SERVER'S PORT MUST BE FORWARDED!) will work the same as doing it on the same computer. Put your server script on your 1st computer, and put the client script on your 2nd computer.

Below will go step by step through making a simple TCP Client in Torque. I will explain what each code does if necessary.


Firstly, create your TCP Object (And disallow it from making a duplicate)
Code: [Select]
if(!isObject(TCPclient))
        new TCPObject(TCPclient);

Create a function to have it connect to the server.

Code: [Select]
function TCPclient_connect()
{
        //The port will be specified on the server side.
        //I will use port 3000 for this example

        TCPclient.connect("localhost:3000");
}

This code will basically prevent a few extra steps from having to be done. The TCPclient Object will try to connect to
localhost with the port 3000.

Now that you have done that, we also want to have it send data once it connects succesfully.

Code: [Select]
function TCPclient::onConnected(%this)
{
        %this.send("Sending Message\r\n");
        //Now we wait for the response.
}

This code will send data to the remote host or local host. In the example, we are just sending some data that says "Sending Message".

\r\n is basically a "return carriage", which tells the server that we are done sending the current chunk of information, and starts it on a new line to receive more data (if needed).

Now we will react to the data that is sent to us.

Code: [Select]
function TCPclient::onLine(%this,%data)
{
    echo(%data);
    if(%data $= "Return Message")
    {
        %this.disconnect();
    }
}

When the server sends us the message "Return Message", we will disconnect.

That should finish the client.

Complete code:
Code: [Select]
if(!isObject(TCPclient))
        new TCPObject(TCPclient);

function TCPclient_connect()
{
        //The port will be specified on the server side.
        //I will use port 3000 for this example

        TCPclient.connect("localhost:3000");
}

function TCPclient::onConnected(%this)
{
        %this.send("Sending Message\r\n");
        //Now we wait for the response.
}

function TCPclient::onLine(%this,%data)
{
    echo(%data);
    if(%data $= "Return Message")
    {
        %this.disconnect();
    }
}


Now that we are done coding the client side, we can go ahead and start making the server side.


Firstly, make your TCP Object (as always).

Code: [Select]
if(!isObject(TCPserver))
        new TCPObject(TCPserver);

Now make the server listen on the port for a connection.

Code: [Select]
if(!TCPserver.isListening)
{
    TCPserver.listen(3000);
    TCPserver.isListening = true;
}

We should make a ScriptGroup to keep up with all our connections (clients)

Code: [Select]
if(!isObject(TCPServerGroup))
    new ScriptObject(TCPServerGroup);

Now that we have our script group (which will allow us to add the clients in, interact with all of them and keeps track of them)

Next, add in below
Code: [Select]
function TCPserver::onConnectRequest(%this, %ip, %socket)
{
        %cl = new TCPObject(TCPSock,%socket);
        TCPServerGroup.add(%cl);
       
        //Client disconnects after receiving data.
}

That will create a new connection for the client, allowing both the server and the client to communicate

We need to use the onLine function to recieve the data the client is sending us.
The function will also check for the message "Sending Message", and send them a message back ("Return Message").

Code: [Select]
function TCPSock::onLine(%this,%data) //MAKE SURE You use the CLIENT OBJECT'S NAME! (TCPSock)
{
    echo(%data);
    if(%data $= "Sending Message")
        %this.send("Return Message\r\n");
}

Now that we have handled the data, we will make sure to delete the object after it disconnects (it will remove itself from the ScriptGroup)

Code: [Select]
function TCPSock::onDisconnect(%this)
{
    %this.delete();
}

Complete server code

Code: [Select]
if(!isObject(TCPserver))
        new TCPObject(TCPserver);

if(!TCPserver.isListening)
{
    TCPserver.listen(3000);
    TCPserver.isListening = true;
}

if(!isObject(TCPServerGroup))
    new ScriptObject(TCPServerGroup);

function TCPserver::onConnectRequest(%this, %ip, %socket)
{
        %cl = new TCPObject(TCPSock,%socket);
        TCPServerGroup.add(%cl);
       
        //Client disconnects after receiving data.
}

function TCPSock::onLine(%this,%data) //MAKE SURE You use the CLIENT OBJECT'S NAME! (TCPSock)
{
    echo(%data);
    if(%data $= "Sending Message")
        %this.send("Return Message\r\n");
}

function TCPSock::onDisconnect(%this)
{
    %this.delete();
}

Testing

1. If you are using 1 computer:
Open 2 Blockland clients, load the server script on one, and load the client script on one.

2. If you are using 2 LOCAL computers:
Load blockland on both computers
Load the server script on one computer, and the client script on the other.

3. If you are 2 computers that are NOT LOCAL:
Repeat step 2, but make sure the server computer's port (3000 that we defined) is PORT FORWARDED.

On the client, connect to the server using the function we defined (in console)

Your console should say (on client)

Return Message

On the server

Sending Message

If you got these messages in your respective consoles, congratulations, you successfully made a working client and server TCP script!

      Examples of TCP Objects.
Code: [Select]
//Downloading a file with TCP Objects.

if(!isObject(TCP_FileDL))
new TCPObject(TCP_FileDL);

function TCP_FileDL::Download(%server, %directory, %port, %outputFile)
{
if(%server $= "" || %port $= "" || %directory $= "" || %outputFile $= "")
return;

%tcp.server = %server;
%tcp.directory = %directory;
%tcp.port = %port;
%tcp.outputFile = %outputFile;

%tcp.connectAttempt = 0;

%tcp.connect(%server @ ":" @ %port);
}

function TCP_FileDL::onConnected(%this)
{
%this.send("GET" SPC %this.directory SPC "HTTP/1.0\r\nHost:" SPC %this.server @ "\r\n\r\n");
}

function TCP_FileDL::onLine(%this, %line)
{
if(strPos(%line,"Content-Length:") >= 0)
%this.len = getWord(%line,1);

if(%line $= "")
%this.setBinarySize(%this.len);
}

function TCP_FileDL::onBinChunk(%this, %chunk)
{
if(%chunk >= %this.len)
{
%this.saveBufferToFile(%this.file);
%this.schedule(10,delete);
}
}

function TCP_FileDL::onConnectFailed(%this)
{
if(%this.connectAttempt >= 2)
error("Connection Failed.");
else
{
%this.connectAttempt++;
%this.schedule(2000,0,connect,%tcp.server @ ":" @ %tcp.port);
error("Connection Retry...");
}
}

function TCP_FileDL::onDNSFailed(%this)
{
error("DNS Failure.");
}

 //example: TCP_FileDL.Download("www.example.com","/files/Script_Example.zip",80,"Add-ons/Script_Example.zip");

(Credit to Zeblote for original code, highly edited by me (so problems with this are not his fault))

Got an example? Post one and I will add it here.

NOTE: This thread may need some refinement. The code has not been tested, if you come acrost any problem with the guide or reference, please make a reply. Thanks.
« Last Edit: December 02, 2014, 05:57:19 PM by Wrapperup »


very helpful... might play around with these a bit.

Did you by chance make this because

I couldn't even begin to guess what this is all about xD

So much more to learn

Oh right, to the point, great looking tutorial. I'll get focused on this, get out my scripting notebook and start learning tomorrow
« Last Edit: September 14, 2014, 01:23:00 PM by Dannu »

Yay, you finally did it! :D

Did you by chance make this because

Oh right, to the point, great looking tutorial. I'll get focused on this, get out my scripting notebook and start learning tomorrow

I had this in my dropbox for a while, i completly forgot about it. Saw a thread about tcp objects and i was reminded. Decided to polish it out a tiny bit and post it here.