I made a simple client that sends and receives ICMP Echo Requests only once, so before I forget, I made a note of what I learned at the time of implementation and what I was careful about.
--Practice of network programming --Practice of gem package release --Distraction
--Return the success or failure of the ping (ICMP) result as true / false --The destination is specified as an IP address
--Specify destination by FQDN --Retry --Customization of transmitted data (ID specification, data part specification, etc.)
require "simple_ping" ping_client = SimplePing::Client.new(src_ip_addr: "192.168.1.100") puts ping_client.exec(dest_ip_addr: "192.168.1.101") ? "Success!" : "Failed.."
> sudo ruby ping.rb Success!
--You will be doing socket programming, but if you look at the Documentation, you will see some sockets. There are different types, but this time I will touch the ICMP header directly, so I will use
SOCK_RAW (Raw socket).
--When you finally send the data (send), you need to specify the data as a character string. There is. It is necessary to convert the prepared ICMP header data string into a character string one byte at a time according to the ASCII code.
--For example, if the "identifier" is 65, 65 will be ʻA
on the [ASCII code](http://www3.nit.ac.jp/~tamura/ex2/ascii.html), so ʻA You need to send.
--On Ruby, you can get characters according to ASCII code by using
65.chr etc. Reference
--However, note that the encoding type seems to be varies depending on the setting.
--When receiving, it is received by
recvfrom method, and the data can be obtained as a character string.
--The acquired data is in the form of including the IP header.
--Since the size of the IP header is basically 20 bytes (it seems that it may be different, but this time it is not assumed in the implementation), the ICMP header data can be acquired in order from the 21st byte.
--For example, if it is the "type" at the beginning of the ICMP header, you can get it as follows.
--You can convert a string to ASCII code with the
mesg, _ = socket.recvfrom(1500) mesg.bytes #=> 0
--At the time of reception, it is necessary to determine whether the received packet is the return packet of the transmitted item, but check the correspondence between transmission and reception by collating the "ID", "sequence number" and "type" (below). According to RFC)
The data contained in the received echo message must be returned as the data in the echo reply message. The identifier and sequence number are used by the echo sender to associate the echo request with its reply. An identifier may be used, for example the port number used by TCP or UDP to identify the session, or the sequence number may be incremented with each echo request. The echo-returning side returns the same value in the echo reply. http://srgia.com/docs/rfc792j.html
I made various Sockets with Ruby and played with them. --Qiita https://qiita.com/MikuriyaHiroshi/items/b0a40f5e7b7be1ef327c
[Ruby] Network program using RawSocket – Euniclus https://euniclus.com/article/ruby-port-scan/
BasicSocket # send (Ruby 2.7.0 Reference Manual) https://docs.ruby-lang.org/ja/latest/method/BasicSocket/i/send.html
Internet Control Message Protocol - Wikipedia https://ja.wikipedia.org/wiki/Internet_Control_Message_Protocol#ICMP%E3%83%98%E3%83%83%E3%83%80
Convert ASCII code and characters (ord, chr, bytes, unpack, codepoints) | Makumaku Ruby Note https://maku77.github.io/ruby/number/ascii-char.html
RFC792(INTERNET CONTROL MESASAGE PROTOCOL) http://srgia.com/docs/rfc792j.html