Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Net::TCPClient is a TCP Socket Client with automated failover, load balancing, retries and built-in timeouts.
Net::TCPClient implements high availability and resilience features that many developers wish was already included in the standard Ruby libraries.
Another important feature is that the connect and read API's use timeout's to prevent a network issue from "hanging" the client program.
require 'net/tcp_client'
Net::TCPClient.connect(server: 'mydomain:3300') do |client|
client.write('Update the database')
response = client.read(20)
puts "Received: #{response}"
end
Enable SSL encryption:
require 'net/tcp_client'
Net::TCPClient.connect(server: 'mydomain:3300', ssl: true) do |client|
client.write('Update the database')
response = client.read(20)
puts "Received: #{response}"
end
Net::TCPClient automatically tries each server in turn, should it fail to connect, or if the connection is lost the next server is tried immediately.
Net::TCPClient detects DNS entries that have multiple IP Addresses associated with them and adds each of the ip addresses for the single DNS name to the list of servers to try to connect to.
If a server is unavailable, cannot connect, or the connection is lost, the next server is immediately tried. Once all servers have been exhausted, it will keep trying to connect, starting with the first server again.
When a connection is first established, and every time a connection is lost, Net::TCPClient uses connection policies to determine which server to connect to.
Using the connection policies client TCP connections can be balanced across multiple servers.
Servers are tried in the order they were supplied.
tcp_client = Net::TCPClient.new(
servers: ['server1:3300', 'server2:3300', 'server3:3600']
)
The servers will tried in the following order:
server1
, server2
, server3
:ordered
is the default, but can be explicitly defined follows:
tcp_client = Net::TCPClient.new(
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
policy: :ordered
)
Servers are tried in a Random order.
tcp_client = Net::TCPClient.new(
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
policy: :random
)
No server is tried again until all of the others have been tried first.
Example run, the servers could be tried in the following order:
server3
, server1
, server2
Supply your own custom order / load balancing algorithm for connecting to servers:
Example:
tcp_client = Net::TCPClient.new(
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
policy: -> addresses, count do
# Return nil after the last address has been tried so that retry logic can take over
if count <= address.size
addresses.sample
end
end
)
The above example returns addresses in random order without checking if a host name has been used before.
It is important to check the count so that once all servers have been tried, it should return nil so that the retry logic can take over. Otherwise it will constantly try to connect to the servers without the retry delays etc.
Example run, the servers could be tried in the following order:
server3
, server1
, server3
If a connection cannot be established to any servers in the list Net::TCPClient will retry from the first server. This retry behavior can be controlled using the following options:
connect_retry_count
[Integer]
connect_retry_interval
[Float]
retry_count
[Integer]
A server will only be retried again using the retry controls above once all other servers in the list have been exhausted.
This means that if a connection is lost to a server that it will try to connect to a different server, not the same server unless it is the only server in the list.
If there are multiple servers in the list it is important to keep the connect_timeout
low otherwise
it can take a long time to find the next available server.
To transparently handle when a connection is lost after it has been established
wrap calls that can be retried with retry_on_connection_failure
.
Net::TCPClient.connect(
server: 'localhost:3300',
connect_retry_interval: 0.1,
connect_retry_count: 5
) do |client|
# If the connection is lost, create a new one and retry the write
client.retry_on_connection_failure do
client.write('How many users available?')
response = client.read(20)
puts "Received: #{response}"
end
end
If the connection is lost during either the write
or the read
above the
entire block will be re-tried once the connection has been re-stablished.
Any time a connection has been established a callback can be called to handle activities such as:
tcp_client = Net::TCPClient.new(
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
on_connect: -> do |client|
client.write('My username and password')
result = client.read(2)
raise "Authentication failed" if result != 'OK'
end
)
tcp_client = Net::TCPClient.new(
servers: ['server1:3300', 'server2:3300', 'server3:3600'],
on_connect: -> do |client|
# Set the sequence number to 0
client.user_data = 0
end
)
tcp_client.retry_on_connection_failure do
# Write with the sequence number
tcp_client.write("#{tcp_client.user_data} hello")
result = tcp_client.receive(30)
# Increment sequence number after every call to the server
tcp_client.user_data += 1
end
Net::TCPClient is actively being used in a high performance, highly concurrent production environments. The resilient capabilities of Net::TCPClient are put to the test on a daily basis, including connections over the internet between remote data centers.
gem install net_tcp_client
To enable logging add Semantic Logger:
gem install semantic_logger
Or, add the following lines to you Gemfile
:
gem 'semantic_logger'
gem 'net_tcp_client'
To configure a stand-alone application for Semantic Logger:
require 'semantic_logger'
# Set the global default log level
SemanticLogger.default_level = :trace
# Log to a file, and use the colorized formatter
SemanticLogger.add_appender(file_name: 'development.log', formatter: :color)
If running Rails, see: Semantic Logger Rails
Join the Gitter chat session if you have any questions.
Issues / bugs can be reported via Github issues.
The following breaking changes have been made with V2:
ResilientSocket::TCPClient has been renamed to Net::TCPClient.
The API is exactly the same, just with a new namespace. Please upgrade to the new
net_tcp_client
gem and replace all occurrences of ResilientSocket::TCPClient
with Net::TCPClient
in your code.
Tested and supported on the following Ruby platforms:
There is a soft dependency on Semantic Logger. It will use SemanticLogger only if it is already available, otherwise any other standard Ruby logger can be used.
Be sure to place the semantic_logger
gem dependency before net_tcp_client
in your Gemfile.
This project uses Semantic Versioning.
FAQs
Unknown package
We found that net_tcp_client demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.