三个Java类实现内网服务提供到公网上(需要公网IP)

在这里插入图片描述

上面为类路径

需要在公网运行PublicServer
在有服务的内网上运行LocalServer

流程图

在这里插入图片描述

下面代码段

公网服务获取类PublicServer

package Server;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class PublicServer {
    private ServerSocket serverSocket;
    public  MyServerClient myServerClient;
    private void CreatePublic(int Port) throws IOException {
        System.out.println("服务器启动成功.........");
        //监听服务器
        serverSocket=new ServerSocket(Port);
        while (true){//接受浏览器请求
            Socket socket=serverSocket.accept();
            System.out.println("请求!");
            new MyServer(socket).run();//提交socket线程进行读写
        }
    }
    private void CreateChannel(int Port) throws IOException {
        myServerClient=new MyServerClient(Port);//隧道开启
        System.out.println("隧道启动");
        myServerClient.KeepAlice();//隧道保持长链
    }
    class MyServer extends Thread {
        private Socket accept;
        MyServer(Socket accept){
            this.accept=accept;
        }
        @Override
        public void run() {
            try {
                InputStream inputStream = accept.getInputStream();
                String RequestMessage;
                accept.setSoTimeout(1000);//设置读取超时,否则堵塞
                try {
                    byte b[]=new byte[1024];
                    try {
                        inputStream.read(b);
                    }catch (Exception e){
                    }
                    RequestMessage=new String(b).split("\r\n")[0];//仅获取请求中的第一行
                    System.out.println(RequestMessage);
                    accept.getOutputStream().write("HTTP/1.1 200 OK  \r\n\r\n".getBytes());//输出头部200
                    if(!"".equals(RequestMessage)){//非空请求进行Channel传输
                            myServerClient.GetAndSend(RequestMessage.split(" ")[1],accept.getOutputStream());
                    }else{
                        System.out.println("空请求");
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    accept.close();//关闭
                }

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

    public static void main(String[] args) throws IOException {
        if(args.length!=2){
            System.out.println("参数不足使用默认端口号和地址");
            System.out.println("SPort:"+ 7456+",CPort:"+8080);
            PublicServer server=new PublicServer();
            server.CreateChannel(7456);
            server.CreatePublic(8080);
        }else{
            PublicServer server=new PublicServer();
            server.CreateChannel(Integer.parseInt(args[0]));
            server.CreatePublic(Integer.parseInt(args[1]));
        }
    }
}

本地服务提供类LocalServer

package Client;

import java.io.*;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;

public class LocalServer {//进行Channel连接,提供内网服务
    Socket socket;
//    static int SPort=8888;
    static int SPort=7456;
    static  int CPort=5555;
     static boolean check=false;
    static String ip="172.81.247.205";
//    static String ip="127.0.0.1";
    LocalServer(int sport,int cport,String ip) throws Exception {
        SPort=sport;
        CPort=cport;
        this.ip=ip; init();
    }
    LocalServer() throws Exception {
        init();
    }
    public void init() throws Exception {//进行Channel连接
        while (true){
            try {
                socket=new Socket(ip,SPort);
                break;
            }catch (ConnectException CE){
                continue;
            }
        }
        System.out.println("隧道已连接");
        while (true){
//            接受Channel参数请求
            String param=new DataInputStream(socket.getInputStream()).readUTF();
            if(param.trim().equals("")){//保持连接
                continue;
            }
            System.out.println("param"+param);
            new SendData(GetOneStream(param)).run();//开启线程回应Channel并且阻塞
            while (check){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    InputStream GetOneStream(String param) throws Exception {//获取Stream流
        URL url=new URL("http://127.0.0.1:"+CPort+param);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(6 * 1000);
        return conn.getInputStream();
    }
    class SendData extends Thread{
        InputStream is;
        SendData(InputStream is){
            this.is=is;
        }
        @Override
        public void run() {//与内网服务对接传输
            try {
                Socket s=new Socket(ip,SPort);
                check=true;
                int len=is.read();
                while (len!=-1){
                    s.getOutputStream().write(len);
                    len=is.read();
                }
                s.close();
                check=false;
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
    public static void main(String[] args) throws Exception {
        if(args.length!=3){
            System.out.println("参数不足使用默认端口号和地址");
            System.out.println("SPort:"+ SPort+",CPort:"+CPort+",ip:"+ip);
               while (true){
                   try {
                       new LocalServer();
                   }catch (Exception e){
                       System.out.println("隧道断开,重新连接");
                   }
               }

        }else{
            while (true){
                try {
                    new LocalServer(Integer.parseInt(args[0]),Integer.parseInt(args[1]),args[2]);
                }catch (Exception e){
                    System.out.println("隧道断开,重新连接");
                }
            }
        }


    }
}


Channel类、SC之间的通讯类
MyServerClient

package Server;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyServerClient {//进行Channel连接,获取内网服务
    private  int Port;
    private static boolean check=false;
    public static String res="";
    public static ServerSocket serverSocket;
    public static Socket socket;
    MyServerClient(int  accept) throws IOException {//初始化Channel
        this.Port=accept;
        serverSocket=new ServerSocket(Port);
        System.out.println(Port+"隧道等待连接");
        socket=serverSocket.accept();
        System.out.println(Port+"隧道连接成功");
    }
    private final String NotFoundPage="<!DOCTYPE html>" +            "<html lang=\"en\">" +            "<head>" +            "    <meta charset=\"UTF-8\">" +            "    <meta http-equiv=\"Cache-Control\" content=\"max-age=7200\" />" +            "    <meta http-equiv=\"Expires\" content=\"Mon, 20 Jul 2013 23:00:00 GMT\" />" +            "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">" +            "    <title>404 not found</title>" +            "</head>" +            "<body style=\"display: flex;min-width: 300px;\">" +            "    <div style=\"margin-top: 0%;    width: 60%;    padding-left: 20%;\" >" +            "        <img style=\"width: 100%;\" src=\"404-l.jpg\" alt=\"\" srcset=\"\"/>" +            "        <div style=\"display: flex;\">" +            "            <span style=\"line-height: 64px;font-size: xxx-large;width: 50%;text-align: right;\">" +            "                404</span>" +            "                <img  style=\"width: 50%;max-width: 64px;\" src=\"404-r.png\" alt=\"\" srcset=\"\"/> </div>" +            "    </div>" +            "</body>" +            "</html>";
    private static void  GetData(String param,OutputStream os) throws IOException {//Channel核心:与内网服务通讯
        System.out.println("param"+param);
        new DataOutputStream(socket.getOutputStream()).writeUTF(param);//发送参数
        ReceiveData receiveData=new ReceiveData(os);//线程创建
        receiveData.run();//进行线程run
        while (check){// 等待堵塞
            try {
                Thread.sleep(10);
                if(receiveData.error){break;}
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static class ReceiveData extends Thread{//接受Channel回调的线程,与本地socket对接
        public boolean error=false;
        OutputStream os;
        ReceiveData(OutputStream os){
            this.os=os;
        }
        @Override
        public void run() {
            try {
                Socket s=serverSocket.accept();
                check=true;
                res="";
                    int len=s.getInputStream().read();
                    while (len!=-1){
                        os.write(len);
                        len=s.getInputStream().read();
                    }
                s.close();
                check=false;
            } catch (IOException e) {
                error=true;
//                e.printStackTrace();
            }

        }
    }
    public  void  GetAndSend(String param, OutputStream os)throws IOException  {//发送参数且返回到os中
            if(param.equals("/404-l.jpg")||param.equals("/404-r.png")){
                FileInputStream fis=new FileInputStream(param.substring(1));
                int len=fis.read();
                while (len!=-1){
                    os.write(len);
                    len=fis.read();
                }
                fis.close();

            }else if(param.endsWith("favicon.ico")){
                FileInputStream fis=new FileInputStream("favicon.ico");
                int len=fis.read();
                while (len!=-1){
                    os.write(len);
                    len=fis.read();
                }
                fis.close();
            }
            else{
                GetData(param,os);//这里为就可以,上面内容可以DIY设置
            }
    }
    public void KeepAlice(){//保持socket长连
        ExecutorService es =Executors.newCachedThreadPool();//创建Future非阻塞线程
        es.submit(()->{
            while (true){
                Thread.sleep(1000);
                try {
                    new DataOutputStream(socket.getOutputStream()).writeUTF("");//发送空字符判断socket是否断开
                }catch (Exception e){
                    System.err.println("内网服务异常断开,重连中");
                    socket=serverSocket.accept();//重连
                    System.err.println("内网服务恢复0");
                }

            }
        });
    }
}

已上传到GitHubEnter

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现本地IP服务器内网IP的互通,需要进行以下步骤: 1. 在云服务器的安全组中添加入站规则,允许本地IP地址的访问。 2. 在本地电脑中使用远程桌面软件连接云服务器,登录到服务器。 3. 在服务器中配置路由表,将本地IP地址和服务器内网IP地址进行映射。 4. 在本地电脑中配置路由表,将服务器内网IP地址和云服务器公网IP地址进行映射。 具体操作步骤如下: 1. 登录到阿里云的管理控制台,找到对应的云服务器实例,进入安全组页面,添加入站规则,允许从本地IP地址的访问。 2. 在本地电脑上使用远程桌面软件连接到云服务器,登录到服务器。 3. 在服务器中打开命令行终端,输入以下命令: ``` route -p add 本地IP地址 mask 子网掩码 服务器内网IP地址 ``` 其中,本地IP地址是指本地电脑的IP地址,子网掩码和服务器内网IP地址需要根据实际情况进行填写。该命令的作用是将本地IP地址和服务器内网IP地址进行映射,并添加到路由表中。 4. 在本地电脑上打开命令行终端,输入以下命令: ``` route -p add 服务器内网IP地址 mask 子网掩码 云服务器公网IP地址 ``` 其中,服务器内网IP地址和云服务器公网IP地址需要根据实际情况进行填写。该命令的作用是将服务器内网IP地址和云服务器公网IP地址进行映射,并添加到本地电脑的路由表中。 完成以上操作后,本地IP地址和服务器内网IP地址之间就可以实现互通了。如果需要多个本地电脑与云服务器进行通信,需要对每个本地电脑和服务器都进行以上操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值