Click here to Skip to main content
15,885,914 members
Articles / Database Development / SQL Server

Develop high performance distributed applications with batching, asynchrony, and parallel computation

Rate me:
Please Sign up or sign in to vote.
3.71/5 (14 votes)
27 Sep 20048 min read 66.3K   1.2K   51  
Performance comparison between SocketPro and .NET remoting.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using USOCKETLib;
using UDBLib;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace Offset
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class frmMain : System.Windows.Forms.Form
	{
		private const uint		sidMySampleService = 0x1F0000AA;
		private const ushort	idEchoMyString = 0x2002;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.Button btnConnect;
		private System.Windows.Forms.Button btnDisconnect;
		private System.Windows.Forms.CheckBox chkSSL;
		private System.Windows.Forms.CheckBox chkZip;
		private System.Windows.Forms.TextBox txtHost;
		private System.Windows.Forms.TextBox txtNetPort;
		private System.Windows.Forms.TextBox txtProPort;
		private System.Windows.Forms.GroupBox groupBox1;
		private System.Windows.Forms.GroupBox groupBox2;
		private System.Windows.Forms.TextBox txtTimeRequiredNet;
		private System.Windows.Forms.TextBox txtTimeRequiredPro;
		private System.Windows.Forms.Label label4;
		private System.Windows.Forms.Label label5;
		private System.Windows.Forms.TextBox txtSQLNet;
		private System.Windows.Forms.Button btnRunSQLNet;
		private System.Windows.Forms.Button btnRunSQLPro;
		private System.Windows.Forms.Button btnNet;
		private System.Windows.Forms.Button btnPro;
		private System.Windows.Forms.TextBox txtSQLPro;

		private USOCKETLib.USocketClass		m_ClientSocket;
		private UDBLib.URowsetClass			m_Rowset;
		private UDBLib.UCommandClass		m_Command;
		private UDBLib.USessionClass		m_Session;
		private UDBLib.UDataSourceClass		m_DataSource;
		private bool						m_bAnyThingWrong;
		private string						m_strErrorMsg;
		private long						m_lFreq;
		private long						m_lStart;

		private TcpChannel					m_Tcp;
		private RemotingSamples.HelloServer	m_HelloServer;

		[DllImport("kernel32.dll")]
		public static extern void QueryPerformanceCounter(ref long lCount);
		[DllImport("kernel32.dll")]
		public static extern void QueryPerformanceFrequency(ref long lFreq);
		

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public frmMain()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.label1 = new System.Windows.Forms.Label();
			this.label2 = new System.Windows.Forms.Label();
			this.label3 = new System.Windows.Forms.Label();
			this.btnConnect = new System.Windows.Forms.Button();
			this.btnDisconnect = new System.Windows.Forms.Button();
			this.chkSSL = new System.Windows.Forms.CheckBox();
			this.chkZip = new System.Windows.Forms.CheckBox();
			this.txtHost = new System.Windows.Forms.TextBox();
			this.txtNetPort = new System.Windows.Forms.TextBox();
			this.txtProPort = new System.Windows.Forms.TextBox();
			this.groupBox1 = new System.Windows.Forms.GroupBox();
			this.btnNet = new System.Windows.Forms.Button();
			this.btnRunSQLNet = new System.Windows.Forms.Button();
			this.txtSQLNet = new System.Windows.Forms.TextBox();
			this.label5 = new System.Windows.Forms.Label();
			this.txtTimeRequiredNet = new System.Windows.Forms.TextBox();
			this.groupBox2 = new System.Windows.Forms.GroupBox();
			this.btnPro = new System.Windows.Forms.Button();
			this.btnRunSQLPro = new System.Windows.Forms.Button();
			this.txtSQLPro = new System.Windows.Forms.TextBox();
			this.label4 = new System.Windows.Forms.Label();
			this.txtTimeRequiredPro = new System.Windows.Forms.TextBox();
			this.groupBox1.SuspendLayout();
			this.groupBox2.SuspendLayout();
			this.SuspendLayout();
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(12, 4);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(132, 20);
			this.label1.TabIndex = 0;
			this.label1.Text = "Host Address:";
			// 
			// label2
			// 
			this.label2.Location = new System.Drawing.Point(180, 4);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(128, 20);
			this.label2.TabIndex = 1;
			this.label2.Text = "dotNet Remoting Port:";
			// 
			// label3
			// 
			this.label3.Location = new System.Drawing.Point(316, 4);
			this.label3.Name = "label3";
			this.label3.Size = new System.Drawing.Size(92, 20);
			this.label3.TabIndex = 2;
			this.label3.Text = "SocketPro Port:";
			// 
			// btnConnect
			// 
			this.btnConnect.Location = new System.Drawing.Point(500, 0);
			this.btnConnect.Name = "btnConnect";
			this.btnConnect.Size = new System.Drawing.Size(100, 24);
			this.btnConnect.TabIndex = 3;
			this.btnConnect.Text = "Connect";
			this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
			// 
			// btnDisconnect
			// 
			this.btnDisconnect.Location = new System.Drawing.Point(500, 28);
			this.btnDisconnect.Name = "btnDisconnect";
			this.btnDisconnect.Size = new System.Drawing.Size(100, 24);
			this.btnDisconnect.TabIndex = 4;
			this.btnDisconnect.Text = "Disconnect";
			this.btnDisconnect.Click += new System.EventHandler(this.btnDisconnect_Click);
			// 
			// chkSSL
			// 
			this.chkSSL.Location = new System.Drawing.Point(420, 4);
			this.chkSSL.Name = "chkSSL";
			this.chkSSL.Size = new System.Drawing.Size(76, 20);
			this.chkSSL.TabIndex = 5;
			this.chkSSL.Text = "SSL ?";
			// 
			// chkZip
			// 
			this.chkZip.Location = new System.Drawing.Point(420, 32);
			this.chkZip.Name = "chkZip";
			this.chkZip.Size = new System.Drawing.Size(76, 20);
			this.chkZip.TabIndex = 6;
			this.chkZip.Text = "Zip ?";
			// 
			// txtHost
			// 
			this.txtHost.Location = new System.Drawing.Point(12, 28);
			this.txtHost.Name = "txtHost";
			this.txtHost.Size = new System.Drawing.Size(164, 20);
			this.txtHost.TabIndex = 7;
			this.txtHost.Text = "localhost";
			// 
			// txtNetPort
			// 
			this.txtNetPort.Location = new System.Drawing.Point(180, 28);
			this.txtNetPort.Name = "txtNetPort";
			this.txtNetPort.Size = new System.Drawing.Size(76, 20);
			this.txtNetPort.TabIndex = 8;
			this.txtNetPort.Text = "17004";
			// 
			// txtProPort
			// 
			this.txtProPort.Location = new System.Drawing.Point(316, 28);
			this.txtProPort.Name = "txtProPort";
			this.txtProPort.Size = new System.Drawing.Size(76, 20);
			this.txtProPort.TabIndex = 9;
			this.txtProPort.Text = "17002";
			// 
			// groupBox1
			// 
			this.groupBox1.Controls.Add(this.btnNet);
			this.groupBox1.Controls.Add(this.btnRunSQLNet);
			this.groupBox1.Controls.Add(this.txtSQLNet);
			this.groupBox1.Controls.Add(this.label5);
			this.groupBox1.Controls.Add(this.txtTimeRequiredNet);
			this.groupBox1.Location = new System.Drawing.Point(12, 60);
			this.groupBox1.Name = "groupBox1";
			this.groupBox1.Size = new System.Drawing.Size(588, 92);
			this.groupBox1.TabIndex = 10;
			this.groupBox1.TabStop = false;
			this.groupBox1.Text = "dotNet Remoting";
			// 
			// btnNet
			// 
			this.btnNet.Enabled = false;
			this.btnNet.Location = new System.Drawing.Point(8, 56);
			this.btnNet.Name = "btnNet";
			this.btnNet.Size = new System.Drawing.Size(480, 24);
			this.btnNet.TabIndex = 6;
			this.btnNet.Text = "Execute 10000 requests";
			this.btnNet.Click += new System.EventHandler(this.btnNet_Click);
			// 
			// btnRunSQLNet
			// 
			this.btnRunSQLNet.Enabled = false;
			this.btnRunSQLNet.Location = new System.Drawing.Point(388, 28);
			this.btnRunSQLNet.Name = "btnRunSQLNet";
			this.btnRunSQLNet.Size = new System.Drawing.Size(100, 20);
			this.btnRunSQLNet.TabIndex = 5;
			this.btnRunSQLNet.Text = "Execute SQL";
			this.btnRunSQLNet.Click += new System.EventHandler(this.btnRunSQLNet_Click);
			// 
			// txtSQLNet
			// 
			this.txtSQLNet.Location = new System.Drawing.Point(8, 28);
			this.txtSQLNet.Name = "txtSQLNet";
			this.txtSQLNet.Size = new System.Drawing.Size(372, 20);
			this.txtSQLNet.TabIndex = 4;
			this.txtSQLNet.Text = "Select * from orders";
			// 
			// label5
			// 
			this.label5.Location = new System.Drawing.Point(496, 28);
			this.label5.Name = "label5";
			this.label5.Size = new System.Drawing.Size(88, 12);
			this.label5.TabIndex = 2;
			this.label5.Text = "Time Required:";
			// 
			// txtTimeRequiredNet
			// 
			this.txtTimeRequiredNet.Location = new System.Drawing.Point(496, 44);
			this.txtTimeRequiredNet.Name = "txtTimeRequiredNet";
			this.txtTimeRequiredNet.Size = new System.Drawing.Size(84, 20);
			this.txtTimeRequiredNet.TabIndex = 0;
			this.txtTimeRequiredNet.Text = "0";
			// 
			// groupBox2
			// 
			this.groupBox2.Controls.Add(this.btnPro);
			this.groupBox2.Controls.Add(this.btnRunSQLPro);
			this.groupBox2.Controls.Add(this.txtSQLPro);
			this.groupBox2.Controls.Add(this.label4);
			this.groupBox2.Controls.Add(this.txtTimeRequiredPro);
			this.groupBox2.Location = new System.Drawing.Point(12, 160);
			this.groupBox2.Name = "groupBox2";
			this.groupBox2.Size = new System.Drawing.Size(588, 92);
			this.groupBox2.TabIndex = 11;
			this.groupBox2.TabStop = false;
			this.groupBox2.Text = "SocketPro";
			// 
			// btnPro
			// 
			this.btnPro.Enabled = false;
			this.btnPro.Location = new System.Drawing.Point(8, 56);
			this.btnPro.Name = "btnPro";
			this.btnPro.Size = new System.Drawing.Size(476, 24);
			this.btnPro.TabIndex = 4;
			this.btnPro.Text = "Execute 10000 requests";
			this.btnPro.Click += new System.EventHandler(this.btnPro_Click);
			// 
			// btnRunSQLPro
			// 
			this.btnRunSQLPro.Enabled = false;
			this.btnRunSQLPro.Location = new System.Drawing.Point(384, 28);
			this.btnRunSQLPro.Name = "btnRunSQLPro";
			this.btnRunSQLPro.Size = new System.Drawing.Size(100, 20);
			this.btnRunSQLPro.TabIndex = 3;
			this.btnRunSQLPro.Text = "Execute SQL";
			this.btnRunSQLPro.Click += new System.EventHandler(this.btnRunSQLPro_Click);
			// 
			// txtSQLPro
			// 
			this.txtSQLPro.Location = new System.Drawing.Point(8, 28);
			this.txtSQLPro.Name = "txtSQLPro";
			this.txtSQLPro.Size = new System.Drawing.Size(372, 20);
			this.txtSQLPro.TabIndex = 2;
			this.txtSQLPro.Text = "Select * from orders";
			// 
			// label4
			// 
			this.label4.Location = new System.Drawing.Point(492, 28);
			this.label4.Name = "label4";
			this.label4.Size = new System.Drawing.Size(88, 12);
			this.label4.TabIndex = 1;
			this.label4.Text = "Time Required:";
			// 
			// txtTimeRequiredPro
			// 
			this.txtTimeRequiredPro.Location = new System.Drawing.Point(492, 44);
			this.txtTimeRequiredPro.Name = "txtTimeRequiredPro";
			this.txtTimeRequiredPro.Size = new System.Drawing.Size(88, 20);
			this.txtTimeRequiredPro.TabIndex = 0;
			this.txtTimeRequiredPro.Text = "0";
			
			// 
			// frmMain
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(612, 265);
			this.Controls.Add(this.groupBox2);
			this.Controls.Add(this.groupBox1);
			this.Controls.Add(this.txtProPort);
			this.Controls.Add(this.txtNetPort);
			this.Controls.Add(this.txtHost);
			this.Controls.Add(this.chkZip);
			this.Controls.Add(this.chkSSL);
			this.Controls.Add(this.btnDisconnect);
			this.Controls.Add(this.btnConnect);
			this.Controls.Add(this.label3);
			this.Controls.Add(this.label2);
			this.Controls.Add(this.label1);
			this.MaximizeBox = false;
			this.Name = "frmMain";
			this.Text = "Offset dotNet remoting weaknesses with strong points of socket";
			this.Load += new System.EventHandler(this.frmMain_Load);
			this.groupBox1.ResumeLayout(false);
			this.groupBox2.ResumeLayout(false);
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new frmMain());
		}
		private void OnClosed(int nSocketHandle, int nError)
		{
			btnPro.Enabled = false;
			btnRunSQLPro.Enabled = false;
		}
		private void OnConnected(int nSocketHandle, int nError)
		{
			if(nError == 0)
			{
				btnPro.Enabled = true;
				btnRunSQLPro.Enabled = true;
				m_ClientSocket.SetSockOpt((int)USOCKETLib.tagSocketOption.soRcvBuf, 116800, (int)USOCKETLib.tagSocketLevel.slSocket);
				m_ClientSocket.StartBatching();
				m_ClientSocket.SwitchTo((int)sidMySampleService);
				m_ClientSocket.TurnOnZipAtSvr(chkZip.Checked);
				m_ClientSocket.SetSockOptAtSvr((int)USOCKETLib.tagSocketOption.soSndBuf, 116800, (int)USOCKETLib.tagSocketLevel.slSocket);
				m_ClientSocket.SetSockOptAtSvr((int)USOCKETLib.tagSocketOption.soTcpNoDelay, 1, (int)USOCKETLib.tagSocketProtocol.spTCP);
				m_ClientSocket.CommitBatching(false);
			}
			else
			{
				MessageBox.Show(m_ClientSocket.ErrorMsg);
			}
		}
		private void OnRequestProcessed (int hSocket, short nRequestID, int lLen, int lLenInBuffer, short sFlag)
		{
			if(nRequestID == idEchoMyString)
			{
				object obj;
				obj = m_ClientSocket.GetRtnBuffer(lLen);
			}
		}

		private void OnRowsetRequestProcessed (int hSocket, short nRequestID, int lLen, int lLenInBuffer, short sFlag)
		{
			
		}
		
		private void OnCommandRequestProcessed (int hSocket, short nRequestID, int lLen, int lLenInBuffer, short sFlag)
		{
			double dTime;
			long lTime = 0;
			if(!m_bAnyThingWrong && m_Command.Rtn != 0)
			{
				m_strErrorMsg = m_Command.ErrorMsg;
				m_bAnyThingWrong = true;
			}
			switch(nRequestID)
			{
				case (short)UDBLib.tagDBRequestID.idCmndReleaseCreatedObject:
					QueryPerformanceCounter(ref lTime);
					lTime = 100000*(lTime-m_lStart)/m_lFreq;
					dTime = lTime;
					dTime /= 100;
					txtTimeRequiredPro.Text = dTime.ToString();
					break;
				default:
					break;
			}
		}
		private void OnDataSourceRequestProcessed (int hSocket, short nRequestID, int lLen, int lLenInBuffer, short sFlag)
		{
			if(!m_bAnyThingWrong && m_DataSource.Rtn != 0)
			{
				m_strErrorMsg = m_DataSource.ErrorMsg;
				m_bAnyThingWrong = true;
			}

		}

		private void frmMain_Load(object sender, System.EventArgs e)
		{
			m_ClientSocket = new USocketClass();
			m_Rowset = new URowsetClass();
			m_Command = new UCommandClass();
			m_Session = new USessionClass();
			m_DataSource = new UDataSourceClass();

			m_Rowset.AttachSocket(m_ClientSocket);
			m_Command.AttachSocket(m_ClientSocket);
			m_Session.AttachSocket(m_ClientSocket);
			m_DataSource.AttachSocket(m_ClientSocket);

			m_ClientSocket.OnSocketClosed += new _IUSocketEvent_OnSocketClosedEventHandler(OnClosed);
			m_ClientSocket.OnSocketConnected += new _IUSocketEvent_OnSocketConnectedEventHandler(OnConnected);
			m_ClientSocket.OnRequestProcessed += new _IUSocketEvent_OnRequestProcessedEventHandler(OnRequestProcessed);

			m_Rowset.OnRequestProcessed += new _IURequestEvent_OnRequestProcessedEventHandler(OnRowsetRequestProcessed);
			m_Command.OnRequestProcessed += new _IURequestEvent_OnRequestProcessedEventHandler(OnCommandRequestProcessed);
			m_DataSource.OnRequestProcessed += new _IURequestEvent_OnRequestProcessedEventHandler(OnDataSourceRequestProcessed);

			m_ClientSocket.UserID = "SocketPro";
			m_ClientSocket.Password = "PassOne";
			
			m_Tcp = new TcpChannel();
			ChannelServices.RegisterChannel(m_Tcp);
			
			m_ClientSocket.RecvTimeout = 5000;
			QueryPerformanceFrequency(ref m_lFreq);
		}

		private void btnRunSQLPro_Click(object sender, System.EventArgs e)
		{
			m_bAnyThingWrong = false;
			if(m_ClientSocket.CurrentSvsID != (int)USOCKETLib.tagServiceID.sidOleDB)
			{
				m_ClientSocket.SwitchTo((int)USOCKETLib.tagServiceID.sidOleDB);
				m_DataSource.Open("Provider=sqloledb;Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind", 0);
				m_Session.Open("", 0);
				m_Command.Open("", 0);
				m_ClientSocket.WaitAll(5000);
			}
			QueryPerformanceCounter(ref m_lStart);
			m_ClientSocket.StartBatching();
			m_Command.ExecuteSQL(txtSQLPro.Text, (short)UDBLib.tagCreatedObject.coRowset, (short)UDBLib.tagCursorType.ctForwardOnly, (int)UDBLib.tagRowsetHint.rhReadOnly);
			m_Rowset.Open("", 0, 0, 0, false);
			m_Rowset.AsynFetch(true, 0, 0x7FFFFFFF); //all of records
			m_Rowset.Close();
			m_Command.ReleaseCreatedObject();
			m_ClientSocket.CommitBatching(true);
		}

		private void btnConnect_Click(object sender, System.EventArgs e)
		{
			string strHost = txtHost.Text;
			string strDestination = strHost + ":" + Int32.Parse(txtNetPort.Text);
			string strURL = "tcp://" + strDestination + "/SayHello";

			try
			{
//				TcpChannel tcpClient = new TcpChannel();
//				ChannelServices.RegisterChannel(tcpClient);
				m_HelloServer = (RemotingSamples.HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer), strURL);
/*				ObjectHandle objHandle = Activator.CreateInstance(
					"RemotingSamples",
					"RemotingSamples.HelloServer",
					new
					object[] { new
								 System.Runtime.Remoting.Activation.UrlAttribute(strURL)});
				m_HelloServer = (RemotingSamples.HelloServer)objHandle.Unwrap();*/
			}
			catch(Exception eEx)
			{
				MessageBox.Show(eEx.Message);
				return;
			}
			
			btnRunSQLNet.Enabled = true;
			btnNet.Enabled = true;
			
			if(chkSSL.Checked)
				m_ClientSocket.EncryptionMethod = (int)USOCKETLib.tagEncryptionMethod.SSL23;
			else
				m_ClientSocket.EncryptionMethod = (int)USOCKETLib.tagEncryptionMethod.NoEncryption;
			m_ClientSocket.Connect(txtHost.Text, Int32.Parse(txtProPort.Text), false, (int)USOCKETLib.tagSocketType.stSTREAM, (int)USOCKETLib.tagAddressFamily.afINet, (int)USOCKETLib.tagSocketProtocol.spIP, 0);
		}

		private void btnDisconnect_Click(object sender, System.EventArgs e)
		{
			m_ClientSocket.Disconnect();
		}

		private void btnRunSQLNet_Click(object sender, System.EventArgs e)
		{
			double dTime;
			long lTime = 0;
			DataSet ds = null;
			QueryPerformanceCounter(ref m_lStart);
			ds = m_HelloServer.GetMyDataSet("server=(local);Integrated Security=SSPI;database=northwind", txtSQLNet.Text);
			QueryPerformanceCounter(ref lTime);
			lTime = 100000*(lTime-m_lStart)/m_lFreq;
			dTime = lTime;
			dTime /= 100;
			txtTimeRequiredNet.Text = dTime.ToString();
		}

		private void btnNet_Click(object sender, System.EventArgs e)
		{
			int n;
			string str;
			double dTime;
			long lTime = 0;
			QueryPerformanceCounter(ref m_lStart);
			for(n=0; n<10000; n++)
			{
				str = m_HelloServer.DoEcho("MyEcho");
			}
			QueryPerformanceCounter(ref lTime);
			lTime = 100000*(lTime-m_lStart)/m_lFreq;
			dTime = lTime;
			dTime /= 100;
			txtTimeRequiredNet.Text = dTime.ToString();
		}

		private void btnPro_Click(object sender, System.EventArgs e)
		{
			int n;
			int j;
			if(m_ClientSocket.CurrentSvsID != (int)sidMySampleService)
			{
				m_ClientSocket.SwitchTo((int)sidMySampleService);
				m_ClientSocket.WaitAll(1000);
			}
//			m_ClientSocket.Syn = true;
			QueryPerformanceCounter(ref m_lStart);
			for(n=0; n<40; n++)
			{
				m_ClientSocket.StartBatching();
				for(j=0; j<250; j++)
				{
					m_ClientSocket.SendRequest((short)idEchoMyString, "MyEcho", false);
				}
				m_ClientSocket.CommitBatching(true);
			}
//			m_ClientSocket.Syn = false;
			m_ClientSocket.WaitAll(5000);
			double dTime;
			long lTime = 0;
			QueryPerformanceCounter(ref lTime);
			lTime = 100000*(lTime-m_lStart)/m_lFreq;
			dTime = lTime;
			dTime /= 100;
			txtTimeRequiredPro.Text = dTime.ToString();
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United States United States
Yuancai (Charlie) Ye, an experienced C/C++ software engineer, lives in Atlanta, Georgia. He is an expert at continuous inline request/result batching, real-time stream processing, asynchronous data transferring and parallel computation for the best communication throughput and latency. He has been working at SocketPro (https://github.com/udaparts/socketpro) for more than fifteen years.

Comments and Discussions