Java教程

Java-网络编程

本文主要是介绍Java-网络编程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

概述

  • 打电话 – 连接 – 接了 – 通话 TCP
  • 发短信 – 发送了就完事 – 接收 UDP
  • 网络编程的目的:
    • 传播交流信息,数据交换,通信
  • 前提:
    • 如何准确定位网络上的一台主机 192.168.16.124:端口 ,定位到这个计算机上的某个资源
    • 找到了这个主机,如何传输数据?
  • 网络编程:TCP/IPJavaWeb网页编程:B/S

网络通信的要素

  • 通信双方地址:
    • ip
    • 端口号
    • 192.168.16.124:5900
  • 规则:网络通信的协议
    • UDP:用户传输协议
    • TCP:用户数据报协议
  • TCP/IP 四层概念模型:
    • 应用层
    • 传输层
    • 网络层
    • 数据链路层
  • 网络编程中有两个主要问题
    • 如何准确的定位到网络上的一台或者多台主机
    • 找到主机之后如何进行通信
  • 万物皆对象

IP(InetAddress)

  • 唯一定位一台网络上的计算机
  • 127.0.0.1 :本机 localhost
  • IP地址的分类
    • ipv4/ipv6
      • IPV4 ,4个字节组成,总共42亿个;30亿在北美,亚洲4亿;2011年就用尽了
      • IPV6 ,128位,8个无符号整数!
      • 2001:5a42:2451:abcc:1ccc:1342
    • 公网(互联网) - 私网(局域网)
      • ABCD类地址
      • 192.168.xx.xx ,专门给组织内部使用的
  • 域名:记忆IP问题
package ink.lesson01;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class TestInetAddress {
    public static void main(String[] args) {
        try {
            //查询本机地址
            InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
            System.out.println(inetAddress1);    // /127.0.0.1

            InetAddress inetAddress3 = InetAddress.getByName("localhost");
            System.out.println(inetAddress3);   // localhost/127.0.0.1

            InetAddress inetAddress4 = InetAddress.getLocalHost();
            System.out.println(inetAddress4);   // DC-Pro/10.200.34.15


            //查询网站ip地址
            InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inetAddress2);   // www.baidu.com/14.215.177.38
            
            System.out.println("\n====================\n");

            //常用方法
            System.out.println(inetAddress2.getAddress());      // [B@14ae5a5
            System.out.println(inetAddress2.getCanonicalHostName());        // 14.215.177.38
            System.out.println(inetAddress2.getHostAddress());      // 14.215.177.38
            System.out.println(inetAddress2.getHostName());     // www.baidu.com

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

端口

  • 端口表示计算机上的一个程序的进程

    • 不同进程有不同的端口号,用来区分软件!
    • 规定:0~65535
    • TCP,UDP:一共 65535*2 个,单个协议下,端口号不能冲突
  • 端口分类:

    • 共有端口 0~1023

      • HTTP:80
      • HTTPS:443
      • FTP:21
      • Telent:23
    • 程序注册端口:1024~49151,分配用户或者程序

      • Tomcat:8080
      • MySQL:3306
      • Oracle:1521
    • 动态、私有:49152~65535

      • netstat -ano	#查看所有端口
        netstat -ano|findstr "5900"		#查看指定端口
        

通信协议

  • 协议:约定,就好比我们交流用的是普通话

  • 网络通信协议:速率,传输码率,代码结构,传输控制…

  • TCP/IP协议族:实际上是一组协议

  • TCP & UDP 对比:

    • tcp:打电话

      • 连接,稳定

      • 三次握手,四次挥手

      • 最少需要三次,保证稳定连接!
        A:你瞅啥?
        B:瞅你咋地?
        C:干一场!
        
        A:我要走了!
        B:你真的要走了吗?
        B:你真的真的要走了吗?
        A:我真的要走了!
        
      • 客户端,服务端

      • 传输完成,释放连接,效率低

    • udp:发短信

      • 不连接,不稳定
      • 客户端和服务端,没有明确界限
      • 不管有没有准备好,都可以发个你~
      • DDOS:洪水攻击

TCP

  • 客户端
    • 连接服务器Socket
    • 发送消息
package ink.lesson02;

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

//客户端
public class TcpClientDemo01 {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream os = null;

        try {
            //1. 要知道服务器的地址,端口号
            InetAddress serverIP = InetAddress.getByName("127.0.0.1");
            int port = 9999;
            //2. 创建一个socket连接
            socket = new Socket(serverIP,port);
            //3. 发送消息IO流
            os = socket.getOutputStream();
            os.write("你好,这是一个TCP聊天模型".getBytes());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //资源使用完后需要关闭,注意先后顺序
            //正规项目的开发中,捕获异常是很有必要的,IDEA快捷键: Ctrl + Alt + T
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • 服务端
    • 建立服务的端口 ServerSocket
    • 等待用户的连接 accept
    • 接收用户消息
package ink.lesson02;

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

//服务端
public class TcpServerDemo01 {
    public static void main(String[] args) {

        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;

        try {
            //1. 要有一个地址
            serverSocket = new ServerSocket(9999);

            //循环,持续接收消息
            while (true) {
                //2. 等待客户端连接过来
                socket = serverSocket.accept();
                //3. 读取客户端的消息
                is = socket.getInputStream();

                //管道流
                baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = is.read(buffer)) != -1) {
                    baos.write(buffer,0,len);
                }

                System.out.println(baos.toString());
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //资源使用完后需要关闭,注意先后顺序
            //正规项目的开发中,捕获异常是很有必要的,IDEA快捷键: Ctrl + Alt + T
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

文件上传

  • 需要注意文件的路径,路径文件夹必须提前创建好
  • 服务端
package ink.lesson02;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServerDemo02 {
    public static void main(String[] args) throws Exception {
        //1. 创建服务
        ServerSocket serverSocket = new ServerSocket(9999);
        //2. 监听客户端的连接
        Socket socket = serverSocket.accept();  //阻塞式监听,会一直等待客户端的连接
        //3. 获取输入流
        InputStream is = socket.getInputStream();

        //4. 文件输出
        FileOutputStream fos = new FileOutputStream(new File("网络编程/src/newfile/new-kb.png"));
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            fos.write(buffer,0,len);
        }

        //通知客户端我接收完毕了
        OutputStream os = socket.getOutputStream();
        os.write("我接收完毕,你可以断开了".getBytes());

        //关闭资源
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}
  • 客户端
package ink.lesson02;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

public class TcpClientDemo02 {
    public static void main(String[] args) throws Exception {
        //1. 创建一个Socket连接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9999);
        //2. 创建一个输出流
        OutputStream os = socket.getOutputStream();

        //3. 读取文件
        FileInputStream fis = new FileInputStream(new File("网络编程/src/file/kb.png"));
        //4. 写出文件
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer)) != -1) {
            os.write(buffer,0,len);
        }

        //通知服务求,我已经结束了
        socket.shutdownInput();     //我已经传输完了!

        //确定服务器接收完毕,才能够断开连接
        InputStream inputStream = socket.getInputStream();
        //String byte[]
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        byte[] buffer2 = new byte[1024];
        int len2;
        while ((len2 = inputStream.read(buffer2)) != -1) {
            baos.write(buffer2,0,len2);
        }

        System.out.println(baos.toString());

        //5. 关闭资源
        baos.close();
        inputStream.close();
        fis.close();
        os.close();
        socket.close();
    }
}

Tomcat

  • 服务端

    • 自定义 S
    • Tomcat服务器 S:Java后台开发
  • 客户端

    • 自定义 C
    • 浏览器 B
  • tomcat 字符乱码问题:

    • 打开 \apache-tomcat-8.5.64\conf\logging.properties
    • UTF-8 修改为 GBK : java.util.logging.ConsoleHandler.encoding = GBK

UDP

  • 发信息:不用连接,但需要知道对方地址
  • 发送消息
package ink.lesson03;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

//不需要连接服务器
public class UdpClientDemo01 {
    public static void main(String[] args) throws Exception {
        //1. 建立一个Socket
        DatagramSocket socket = new DatagramSocket();

        //2. 建个包
        String msg = "你好,服务器";
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 9090;

        //数据,数据的长度起始,要发给谁?
        DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);

        //3. 发送包
        socket.send(packet);

        //4. 关闭流
        socket.close();
    }
}
  • 接收端
package ink.lesson03;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

//等待客户端的连接!
public class UdpServerDemo01 {
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket socket = new DatagramSocket(9090);

        //接收数据包
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);

        socket.receive(packet);     //阻塞接收

        System.out.println(packet.getAddress().getHostAddress());   // 127.0.0.1
        System.out.println(new String(packet.getData(),0,packet.getLength()));  // 你好,服务器

        //关闭连接
        socket.close();
    }
}

循环发送和接收消息

  • 发送消息
package ink.chat;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class UdpSenderDemo01 {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(8888);

        //准备数据:控制台读取 System.in
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        while (true) {
            String data = reader.readLine();
            byte[] datas = data.getBytes();
            DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));

            socket.send(packet);
            if (data.equals("bye")) {
                break;
            }
        }

        socket.close();
    }
}
  • 接收消息
package ink.chat;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpReceiveDemo01 {
    public static void main(String[] args) throws Exception {
        DatagramSocket socket = new DatagramSocket(6666);

        while (true) {
            //准备接收包裹
            byte[] container = new byte[1024];
            DatagramPacket packet = new DatagramPacket(container,0,container.length);
            socket.receive(packet);     //阻塞式接收包裹

            //断开连接 bye
            byte[] data = packet.getData();
            String receiveData = new String(data,0, data.length);

            System.out.println(receiveData);

            if (receiveData.equals("bye")) {
                break;
            }
        }

        socket.close();
    }
}

在线咨询

  • 两个人都可以是发送方,也都可以是接收方(多线程
package ink.chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

public class TalkSend implements Runnable{
    DatagramSocket socket = null;
    BufferedReader reader = null;

    private int fromPort;
    private String toIP;
    private int toPort;

    public TalkSend(int fromPort, String toIP, int toPort) {
        this.fromPort = fromPort;
        this.toIP = toIP;
        this.toPort = toPort;

        try {
            socket = new DatagramSocket(fromPort);
            reader = new BufferedReader(new InputStreamReader(System.in));
        } catch (SocketException e) {
            e.printStackTrace();    //打印栈信息
        }
    }

    @Override
    public void run() {

        while (true) {
            try {
                String data = reader.readLine();
                byte[] datas = data.getBytes();
                DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress(this.toIP,this.toPort));

                socket.send(packet);
                if (data.equals("bye")) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        socket.close();
    }
}
package ink.chat;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class TalkReceive implements Runnable{
    DatagramSocket socket = null;
    private int port;
    private String msgFrom;

    public TalkReceive(int port, String msgFrom) {
        this.port = port;
        this.msgFrom = msgFrom;
        try {
            socket = new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        while (true) {

            try {
                //准备接收包裹
                byte[] container = new byte[1024];
                DatagramPacket packet = new DatagramPacket(container,0,container.length);
                socket.receive(packet);     //阻塞式接收包裹

                //断开连接 bye
                byte[] data = packet.getData();
                String receiveData = new String(data,0, data.length);

                System.out.println(msgFrom + ":" + receiveData);

                if (receiveData.equals("bye")) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        socket.close();
    }
}
package ink.chat;

public class TalkStudent {
    public static void main(String[] args) {
        //开启两个线程
        new Thread(new TalkSend(7777,"localhost",9999)).start();
        new Thread(new TalkReceive(8888,"老师")).start();
    }
}
package ink.chat;

public class TalkTeacher {
    public static void main(String[] args) {
        new Thread(new TalkSend(5555,"localhost",8888)).start();
        new Thread(new TalkReceive(9999,"学生")).start();
    }
}

URL

https://www.baidu.com/

统一资源定位符:定位资源的,定位互联网上的某一个资源

DNS 域名解析:将域名解析为 IP 地址

协议://ip地址:端口/项目名/资源
  • Java 中的 URL
package ink.lesson04;

import java.net.MalformedURLException;
import java.net.URL;

public class URLDemo01 {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=kuangshen&password=123");
        System.out.println(url.getProtocol());  //协议名
        System.out.println(url.getHost());  //主机ip
        System.out.println(url.getPort());  //端口
        System.out.println(url.getPath());  //文件
        System.out.println(url.getFile());  //全路径
        System.out.println(url.getQuery()); //参数

        /*
            http
            localhost
            8080
            /helloworld/index.jsp
            /helloworld/index.jsp?username=kuangshen&password=123
            username=kuangshen&password=123
         */
    }
}
  • 在网络上下载资源
package ink.lesson04;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class UrlDown {
    public static void main(String[] args) throws Exception {
        //1. 下载地址
        URL url = new URL("http://127.0.0.1:8080/alibaba/hello.txt");

        //2. 连接到这个资源 HTTP
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

        InputStream inputStream = urlConnection.getInputStream();

        FileOutputStream fos = new FileOutputStream("网络编程/src/newfile/hello.txt");

        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            fos.write(buffer,0,len);    //写出这个数据
        }

        fos.close();
        inputStream.close();
        urlConnection.disconnect();     //断开连接
    }
}
这篇关于Java-网络编程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!