Is it a right thing to do, to use Node.JS as a TCP Server?

6,180 views
Skip to first unread message

Kaveh Shahbazian

unread,
Jun 21, 2013, 1:20:25 PM6/21/13
to nod...@googlegroups.com
Is it a right thing to do, to use Node.JS as a TCP Server? Does that considered as abusing Node.JS? And if anybody had did that what were the pros and cons in the long run?

Sam Roberts

unread,
Jun 21, 2013, 1:37:46 PM6/21/13
to nod...@googlegroups.com
On Fri, Jun 21, 2013 at 10:20 AM, Kaveh Shahbazian
<kaveh.sh...@gmail.com> wrote:
> Is it a right thing to do, to use Node.JS as a TCP Server? Does that
> considered as abusing Node.JS?

Its a primary use case (though with zero info about what you are
serving over TCP, its hard to say more).

http://nodejs.org/docs/latest/api/net.html#net_net_createserver_options_connectionlistener

Kaveh Shahbazian

unread,
Jun 21, 2013, 2:07:29 PM6/21/13
to nod...@googlegroups.com
I have crafted a high performance TCP server in C# (based on SocketAsyncEventArgs) which works brilliantly (for this project). I have more than 7000 clients, sending TCP messages every 30 sec - 1 min; with no authentication, via GPRS; and sometimes, after a total-crumbling in out GPRS network; the load becomes very heavy; since every client is trying to send it's buffered messages too.

When I saw that Node.JS can do TCP handling, I decided to give it a go (I thought: "Heh...Let's see if it can compete with my 'state of the art' TCP server").

And it was astonishing how Node.JS was (is) more performant (in some cases far more performant) than that "state of the art TCP server" and was far simpler and used far less resources.

Of course I have not implemented the message parsing part in Node.JS yet. So I must find a performant way to implement heavy-lifting in an async manner.

(The other thing I am investigating is Go. But Node.JS experience for me was very unique since it's using JavaScript, and it has a bigger and more active community than Go. I love Go, but for instance there is no official MongoDB driver for Go.)

Kaveh Shahbazian

unread,
Jun 21, 2013, 2:29:23 PM6/21/13
to nod...@googlegroups.com
And BTW the messages are ASCII strings.

Kaveh Shahbazian

unread,
Jun 21, 2013, 4:09:12 PM6/21/13
to nod...@googlegroups.com
I have implemented a simple echo server in both Go and Node.JS. On my current machine (4 GB RAM, 2 Cores 2.6) the results are:

Go:
sent: 100% rcvd: 100%, fail: 0%, count: 10000
1950.98729712171 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 5000
1935.92528691284 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 50000
1941.62775741722 op/sec

Node.JS:
sent: 100% rcvd: 100%, fail: 0%, count: 10000
2664.94681658911 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 5000
2740.86607750106 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 50000
2829.08137679441 op/sec

How is it tha Node.JS performs better; based on a dynamic language?

Note: I love Go and I'll use it every chance I get. This is just a very very basic benchmark (maybe flawed); and if I implement the message parsing part too, I am not sure which one would do better because there would be a CPU vs I/O throttling in work.

Mikeal Rogers

unread,
Jun 21, 2013, 4:29:07 PM6/21/13
to nod...@googlegroups.com
Could you please post the code for this benchmark.

Also, being a "dynamic" language does not mean certain operations are slower or faster, it just means that the optimizations that need to happen for something to be fast live in a vm rather than a compiler.

--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Kaveh Shahbazian

unread,
Jun 21, 2013, 4:50:10 PM6/21/13
to nod...@googlegroups.com
Node.JS TCP Server:

var net = require('net');
var fs   = require('fs');

var HOST = '127.0.0.1';
var PORT = 3000;
var timeout = 420000; // msec

var lg = function(message) {
console.log(message);
};

var server = net.createServer();

server.on('listening', function() {
lg('Server listening on ' + HOST +':'+ PORT);
});

server.on('connection', function(sock) {
sock.setTimeout(timeout, function() {
try {
sock.end();
}
catch(x) {
lg('on end' + x);
}
});
sock.setNoDelay(true);
    sock.setEncoding('ascii');
    
    sock.on('data', function(data) {
try {
sock.write(data);
}
catch(x) {
lg(x);
}
    });
sock.on('end', function(data) {
try {
sock.end();
}
catch(x) {
lg('on end' + x);
}
    });
sock.on('error', function(err) {
lg(err);
});
    
    sock.on('close', function(data) {
try {
sock.end();
}
catch(x) {
lg(x);
}
try {
sock.destroy();
}
catch(x) {
lg('on close' + x);
}
    });
sock.on('timeout', function() {
});
});

server.on('error', function(err) {
});

server.on('close', function() {
});

server.listen(PORT, HOST);

Go TCP Server:

package main

import (
"log"
"net"
"os"
"runtime"
)

func main() {
ln, err := net.Listen("tcp", ":3000")

if err != nil {
log.Fatal(err)
}

for {
conn, err := ln.Accept()

if err != nil {
log.Println(err)
continue
}

go handleConn(conn)
}
}

func handleConn(c net.Conn) {
buf := make([]byte, 65536)

for {
n, err := c.Read(buf)

if err != nil || n == 0 {
c.Close()
break
}

n, err = c.Write(buf[0:n])

if err != nil {
c.Close()
break
}
}

log.Printf("conn %v closed", c.RemoteAddr())
}

func init() {
runtime.GOMAXPROCS(1110)

flags := log.Flags()
log.SetFlags(flags | log.Lmicroseconds | log.Llongfile | log.Lshortfile)

fn := "log.log"
f, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModeAppend)
if err != nil {
log.Println(err)
}
log.SetOutput(f)
}

And the client is in C#:

//...
namespace TestClient
{
    static partial class Program
    {
        static void Main(string[] args)
        {
            ThreadPool.SetMaxThreads(10000, 5000);
            ThreadPool.SetMinThreads(2000, 2500);

            var taskCount = 10000;

            var time = new Stopwatch();

            time.Start();
            for (int i = 0; i < taskCount; i++)
            {
                SampleSend();
            }

            var lastLogAt = DateTime.Now.AddMinutes(-1);
            while (TaskCount < taskCount)
            {
                Thread.Sleep(10);

                if ((DateTime.Now - lastLogAt).TotalSeconds > 0.5)
                {
                    Console.WriteLine(Interlocked.Read(ref TaskCount));
                    lastLogAt = DateTime.Now;
                }
            }
            time.Stop();

            var l = string.Format("sent: {0}% rcvd: {1}%, fail: {2}%, count: {3}", 100d * SentCount / taskCount, 100d * RcvdCount / taskCount, 100d * FailCount / taskCount, taskCount);
            var l2 = string.Format("{0} op/sec", taskCount / time.Elapsed.TotalSeconds);

            Log(l);
            Log(l2);

            Console.WriteLine("press any key to exit");
            Console.ReadKey();
        }

        public static long SentCount = 0;
        public static long RcvdCount = 0;
        public static long FailCount = 0;
        public static long TaskCount = 0;

        static async void SampleSend()
        {
            await Task.Delay(0);

            Interlocked.Increment(ref TaskCount);

            TcpClient client = null;
            var enc = new ASCIIEncoding();

            try
            {
                client = new TcpClient();
                client.SendTimeout = TimeSpan.FromSeconds(0.5).Milliseconds;
                client.ReceiveTimeout = TimeSpan.FromSeconds(0.5).Milliseconds;
                client.Connect(IPAddress.Parse("127.0.0.1"), 3000);

                var strm = client.GetStream();

                try
                {
                    var message = "ping";

                    var bytes = enc.GetBytes(message);

                    strm.Write(bytes, 0, bytes.Length);
                    strm.Flush();

                    Interlocked.Increment(ref SentCount);

                    int b = 0;
                    var rcvdBytes = new List<byte>();
                    while ((b = strm.ReadByte()) > -1)
                    {
                        rcvdBytes.Add((byte)(b & 0xFF));

                        if (Encoding.ASCII.GetString(rcvdBytes.ToArray()) == message) break;
                    }

                    Interlocked.Increment(ref RcvdCount);
                }
                finally
                {
                    strm.Close();
                }
            }
            catch (Exception x)
            {
                LogError(x);

                Interlocked.Increment(ref FailCount);
            }
            finally { try { client.Close(); } catch { } }
        }
//...
}
}

Trevor Norris

unread,
Jun 22, 2013, 2:03:02 AM6/22/13
to nod...@googlegroups.com
What version of node are you running against? I've made a couple comments on your code.

As far as message parsing goes you have two routes. Either you can do all of it in js, which is fairly standard, or you can write a native module to do the same. The later is usually only necessary if the data being parsed is packed in some binary format, but in my experience even normal (i.e. ascii text) parsing can achieve up to +30% performance gains.

On Friday, June 21, 2013 1:50:10 PM UTC-7, Kaveh Shahbazian wrote:
Node.JS TCP Server:

server.on('connection', function(sock) {

    sock.setEncoding('ascii');

If you're running this on latest master and in a controlled environment where you know the input will only be ascii characters then use encoding 'binary'. You'll get about double the performance since it doesn't take time to check if all characters are actually in the ascii range. Though, again, this is only for latest master and _only_ if it's a controlled environment.

    
    sock.on('data', function(data) {
try {
sock.write(data);

Why wrap this in a try/catch?
 

server.on('error', function(err) {
});

If you're not actively using the callbacks then don't set them. It'll still make the event call if a callback is set. Not expensive by any means, but also not free.

Kaveh Shahbazian

unread,
Jun 22, 2013, 2:42:38 AM6/22/13
to nod...@googlegroups.com
Thanks for your comment.

You are right; my messages are plain ascii strings. That was a valuable point, which perhaps I would learn it my wasting many hours.

About the try/catch in 'on data' I put there in case the connection dropped from the client side in the middle of transmission; am I mistaken about that?

About 'on error'; I will use it to log errors. This was just the blueprint.

Matteo Collina

unread,
Jun 22, 2013, 12:03:42 PM6/22/13
to nod...@googlegroups.com
Hi Kaveh,

the MQTT.js (https://github.com/adamvr/MQTT.js) library can crank up to 30000 msg/sec, with my recent PR (https://github.com/adamvr/MQTT.js/pull/113) and on my 2011 Macbook Air. MQTT is a binary protocol, so things might be different.

Ideally you should write a custom WriteStream and avoid Buffer#slice whenever you can.
In your code you are doing it wrong, hooking it up on the 'data' event is not the way to go if you want to achieve performance.

Let me know.

Cheers,

Matteo

Kaveh Shahbazian

unread,
Jun 22, 2013, 12:20:48 PM6/22/13
to nod...@googlegroups.com
Thanks for introducing MQTT.js (https://github.com/adamvr/MQTT.js). But in my case, the clients are just GPS/GPRS modems and they have very primitive firmware with a very restricted scripting options; and unfortunately they do not support MQTT protocol.

But MQTT.js looks very promising. I'll have it on my tool-belt.

Matteo Collina

unread,
Jun 23, 2013, 11:29:13 AM6/23/13
to nod...@googlegroups.com
Hi Kaveh,

The MQTT protocol is quite simple. If you can code a TCP client, you can code an MQTT one.
It has even been ported to Arduino: https://github.com/knolleary/pubsubclient.
Let me know if I can help.

Cheers,

Matteo


2013/6/22 Kaveh Shahbazian <kaveh.sh...@gmail.com>
Thanks for introducing MQTT.js (https://github.com/adamvr/MQTT.js). But in my case, the clients are just GPS/GPRS modems and they have very primitive firmware with a very restricted scripting options; and unfortunately they do not support MQTT protocol.

But MQTT.js looks very promising. I'll have it on my tool-belt.

--

Ket

unread,
Jun 24, 2013, 9:12:05 PM6/24/13
to nod...@googlegroups.com
I looked into your code. It's just ordinary server code. I always struggle with node data transfer in sending multiple large binary objects simultaneously. It is good to see any comparison.

Kaveh Shahbazian

unread,
Jun 25, 2013, 1:01:24 AM6/25/13
to nod...@googlegroups.com
@Ket I have tested the code with a 8 KB message too (instead of "ping" string). Performance drops but still Node wins. I am not on my machine, but I'll do it at first chance.

Ket

unread,
Jun 25, 2013, 1:05:23 AM6/25/13
to nod...@googlegroups.com
Great to know!

This is the first time I ever heard of such performance comparison experiment. Keep going...

Kaveh Shahbazian

unread,
Jun 25, 2013, 4:49:52 PM6/25/13
to nod...@googlegroups.com
Again I should note that this is a very simple benchmark (a TCP echo server, on this machine; 4 GB RAM, 2.66 dual core). And Node may totally lose if I bring the message parsing in.

Of-course I intend to use Edge.js (http://tjanczuk.github.io/edge/) to do the heavy lifting. I wish Node had a good FFI and I would like to see a project like Edge.js for Go.

@Ket These are the results:

A TCP Echo Server

1) Message: "ping"

Go 1.1 (concurrency: 2 core)
----------------------------
sent: 100% rcvd: 100%, fail: 0%, count: 5000
1636.58787270711 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 15000
1799.52633587598 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 50000
1803.73687672296 op/sec

Node.JS 0.10.12 (clustered: 2 cores)
------------------------------------
sent: 100% rcvd: 100%, fail: 0%, count: 5000
2704.11161793975 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 15000
2890.51876891881 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 50000
2916.40015872916 op/sec

2) Message: 8 KB byte array

Go 1.1 (concurrency: 2 core)
----------------------------
sent: 100% rcvd: 100%, fail: 0%, count: 100
9.93512571545448 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 500
9.90348220735039 op/sec

Node.JS 0.10.12 (clustered: 2 cores)
------------------------------------
sent: 100% rcvd: 100%, fail: 0%, count: 100
9.88128857062181 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 500
9.92767452827498 op/sec

2) Message: 8 KB byte array

Go 1.1 (concurrency: 6 * 2 core)
--------------------------------
sent: 100% rcvd: 100%, fail: 0%, count: 100
9.95100354726409 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 500
9.8849644185269 op/sec

Node.JS 0.10.12 (clustered: 6 * 2 cores)
----------------------------------------
sent: 100% rcvd: 100%, fail: 0%, count: 100
9.89996726575824 op/sec
sent: 100% rcvd: 100%, fail: 0%, count: 500
9.94040223885374 op/sec

As you see Node and Go has a similar performance for a 8 KB message (Node slightly better at greater numbers, Go slightly better at lesser numbers).

Ket

unread,
Jun 26, 2013, 1:27:18 AM6/26/13
to nod...@googlegroups.com
@Kaveh

Thank you for sharing. I've a bit more confident now.

Kaveh Shahbazian

unread,
Jul 12, 2013, 11:24:50 AM7/12/13
to nod...@googlegroups.com
I made a mistake in my Go code: setting the buffer to 64 KB.

If I set the buffer to (for example) 1 KB; performance of Go TCP server is a bit better than Node.JS.

Node.JS:
sent: 100% rcvd: 100%, fail: 0%, count: 5000
2765.13435456013 op/sec

Go:
sent: 100% rcvd: 100%, fail: 0%, count: 5000
2827.81166344494 op/sec

Kaveh Shahbazian

unread,
Jul 12, 2013, 12:20:48 PM7/12/13
to nod...@googlegroups.com
I forgot to say that yet in most cases Node.JS performs better than Go - of course in a little threshold.

Ket

unread,
Jul 12, 2013, 8:34:00 PM7/12/13
to nod...@googlegroups.com
You are confusing me!

Kaveh Shahbazian

unread,
Jul 12, 2013, 10:59:03 PM7/12/13
to nod...@googlegroups.com
That was not my intention!

See; when we have a echo server that echos a little string like "string" and we set a little buffer in Go, it acts a bit better.

But in all other cases (bigger messages) Node.JS acts a bit better.

By "a bit" I mean ~2.5 %.

And in Node.JS you do not need to worry about buffer size and such things at TCP level.

Kaveh Shahbazian

unread,
Oct 15, 2013, 6:33:52 PM10/15/13
to nod...@googlegroups.com
For the record, I have tested this with Go 1.1 and Node.JS v0.10.20; Go is 22% faster - which means Go can handle 22% more concurrent connections.

Mikeal Rogers

unread,
Oct 15, 2013, 11:18:47 PM10/15/13
to nod...@googlegroups.com
is the string utf8 or ascii? and is it ever decoded in to a string by the application or does it just proxy as a buffer?

notice that while the answers to these questions dramatically change the performance characteristics they are entirely irrelevant to the performance a real application you're likely to build.

Evan

unread,
Oct 15, 2013, 11:27:57 PM10/15/13
to nod...@googlegroups.com
http://actionherojs.com/ can run a TCP/TLS server.  The project can share your code between http, websocket, and 'raw' TCP clients (assuming everyone speaks JSON). 

Paul Spaulding

unread,
Oct 16, 2013, 10:53:29 AM10/16/13
to nod...@googlegroups.com
That would assume speed varies linearly with the number of connections.

mscdex

unread,
Oct 16, 2013, 11:32:13 AM10/16/13
to nod...@googlegroups.com
On Tuesday, October 15, 2013 6:33:52 PM UTC-4, Kaveh Shahbazian wrote:
For the record, I have tested this with Go 1.1 and Node.JS v0.10.20; Go is 22% faster - which means Go can handle 22% more concurrent connections.


Out of curiousity, how does it compare to node's master branch?

Hal Styli

unread,
Oct 18, 2013, 9:35:43 AM10/18/13
to nod...@googlegroups.com
Interesting thread. I'm way off topic here but I can't compile the C# code with my VS2010... any thoughts on how can it be hacked to work for me? Downloading the 4.5 framework did not help.

On Friday, 21 June 2013 21:50:10 UTC+1, Kaveh Shahbazian wrote:
. . .
And the client is in C#:
. . .

Kaveh Shahbazian

unread,
Oct 18, 2013, 11:19:23 AM10/18/13
to nod...@googlegroups.com
This is the last code (with some changes):

C#:
using Buddy;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncClient
{
    static partial class Program
    {
        static void Main(string[] args)
        {
            ThreadPool.SetMaxThreads(10000, 5000);
            ThreadPool.SetMinThreads(2000, 2500);

            var taskCount = 1000;

            var time = new Stopwatch();
            var tasks = new List<Task>();

            time.Start();
            for (int i = 0; i < taskCount; i++)
            {
                tasks.Add(StartPing());
            }

            Task.WaitAll(tasks.ToArray());
            time.Stop();

            var l = string.Format("sent: {0}% rcvd: {1}%, fail: {2}%, count: {3}", 100d * SentCount / taskCount, 100d * RcvdCount / taskCount, 100d * FailCount / taskCount, taskCount);
            var l2 = string.Format("{0} op/sec", taskCount / time.Elapsed.TotalSeconds);

            Log(l);
            Log(l2);

            Console.WriteLine("press any key to exit");
            Console.ReadKey();
        }

        public static long SentCount = 0;
        public static long RcvdCount = 0;
        public static long FailCount = 0;
        public static long TaskCount = 0;

        static Task StartPing()
        {
            var t = new Task(() => SampleSendH(), TaskCreationOptions.PreferFairness);
            t.Start();

            return t;
        }

        static void SampleSendH()
        {
            Interlocked.Increment(ref TaskCount);

            TcpClient c = null;
            var enc = new ASCIIEncoding();

            try
            {
                c = new TcpClient();
                c.SendTimeout = TimeSpan.FromSeconds(0.5).Milliseconds;
                c.ReceiveTimeout = TimeSpan.FromSeconds(0.5).Milliseconds;
                c.Connect(IPAddress.Parse("127.0.0.1"), 3000);

                var strm = c.GetStream();

                try
                {
                    //var message = "9900095854,20130305075608,51.44650,35.74327,0,0,1307,4,160,0,0,0.000,0.000,20130305075747,444247,12074,4084";
                    var message = new string('-', 512);
                    //var message = "ping";

                    var bytes = enc.GetBytes(message);

                    strm.Write(bytes, 0, bytes.Length);
                    strm.Flush();

                    Interlocked.Increment(ref SentCount);

                    var retry = 0;
                    int b = 0;
                    var rcvdBytes = new List<byte>();
                    var received = false;

                    do
                    {
                        while ((b = strm.ReadByte()) > -1)
                        {
                            rcvdBytes.Add((byte)(b & 0xFF));

                            if (Encoding.ASCII.GetString(rcvdBytes.ToArray()) == message)
                            {
                                Interlocked.Increment(ref RcvdCount);
                                received = true;
                                break;
                            }
                        }

                        retry++;
                        if (rcvdBytes.Count == 0) Thread.Sleep(TimeSpan.FromMilliseconds(200));
                    } while (retry < 10 && !received);
                }
                finally
                {
                    strm.Close();
                }
            }
            catch (Exception x)
            {
                LogError(x);

                Interlocked.Increment(ref FailCount);
            }
            finally { try { c.Close(); } catch { } }
        }

        #region tools
        public static void Log(object o)
        {
            try
            {
                var entry = new StringBuilder();
                entry = entry.Append(string.Format("[{0:yyyy-MM-dd HH:mm:ss}] ", DateTime.Now));
                entry = entry.Append((o ?? string.Empty).ToString());

                Trace.WriteLine(entry.ToString().Trim());
            }
            catch { }
        }
        public static void Log(string format, object o, params object[] rest)
        {
            try
            {
                var all = new List<object>();
                all.Add(o);
                all.AddRange(rest);

                var entry = new StringBuilder();
                entry = entry.Append(string.Format("[{0:yyyy-MM-dd HH:mm:ss}] ", DateTime.Now));
                entry = entry.Append(string.Format(format, all.ToArray()));

                Trace.WriteLine(entry.ToString().Trim());
            }
            catch { }
        }
        static TraceSource __dataSource = new TraceSource("DataSource");
        static TraceSource __errorSource = new TraceSource("ErrorSource");
        public static void LogError(object o)
        {
            try
            {
                var entry = new StringBuilder();
                entry = entry.Append(string.Format("[{0:yyyy-MM-dd HH:mm:ss}] ", DateTime.Now));
                entry = entry.Append((o ?? string.Empty).ToString());

                __errorSource.WriteLine(entry.ToString().Trim());
            }
            catch { }
        }
        public static void LogError(string format, object o, params object[] rest)
        {
            try
            {
                var all = new List<object>();
                all.Add(o);
                all.AddRange(rest);

                var entry = new StringBuilder();
                entry = entry.Append(string.Format("[{0:yyyy-MM-dd HH:mm:ss}] ", DateTime.Now));
                entry = entry.Append(string.Format(format, all.ToArray()));

                __errorSource.WriteLine(entry.ToString().Trim());
            }
            catch { }
        }
        public static void LogData(object o)
        {
            try
            {
                var entry = new StringBuilder();
                entry = entry.AppendLine(string.Format("[START [{0:yyyy-MM-dd HH:mm:ss}] ", DateTime.Now));
                entry = entry.AppendLine((o ?? string.Empty).ToString());
                entry = entry.AppendLine("END]");

                __dataSource.WriteLine(entry.ToString().Trim());
            }
            catch { }
        }
        #endregion
    }
}

GoLang:
package main

import (
"log"
"net"
"os"
"runtime"
)

func main() {
ln, err := net.Listen("tcp", ":3000")

if err != nil {
log.Fatal(err)
os.Exit(1)
}

log.Println("listening on port 3000...")

for {
conn, err := ln.Accept()

if err != nil {
log.Println(err)
continue
}

go handleConn(&conn)
}
}

func handleConn(carg *net.Conn) {
c := *carg
buf := make([]byte, 1024*2)

for {
n, err := c.Read(buf)

if err != nil || n == 0 {
c.Close()
break
}

n, err = c.Write(buf[0:n])

if err != nil {
c.Close()
break
}
}

//log.Printf("conn %v closed", c.RemoteAddr())
}

func init() {
runtime.GOMAXPROCS(7)

flags := log.Flags()
log.SetFlags(flags | log.Lmicroseconds | log.Llongfile | log.Lshortfile)

fn := "log.log"
f, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModeAppend)
if err != nil {
log.Println(err)
}
log.SetOutput(f)
}

NodeJS:
NodeJS (clustered):
var cluster = require('cluster');
var net = require('net');
var fs = require('fs');
var os = require('os');

var numCPUs = os.cpus().length;

var HOST = '127.0.0.1';
var PORT = 3000;
var timeout = 420000; // msec

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('exit', function (worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} else {
    var lg = function (message) {
        console.log(message);
    };

    var server = net.createServer();

    server.on('listening', function () {
        lg('Server listening on ' + HOST + ':' + PORT);
    });

    server.on('connection', function (sock) {
        sock.setTimeout(timeout, function () {
            try {
                sock.end();
            }
            catch (x) {
                lg('on end' + x);
            }
        });

        sock.setNoDelay(true);

        sock.setEncoding('binary');

        sock.on('data', function (data) {
            try {
                sock.write(data);
            }
            catch (x) {
Reply all
Reply to author
Forward
0 new messages