Giter Site home page Giter Site logo

multi-ping's Introduction

Romana - network and security automation solution for cloud native applications

Romana is a network and security automation solution for cloud native applications.

  • Romana automates the creation of isolated cloud native networks and secures applications with a distributed firewall that applies access control policies consistently across all endpoints (pods or VMs) and services, wherever they run.
  • Through Romana's topology aware IPAM, endpoints receive natively routable addresses: No overlays or tunnels are required, increasing performance and providing operational simplicity.
  • Because IP addresses are assigned with network topology in mind, routes within the network are highly aggregated, reducing the impact on networking hardware, and allowing more secure configurations.
  • Supports Kubernetes and OpenStack clusters, on premise or on AWS.

Installation

To get started with Romana on Kubernetes, go here.

For OpenStack installations, please contact us by email or on Slack.

We are working on more detailed documentation to cover all the features and installation methods. Reach out to the team via email, Slack or GitHub if you need some help in the meantime.

Additional documentation

Visit http://romana.readthedocs.io/ for the complete documentation.

Code

This repository contains the documentation and installation tools for the Romana project. You can find the application code in the core repository.

Latest stable release: 2.0

Contact Us

multi-ping's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

multi-ping's Issues

getaddrinfo failed when pinging by hostname and host can't be resolved

Hi, I have several computers I need to ping and not all of them are online all the time. I noticed that when I run my program with these hosts, it exits with an error rather than saying the host didn't respond. I don't think that the entire ping job should end when one hostname from the list can't be resolved. Can these offline hosts just be returned along with others that didn't respond?

Here is the traceback

Traceback (most recent call last):
File "systool.py", line 298, in
main()
File "systool.py", line 267, in main
living_hosts = heartbeat(hosts)
File "systool.py", line 198, in heartbeat
ping = MultiPing(hosts)
File "C:\Users\user\AppData\Local\Programs\Python\Python36\lib\site-packages\multiping_init_.py", line 85, in init
addr_info = socket.getaddrinfo(d, None)
File "C:\Users\user\AppData\Local\Programs\Python\Python36\lib\socket.py", line 745, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 11001] getaddrinfo failed

MultiPingSocketError while django testing app development on local server

After manage.py runserver getting the following error.
I have created a data model from where I am fetching the value of the switch_ip in the view function and then calling the script named as ping.py with the function named as job. And in ping.py I am using multiping. But facing the below error.

10.255.42.123
hello
Internal Server Error: /network_monitoring
Traceback (most recent call last):
File "C:\Users\sidde\AppData\Local\Programs\Python\Python38\lib\site-packages\multiping_init_.py", line 104, in init
addr_info = socket.getaddrinfo(d, None)
File "C:\Users\sidde\AppData\Local\Programs\Python\Python38\lib\socket.py", line 834, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 11001] getaddrinfo failed

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:\Users\sidde\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\sidde\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\sidde\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\base.py", line 113, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\sidde\PycharmProjects\ether_discovery_project\ether_discovery_project\ether_discovery\views.py", line 50, in network_monitoring
a=ping.job(switch_ip_a2)
File "C:\Users\sidde\PycharmProjects\ether_discovery_project\ether_discovery_project\python_scripts\ping.py", line 18, in job
mp = MultiPing(IP)
File "C:\Users\sidde\AppData\Local\Programs\Python\Python38\lib\site-packages\multiping_init
.py", line 135, in init
raise MultiPingSocketError("Cannot lookup '%s'" % d)
multiping.MultiPingSocketError: Cannot lookup '1'
[04/May/2020 17:09:14] "GET /network_monitoring HTTP/1.1" 500 88939

Multiple uses of MultiPing() // return of receive()

The same MultiPing instance can't be used twice.
It's ugly to create a new object if you want to ping to the same address again.
At least some kind of reset() method would be great.

    pinger = MultiPing(['192.168.112.1'])

    pinger.send()
    ok, nok = pinger.receive(2)
    print(ok, nok)

    time.sleep(3)

    pinger.send()
    ok, nok = pinger.receive(2)
    print(ok, nok)

multiping.MultiPingError: No responses pending


receive() returns a tuple[dict, list].
Is there a reason for that? If i send two packets at once, what seems to be allowed in this way, only one response per given destination is being returned.
MultiPing(['192.168.112.1', '192.168.112.1'])

{'192.168.112.1': 0.0020570755004882812} []

Ping times incorrect

All the response times from using MultiPing on a set of remove hosts seem to be broadly the same and not the actual ping time of each server. For example the results are all approx. 5ms when the actual ping time to each host are 34ms, 50ms, etc.

This does not seem to be giving ping times that relate to the actual host ping times.

Running on Raspberry Pi 64-bit Debian 12 Bookworm.

Feature request: Add support for >65535 addresses

Not saying that they need to be handled simultaneously, but if the library could handle breaking up a /8 into the requisite /16 or /17 chunks internally, it would be really helpful and useful, even if it's not as fast as with <65535 addresses.

I'm currently going to have to do this in my code for a /12.

Bug when only pinging ipv6 addresses

Hi! I want to ping ipv6 addresses only but when I do I don't get a response before the end of the timeout because it seems to wait in the first part of _read_all_from_socket() for an ipv4.

Example :
mp = MultiPing(['2620:0:ccc::2']) mp.send() a,b=mp.receive(5)

returns
a: {'2620:0:ccc::2': 5.005456924438477} b: []

But, when I run this :
mp = MultiPing(['127.0.0.1', '2620:0:ccc::2']) mp.send() a,b=mp.receive(5)

It returns :
a: {'2620:0:ccc::2': 0.028293848037719727, '127.0.0.1': 0.0002079010009765625} b: []

IPv6 support

I needed basic IPv6 support and ended up enhancing your module: https://github.com/mwiget/multi-ping/tree/inet6

Is this something of interest and would it need to be configurable to avoid unintentional name resolution to IPv6? If yes, I'd be happy to start a pull request for further discussion.

My use case btw is in network automation, where I check a list of next hop IPv4 and IPv6 addresses before adding routes. I don't need DNS support, but had to replace gethostbyname() with an IPv6 capable alternative (getaddrinfo()).

Non-blocking socket operation error on Windows

I'm getting the following error from the receive() method when running on Windows:

ERROR: [Errno 10035] A non-blocking socket operation could not be completed immediately

My understanding is that 10035 indicates the end of data. The error does not occur if I make the following change in _read_all_from_socket():

if e.errno == 11:
to
if e.errno == 11 or e.errno ==10035

Burst ICMP request lead to packet loss

When pinging a lots of address (more than 500) on some system/network the burst ICMP request can led to a lot of packet loss. This can be avoided by adding a small delay between each ICMP request (1-5 ms). This has been observed on a Windows Server 2012 R2 Standard (64 bit).

Demo.py NameError

NameError: name 'no_responses' is not defined
no_responses should change to no_response

Max targets?

Is there a max amount of addresses this can ping? I tried using the multi_ping method and giving it 10 retries with 10 seconds for a list of 488 targets, but i'm always getting between 210 and 220 without any response data.

Any ideas? Love this tool otherwise!

Get error "PermissionError: [Errno 13] Permission denied" for some network

For subnetwork 192.168.133.0/24 I get error, when others works fine:
ggadminuser@GGAppSrv:~/snmp-v2$ sudo python3 main.py 192.168.133.0/24 ['192.168.133.0', '192.168.133.1', '192.168.133.2', '192.168.133.3', '192.168.133.4', '192.168.133.5', '192.168.133.6', '192.168.133.7', '192.168.133.8', '192.168.133.9', '192.168.133.10', '192.168.133.11', '192.168.133.12', '192.168.133.13', '192.168.133.14', '192.168.133.15', '192.168.133.16', '192.168.133.17', '192.168.133.18', '192.168.133.19', '192.168.133.20', '192.168.133.21', '192.168.133.22', '192.168.133.23', '192.168.133.24', '192.168.133.25', '192.168.133.26', '192.168.133.27', '192.168.133.28', '192.168.133.29', '192.168.133.30', '192.168.133.31', '192.168.133.32', '192.168.133.33', '192.168.133.34', '192.168.133.35', '192.168.133.36', '192.168.133.37', '192.168.133.38', '192.168.133.39', '192.168.133.40', '192.168.133.41', '192.168.133.42', '192.168.133.43', '192.168.133.44', '192.168.133.45', '192.168.133.46', '192.168.133.47', '192.168.133.48', '192.168.133.49', '192.168.133.50', '192.168.133.51', '192.168.133.52', '192.168.133.53', '192.168.133.54', '192.168.133.55', '192.168.133.56', '192.168.133.57', '192.168.133.58', '192.168.133.59', '192.168.133.60', '192.168.133.61', '192.168.133.62', '192.168.133.63', '192.168.133.64', '192.168.133.65', '192.168.133.66', '192.168.133.67', '192.168.133.68', '192.168.133.69', '192.168.133.70', '192.168.133.71', '192.168.133.72', '192.168.133.73', '192.168.133.74', '192.168.133.75', '192.168.133.76', '192.168.133.77', '192.168.133.78', '192.168.133.79', '192.168.133.80', '192.168.133.81', '192.168.133.82', '192.168.133.83', '192.168.133.84', '192.168.133.85', '192.168.133.86', '192.168.133.87', '192.168.133.88', '192.168.133.89', '192.168.133.90', '192.168.133.91', '192.168.133.92', '192.168.133.93', '192.168.133.94', '192.168.133.95', '192.168.133.96', '192.168.133.97', '192.168.133.98', '192.168.133.99', '192.168.133.100', '192.168.133.101', '192.168.133.102', '192.168.133.103', '192.168.133.104', '192.168.133.105', '192.168.133.106', '192.168.133.107', '192.168.133.108', '192.168.133.109', '192.168.133.110', '192.168.133.111', '192.168.133.112', '192.168.133.113', '192.168.133.114', '192.168.133.115', '192.168.133.116', '192.168.133.117', '192.168.133.118', '192.168.133.119', '192.168.133.120', '192.168.133.121', '192.168.133.122', '192.168.133.123', '192.168.133.124', '192.168.133.125', '192.168.133.126', '192.168.133.127', '192.168.133.128', '192.168.133.129', '192.168.133.130', '192.168.133.131', '192.168.133.132', '192.168.133.133', '192.168.133.134', '192.168.133.135', '192.168.133.136', '192.168.133.137', '192.168.133.138', '192.168.133.139', '192.168.133.140', '192.168.133.141', '192.168.133.142', '192.168.133.143', '192.168.133.144', '192.168.133.145', '192.168.133.146', '192.168.133.147', '192.168.133.148', '192.168.133.149', '192.168.133.150', '192.168.133.151', '192.168.133.152', '192.168.133.153', '192.168.133.154', '192.168.133.155', '192.168.133.156', '192.168.133.157', '192.168.133.158', '192.168.133.159', '192.168.133.160', '192.168.133.161', '192.168.133.162', '192.168.133.163', '192.168.133.164', '192.168.133.165', '192.168.133.166', '192.168.133.167', '192.168.133.168', '192.168.133.169', '192.168.133.170', '192.168.133.171', '192.168.133.172', '192.168.133.173', '192.168.133.174', '192.168.133.175', '192.168.133.176', '192.168.133.177', '192.168.133.178', '192.168.133.179', '192.168.133.180', '192.168.133.181', '192.168.133.182', '192.168.133.183', '192.168.133.184', '192.168.133.185', '192.168.133.186', '192.168.133.187', '192.168.133.188', '192.168.133.189', '192.168.133.190', '192.168.133.191', '192.168.133.192', '192.168.133.193', '192.168.133.194', '192.168.133.195', '192.168.133.196', '192.168.133.197', '192.168.133.198', '192.168.133.199', '192.168.133.200', '192.168.133.201', '192.168.133.202', '192.168.133.203', '192.168.133.204', '192.168.133.205', '192.168.133.206', '192.168.133.207', '192.168.133.208', '192.168.133.209', '192.168.133.210', '192.168.133.211', '192.168.133.212', '192.168.133.213', '192.168.133.214', '192.168.133.215', '192.168.133.216', '192.168.133.217', '192.168.133.218', '192.168.133.219', '192.168.133.220', '192.168.133.221', '192.168.133.222', '192.168.133.223', '192.168.133.224', '192.168.133.225', '192.168.133.226', '192.168.133.227', '192.168.133.228', '192.168.133.229', '192.168.133.230', '192.168.133.231', '192.168.133.232', '192.168.133.233', '192.168.133.234', '192.168.133.235', '192.168.133.236', '192.168.133.237', '192.168.133.238', '192.168.133.239', '192.168.133.240', '192.168.133.241', '192.168.133.242', '192.168.133.243', '192.168.133.244', '192.168.133.245', '192.168.133.246', '192.168.133.247', '192.168.133.248', '192.168.133.249', '192.168.133.250', '192.168.133.251', '192.168.133.252', '192.168.133.253', '192.168.133.254', '192.168.133.255'] Traceback (most recent call last): File "main.py", line 31, in <module> main(sys.argv[1:]) File "main.py", line 18, in main snmp_unavailable_ips, created_snmp_cfgs = search_by_snmp(args_to_ips(args), settings) File "/home/ggadminuser/snmp-v2/search_by_snmp.py", line 91, in search_by_snmp int(settings["ping-retries"]))) File "/home/ggadminuser/snmp-v2/search_by_snmp.py", line 72, in search_alive_by_ping available, dead = multi_ping(hosts, timeout, retries) File "/home/ggadminuser/.local/lib/python3.6/site-packages/multiping/__init__.py", line 484, in multi_ping mp.send() File "/home/ggadminuser/.local/lib/python3.6/site-packages/multiping/__init__.py", line 296, in send self._send_ping(addr, payload=struct.pack("d", time.time())) File "/home/ggadminuser/.local/lib/python3.6/site-packages/multiping/__init__.py", line 259, in _send_ping self._sock.sendto(full_pkt, full_dest_addr) PermissionError: [Errno 13] Permission denied

My network interfaces:
`ggadminuser@GGAppSrv:~/snmp-v2$ ifconfig -a
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.133.128 netmask 255.255.255.0 broadcast 192.168.133.255
inet6 fe80::20c:29ff:fe53:4041 prefixlen 64 scopeid 0x20
ether 00:0c:29:53:40:41 txqueuelen 1000 (Ethernet)
RX packets 48323 bytes 22660264 (22.6 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 208841 bytes 16291320 (16.2 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

ens38: flags=4098<BROADCAST,MULTICAST> mtu 1500
ether 00:0c:29:53:40:4b txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 1000 (Local Loopback)
RX packets 946 bytes 81224 (81.2 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 946 bytes 81224 (81.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
`

OSError: [WinError 10040]

Running the multi_ping on a Windows Server 2012 R2 Standard (64 bit) with Python 3.5.2, I got the following error:


Traceback (most recent call last):
File "", line 1, in
File "D:\venv\lib\site-packages\multiping_init_.py", line 485, in multi_ping
single_results, no_results = mp.receive(retry_timeout)
File "D:\venv\lib\site-packages\multiping_init_.py", line 399, in receive
pkts = self.read_all_from_socket(remaining_time)
File "D:\venv\lib\site-packages\multiping_init
.py", line 320, in _read_all_from_socket
p = self._sock.recv(64)
OSError: [WinError 10040] A message sent on a datagram socket was larger than the internal message buffer or some other
network limit, or the buffer used to receive a datagram into was smaller than the datagram itself


Note that the IP address that I try to ping is not reachable, it works when I ping an address that is reachable. What is weird is that I have the library installed on two server which should be identical (save OS and same Python version) and it only failed on one server.

I could work around the issue by increasing the socket receive buffer to 128 bytes: File "D:\venv\lib\site-packages\multiping\__init__.py", line 320, in _read_all_from_socket p = self._sock.recv(128)

Host-unreachable replies

Looks like replies to ICMP Echo-request messages (ping) which are not Echo-reply are not being handled properly in the receive method and can be interpreted as a positive reply. Specifically, pings to some addresses can return an ICMP host-unreachable message, which, for my specific purpose, should be interpreted as a non-reply. As a quick fix, I added an
else: pass
clause after the
if pkt[_ICMPV6_HDR_OFFSET] == _ICMPV6_ECHO_REPLY:
...
elif pkt[_ICMP_HDR_OFFSET] == _ICMP_ECHO_REPLY:
...
clauses, but I would also suggest a better check for IP4 vs. IP6 packets instead of looking at a byte at a particular location.

multi_ping retry not working correctly

When a request times out, a retry is correctly sent with a new ID but the receive function always looks for the old ID. This result by sending as many retry as specified in the multi_ping function and returning a failed ping as soon as at least one packet loss occurred, even if the first retry was successful.

cannot change the packet size

I need to ping a large number of hosts that are out of our network and need to reduce the packet size. the hosts, in this case, are our customer's devices and the customers will have to pay for this additional data usage. so we want to limit this to the minimum.

AttributeError with 1.2.0 release on Windows

Hi, the latest release (1.1.0) throws an error on Windows 7 under python 3.6.4 and under python 3.5.5. The previous release (1.0.7) does not. Here is the error when running the example code from the readme:

Traceback (most recent call last):
  File "pingtest.py", line 4, in <module>
    mp = MultiPing(["8.8.8.8", "youtube.com", "127.0.0.1"])
  File "C:\ProgramData\Miniconda3x86\envs\graphite\lib\site-packages\multiping\__init__.py", line 119, in __init__
    self._sock6 = self._open_icmp_socket(socket.AF_INET6)
  File "C:\ProgramData\Miniconda3x86\envs\graphite\lib\site-packages\multiping\__init__.py", line 130, in _open_icmp_socket
    else socket.IPPROTO_ICMPV6
AttributeError: module 'socket' has no attribute 'IPPROTO_ICMPV6'

unclosed socket

i got this error when i start using multi_ping inside threading.Timer

image

image

in linux the same.

I think this can help:

class MultiPing(object):
def del(self):

   self._sock.close()
   self._sock6.close()

Bug: RTT is incorrect for IPv6 Packets

Hi there,

having two separate timeouts for IPv4 and IPv6 is not a good idea. In the worst case, the IPv4 socket will block until the timeout is due and only then the _sock6.recv() is called. This leads to incorrect RTT values for IPv6 packets.

The worst case can be easily observed if only IPv6 nodes are pinged. As no IPv4 responses arrive, the sock.recv() blocks until the timeout is due. Here is an example:

import multiping
mp = multiping.MultiPing(["2001:4860:4860::8888"])
mp.send()
mp.receive(30)
({'2001:4860:4860::8888': 33.48264455795288}, [])

As you can see, multiping said, that the response was after ~33 seconds.

lemoer@orange ~ [1]> sudo tcpdump -n -i wlp3s0 host 2001:4860:4860::8888
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlp3s0, link-type EN10MB (Ethernet), capture size 262144 bytes
02:33:44.109704 IP6 .......... > 2001:4860:4860::8888: ICMP6, echo request, seq 0, length 16
02:33:44.169743 IP6 2001:4860:4860::8888 > ..........: ICMP6, echo reply, seq 0, length 16

Observing the scenario in tcpdump reveals that this is not true and the response was already there in a couple of microseconds.

As I am only expecting IPv6 hosts in my current usecase, I wrote this small patch that disables the IPv4 loop, when only IPv6 destinations are pinged. However this is not a suitable approach for upstream. I suggest using poll() here.

Kind regards,
lemoer

Phantom host activity

Apparently, due to the fact that a host is considered to be active only by coincidence of pkt_id, when several copies of the program are launched in parallel, the false definition of inaccessible hosts as active occurs.
If run two copies in parallel, which should check hosts in different subnets, two ICMP-requests are sent to the network to different hosts, but sometimes the IDs in such requests coincide. This automatically leads to the identification of both hosts as active.

Time in between pings

I hired someone to write me a script that used this tool. Is there a way for me to limit the time in between the pings?

Exception when none of the hostnames can be resolved

If the list of host names contains only addresses that cannot be resolved, and ignore_lookup_errors is True, multi_ping fails.

#!/usr/bin/python                                                                                                                                                                                                                                                               
from multiping import multi_ping                                                                                                        
responses, no_responses = multi_ping(["no-such-host", "also-this-doesnt-exist"], timeout=2, retry=0, ignore_lookup_errors=True)         
Traceback (most recent call last):
  File "./test_multiping.py", line 4, in <module>
    responses, no_responses = multi_ping(["no-such-host", "also-this-doesnt-exist"], timeout=2, retry=0, ignore_lookup_errors=True)
  File "/usr/local/lib/python2.7/dist-packages/multiping/__init__.py", line 485, in multi_ping
    single_results, no_results = mp.receive(retry_timeout)
  File "/usr/local/lib/python2.7/dist-packages/multiping/__init__.py", line 376, in receive
    raise MultiPingError("No requests have been sent, yet.")
multiping.MultiPingError: No requests have been sent, yet.

The correct behavior would be to return the failing host names in the no_response array.

Update readme examples for Python 3

The code examples provided in README.md for Using MultiPing are not compatible with Python 3, as they use Python 2 style print statements.

The receive() function returns a tuple containing a results dictionary (addresses and response times) as well as a list of addresses that did not respond in time. The results may be processed like this:

...

for addr, rtt in responses.items():
    print "%s responded in %f seconds" % (addr, rtt)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.