Hi
Today I’ll show you how to set up your laptop or PC as a server with a dynamic IPv6 address and access it over the internet.
First: To access a server over the internet, you need to register your desired name with an ICANN-accredited registrar like Namecheap, GoDaddy, or Porkbun, etc. This will cost you between $10 and $20 or more annually. Not much, but still a bit annoying. Not because of the sum itself, but because the name doesn’t have to be registered. Otherwise, you’d have to buy it for a considerable sum in US dollars (if it’s even for sale) or find a different unregistered name. Then you need to request a static IPv6 address from your internet provider, which will remain unchanged even after you shut down your server. This feature will cost you a few extra dollars.
Normally the mere-mortals like us subscribe Internet provider and get a dynamic IP, formerly IPv4, now IPv6. The main difference lies in the sheer number of addresses: IPv6 covers trillions of addresses, while IPv4 only covers about 4 billion. So, IPv6 allows providers to directly assign an IPv6 address to their customers without complicated mapping or similar processes. This means that a customer with IPv6 can be reached directly via the Internet without their IP address having to be “forwarded” with a port as with IPv4 (hence the name “port forwarding”). A nice feature for private users, but actually useless, since the IPv6 address consists of 32 hexadecimal digits, separated by a semicolon ( : ) after every four digits. Difficult to remember and prone to typos. IPv6 example:
2a02:8071:5302:216b:51ad:fde8:2492:ee55
This is also one reason why all websites are accessible via an easy-to-remember domain name such as “daynhauhoc.com”. The internet finds a domain name using the Domain Name System (DNS), which acts as a phonebook, translating human-readable names (e.g., “daynhauhoc.com”) into IP addresses. This process involves checking local cache, querying recursive resolvers (often via your ISP), and communicating with root, top-level domain (TLD), and authoritative nameservers to fetch the IP address and load the site. This naturally incurs annual costs.
I’ve found a solution that bypasses the DNS and makes the demand for Domain-Name registration superfluous. Instead of a registered domain name via DNS, etc. a name agreed upon with a server can be broadcast. The server with the broadcast ID then responds with its IPv6 address and the associated port, allowing the client to access it legally and programmatically using this IP address and port. The package is called joesocket and contains three Java APIs:
- InetSocket: an extension of Java Socket,
- InetServerSocket: an extension of java ServerSocket,
- IPv6: This API extracts the valid dynamic IPv6 address that your ISP has assigned to your router (and your local computer).
You can download the joesocket.jar from GitHub. If you want the source codes, put a message in my DNH inbox.
As extensions of Java Socket and ServerSocket, the two aforementioned sockets inherit all the functionalities of Socket and ServerSocket, respectively. Programming examples:
TestSocket.java as Client with InetSocket:
import java.net.*;
// include the joesocket package
import joesocket.InetSocket;
import joesocket.IPv6;
//
public class TestSocket {
public static void main(String... argv) throws Exception {
if (argv.length != 2) {
System.out.println("java TestSocket HostID RetryNumber");
System.exit(0);
}
new TestSocket(argv);
}
//
public TestSocket(String... argv) throws Exception {
// instantiate InetSocket
InetSocket soc = new InetSocket(argv[0], Integer.parseInt(argv[1]));
// using InetSocket and IPv6 methods
System.out.println("Client IPv6:"+IPv6.getIPv6());
System.out.println("Host_IP: "+soc.getHostIP()+
"\nHostPort: "+soc.getHostPort()+
"\n\nQ or q to terminate the communication"+
"\n\nX or x to exit the communication and server");
byte[] bb = new byte[512];
// the rest is Java Socket's methods.
while (true) try {
int n = System.in.read(bb);
soc.getOutputStream().write(bb, 0, n);
n = soc.getInputStream().read(bb);
System.out.println(new String(bb, 0, n));
// quit or exit if the last letter is q/Q or x/X
if (bb[n-1] == 'q' || bb[n-1] == 'Q' || bb[n-1] == 'x' || bb[n-1] == 'X') break;
} catch (Exception ex) { }
try {
soc.close();
} catch (Exception ex) { }
System.exit(0);
}
}
TestServer.java as server with InetServerSocket
import java.net.*;
// include the joesocket package
import joesocket.InetServerSocket;
//
public class TestServer {
public static void main(String... argv) throws Exception {
if (argv.length != 2) {
System.out.println("java TestServer HostID PortNumber");
System.exit(0);
}
new TestServer(argv);
}
//
private InetServerSocket svr;
public TestServer(String... argv) throws Exception {
// instantiate InetServerSocket with Host ID and Port
svr = new InetServerSocket(argv[0], Integer.parseInt(argv[1]));
System.out.println("MyServer:"+argv[0]+"@"+argv[1]+" is started..."+
"Press CTRL+C to exit");
try {
while (true) {
// inheritted ServerSocket's accept()
(new Test(svr.accept())).start();
}
} catch (Exception ex) { }
System.exit(0);
}
// full java Socket
private class Test extends Thread {
public Test(Socket soc) {
this.soc = soc;
}
private Socket soc;
public void run() {
byte[] bb = new byte[512];
byte[] BB = new byte[512];
// quit or exit if the 1st letter is q/Q (thread) or x/X (Server's exit)
while (bb[0] != 'q' && bb[0] != 'Q' && bb[0] != 'x' && bb[0] != 'X') try {
int n = soc.getInputStream().read(bb);
// reverse the message and ...
for (int i = 0, j = n-1; i < n; ++i, --j) BB[i] = bb[j];
System.out.println(new String(bb, 0, n));
// send it back to Client
soc.getOutputStream().write(BB, 0, n);
} catch (Exception ex) { }
System.out.println("Client quitted.");
try {
soc.close();
if (bb[0] == 'x' || bb[0] == 'X') svr.close();
} catch (Exception ex) { }
}
}
}
The following image shows you an Ubuntu Client accessing a Windows 11 Server via IPv6
Constructors
InetServerSocket(java.lang.String hostID, int port)
* Method Summary
All Methods [Instance Methods] [Concrete Methods] Modifier and Type Method Description
void close() // close (overwrite)
java.lang.String getHostID() // getHostID returns Host ID
java.lang.String getServerIP() // getServerIP returns IPv6 of hostID
int getServerPort() // getServerPort returns port of hostID
---------------------------------------------------------------------------------
Constructor
InetSocket(java.lang.String hostID, int retries)
* Method Summary
All Methods [Instance Methods] [Concrete Methods] Modifier and Type Method Description
java.lang.String getHostIP() // |getHostIP returns IPv6 of hostID
int getHostPort() // getHostPort returns port of hostID
int getRetries() // getRetries returns the number of retries
---------------------------------------------------------------------------------
Constructor
IPv6()
* Method Summary
All Methods [Static Methods] [Concrete Methods] |Modifier and Type Method Description
static java.lang.String getIPv6() // getIPv6 of this local computer

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?