Java实现两主机间的通信


在这里我有两点需要声明一下:

  • 这里所用的实现语言为 Java ,其实对于其他语言来说也同样适用,因为都是遵循 TCP/IP 协议;
  • 这里所提出的重点是“两主机”,两个不同的主机,意味着不同的IP地址,因为网上的代码大都是直接和本机进行通信,对于一个想通过实战了解TCP/IP的学生来说,总觉得差点什么。

背景知识

socket 是我们实现网络编程的重要工具。

外网IP和内网IP的区别,以下是同一时刻,本机查询到的IP地址。

内网IP为:192.168.1.112

外网IP为:121.193.129.130

为什么分外网IP和内网IP?

因为世界上所有的 IP 地址 加起来一共也就 42亿个左右,每个设备分配一个IP地址肯定是不够用的。

基本分法

将IP地址分为 公有IP 和 私有IP,每个个人所分配到的 IP 都是 私有IP 地址,每个 公有IP 下面会存在很多 私有IP, 如果我们想要访问网络,我们需要将访问的请求发给公有IP,在真正的网络上,你的请求使用的是公有IP,当然,如果想要真正找到另一个网络下的私有IP,并与之相互通信的话,需要将 IP 地址 和 Mac 地址相结合使用。但在使用socket没见过将Mac地址作为变量的操作,也就意味着在互联网的通信过程中(至少在使用socket的过程中)是以IP地址作为初次连接的。

内网和外网通信,这要看你的主动连接方客户端(client)和被动连接方服务端(server)个处于什么位置的。

  1. 假设 server 方在外网,client 方在内网,那么可以直接通过外网 IP 进行连接,不需要任何映射。
  2. 假设 server 方在内网,client 方不论是在内网还是在外网,都需要 Server 方的监听端口在外网能被访问到的权限,二者才能实现通信,可以通过端口映射的方法实现。

构建映射

说直白一些,就是你得有一个域名,可以用阿里云、腾讯云等,直接买个云服务器;我在这里用的是花生壳来实现内网穿透,构建一组映射,用买到的一组ip、端口号与本机的内网IP和端口号绑定构成一组映射,以实现可以外网访问内网的目的。但需要下载官网的phddns

官方文档,不是很麻烦:http://service.oray.com/question/8146.html

实战代码

SockerDemoServer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package hello;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketDemoServer {
public static void main(String[] args) {

ServerSocket serverSocket=null;
Socket clientSocket=null;
BufferedReader in=null;
int port=5000;
String str=null;

try{
InetAddress MyIP=InetAddress.getByName("192.168.43.36");
System.out.println(MyIP.getHostAddress());
try
{
int a = 55;
serverSocket=new ServerSocket(port); //创建服务器套接字
System.out.println("服务器开启,等待连接。。。");
clientSocket=serverSocket.accept();// 获得链接
//接收客户端发送的内容
in=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while(true)
{
str=in.readLine();
System.out.println("客户端发送的内容为:"+str);
Thread.sleep(2000);
}
}
catch(IOException | InterruptedException e)
{
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
catch (UnknownHostException e){
e.printStackTrace();
}


}
}

SocketDomeCilent.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package Test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketDomeCilent {

public static void main(String[] args)
{
Socket socket=null;
PrintWriter out=null;
BufferedReader in=null;

try{
InetAddress serverIP=InetAddress.getByName("wise-ant.picp.io");
int port=37190;
try
{
socket=new Socket(serverIP,port);
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
out=new PrintWriter(socket.getOutputStream(),true);
while(true)
{
int number=(int)(Math.random()*10)+1;
System.out.println("客户端正在发送的内容为:"+number);
out.println(number);
Thread.sleep(2000);
}
}
catch(IOException | InterruptedException e)
{
// TODO 自动生成的 catch 块
e.printStackTrace();
}

}
catch (UnknownHostException e) {
e.printStackTrace();
}



}

}

结果: