Java网络编程

241 阅读6分钟

计算机网络

​计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统网络管理软件网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

网络编程的目的

  • 无线电台
  • 传播交流信息
  • 数据交换
  • 通信
  • 。。。

网络通信的要素

如何实现网络的通信?

  1. 通信双方的地址

    • ip——定位某一个台计算机
    • 端口号——定位到某一个应用
    • 47.99.72.134:1025
  2. 通信协议

image.png

  1. 这里主要学习传输层的TCPUDP

IP

ip地址:InetAddress

  • 唯一定位一台网络上计算机
  • 127.0.0.1:本机(localhost)
  • IP地址分类
    • ipv4 / ipv6
      • ipv4 : 47.99.72.134,4个字节,一共42亿个;2019年底用尽
      • ipv6 : CDCD:910A:2222:5498:8475:1111:3900:2020,128位,每16位用**:**隔开,每4位用一个十六进制数表示,2^128 个(约3.4×10^38)
    • 公网(互联网)/ 私网(局域网)
      • ABCD类地址
      • 192.168.xxx.xxx 私网
    • 域名:IP地址记不住

java.net.InetAddress

package com.volcano.net;

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

public class TestInetAddress {
    public static void main(String[] args) {
        try {
            InetAddress address = InetAddress.getByName("www.baidu.com");
            System.out.println(address);//www.baidu.com/180.101.49.11
            InetAddress address2 = InetAddress.getByName("127.0.0.1");
            System.out.println(address2);// /127.0.0.1
            InetAddress address3 = InetAddress.getLocalHost();
            System.out.println(address3);// DESKTOP-9POAR2H/10.238.60.12
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

端口

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

  • 不同的进程有不同的端口号

  • 规定 0~65535

  • TCP和UDP各有6w+

  • 端口分类

    • 公有端口 0~1023 大部分已经被系统内置应用占用

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

      • Oracle:1521
      • Mysql:3306
      • Tomcat:8080
    • 动态分配或私有:49152~65535

      netstat -ano#查看所有的端口
      netstat -ano|findstr "80"#查看所有指定端口
      tasklist:findstr "80"#查看指定端口的进程
      

java.net.InetSocketAddress

package com.volcano.net;

import java.net.InetSocketAddress;

public class TestInetSocketAddress {
    public static void main(String[] args) {
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8080);
        System.out.println(inetSocketAddress);
        InetSocketAddress inetSocketAddress2 = new InetSocketAddress("localhost", 8080);
        System.out.println(inetSocketAddress2);

        System.out.println(inetSocketAddress.getAddress());
        System.out.println(inetSocketAddress.getHostName());
        System.out.println(inetSocketAddress.getPort());
    }
}

通信协议

网络通信协议:速率、码率、代码结构、传输控制。。。

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

重要:

  • TCP:用户传输协议
  • UDP:用户数据报协议

出名的协议

  • TCP
  • IP

TCP和UDP对比

TCP:打电话

  • 连接、稳定

  • 三次握手、四次挥手

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

UDP:发短信

  • 不连接、不稳定
  • 客户端、服务端:没有明确的界限
  • 不管有没有准备好,都可以发给你
  • DDOS:洪水攻击,疯狂发送垃圾消息,占用目标端口,卡爆网络

TCP

实现聊天

package com.volcano.net;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//先运行这个类
public class TcpServerDemo1 {
    public static void main(String[] args) {
        //最后都需要关闭,所以都先提取出来
        ServerSocket serverSocket=null;
        Socket socket=null;
        InputStream socketInputStream=null;
        ByteArrayOutputStream byteArrayOutputStream=null;
        try {
            //1.首先要有一个地址
            serverSocket = new ServerSocket(9999);
            //循环接受消息
            while(true){
                //2.等待客户端连接
                socket = serverSocket.accept();
                //3.读取客户端消息
                socketInputStream = socket.getInputStream();
                //使用管道流比较合适
                byteArrayOutputStream = new ByteArrayOutputStream();
                byte[] buffer=new byte[1024];
                int len;
                while((len=socketInputStream.read(buffer))!=-1){
                    byteArrayOutputStream.write(buffer,0,len);
                }
                System.out.println(byteArrayOutputStream.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //最后都需要关闭,通过if判断再关闭是最常规的流程,先开的后关
            if(byteArrayOutputStream!=null){
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socketInputStream!=null){
                try {
                    socketInputStream.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 com.volcano.net;

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

public class TcpClientDemo1 {
    public static void main(String[] args) {
        Socket socket=null;
        OutputStream outputStream=null;
        try {
            //1.获得服务器地址
            InetAddress address = InetAddress.getByName("127.0.0.1");
            //端口号
            int port = 9999;
            //2.创建Socket连接
            socket = new Socket(address, 9999);
            //3.发送消息IO流
            outputStream = socket.getOutputStream();
            outputStream.write("aaaa".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(outputStream!=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

传输文件

package com.volcano.net;

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

public class TcpServerDemo02 {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();
        InputStream socketInputStream = socket.getInputStream();
        FileOutputStream fileOutputStream = new FileOutputStream(new File("222.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        while ((len=socketInputStream.read(buffer))!=-1){
            fileOutputStream.write(buffer,0, len);
        }
        //接收完毕,告诉客户端
        OutputStream socketOutputStream = socket.getOutputStream();
        socketOutputStream.write("我好了,你断开吧".getBytes());
        fileOutputStream.close();
        socketInputStream.close();
        serverSocket.close();
    }
}
package com.volcano.net;

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

public class TcpClientDemo02 {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);
        OutputStream outputStream = socket.getOutputStream();
        //创建文件输入流
        FileInputStream fileInputStream = new FileInputStream(new File("家教壁纸.jpg"));
        byte[] buffer = new byte[1024];
        int len;
        //文件写入到socket输出流中
        while ((len=fileInputStream.read(buffer))!=-1){
            outputStream.write(buffer,0,len);
        }
        //传输完毕,告诉服务器
        socket.shutdownOutput();
        //接收服务器消息结果
        InputStream socketInputStream = socket.getInputStream();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int len2;
        byte[] buffer2 = new byte[1024];
        while((len2=socketInputStream.read(buffer2))!=-1){
            byteArrayOutputStream.write(buffer2,0,len2);
        }
        System.out.println(byteArrayOutputStream.toString());
        fileInputStream.close();
        outputStream.close();
        socket.close();
    }
}

UDP

消息发送

package com.volcano.net;

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

public class UdpClientDemo {
    public static void main(String[] args) throws Exception {
        //1.建立一个Socket
        DatagramSocket socket = new DatagramSocket();
        //2.建个包
        String msg = "你好啊,服务器";
        //发送目的地
        InetAddress localhost = InetAddress.getByName("localhost");
        int port=9999;
        DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
        //3.发送
        socket.send(packet);
        socket.close();

    }
}
package com.volcano.net;

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

public class UdpServerDemo {
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket socket=new DatagramSocket(9999);
        //接收数据包,还是需要等待客户端连接
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
        socket.receive(packet);//阻塞接收
        System.out.println(packet.getAddress().getHostAddress());
        System.out.println(new String(packet.getData(),0,packet.getLength()));
        socket.close();
    }
}

image.png

聊天实现

​ 多线程实现聊天。

创建发送和接收两个线程

package com.volcano.net.chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class TalkSend implements Runnable {
    DatagramSocket socket=null;
    BufferedReader reader=null;
    int thisPort;
    String toHost;
    int toPort;

    public TalkSend(int fromPort, String toHost, int toPort) {
        this.thisPort = fromPort;
        this.toHost = toHost;
        this.toPort = toPort;
    }

    @Override
    public void run() {
        try {
            socket = new DatagramSocket(thisPort);

            //准备数据:控制台读取
            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, InetAddress.getByName(toHost),toPort);
                socket.send(packet);
                if(data.equals("bye")){
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


        socket.close();
    }
}
package com.volcano.net.chat;

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

public class TalkReceive implements Runnable {
    DatagramSocket socket=null;
    int thisPort;
    String  fromWho;

    public TalkReceive(int thisPort, String fromWho) {
        this.thisPort = thisPort;
        this.fromWho = fromWho;
    }

    @Override
    public void run() {
        try {
            socket = new DatagramSocket(thisPort);
            //循环接收
            while (true){
                byte[] buffer = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
                socket.receive(packet);
                byte[] data=packet.getData();
                String strData=new String(data,0,data.length);
                System.out.println(fromWho+":"+strData);
                if(strData.trim().equals("bye")){
                    break;
                }
            }
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

在学生端和教师端运行线程,注意端口对应

package com.volcano.net.chat;

public class Student {
    public static void main(String[] args) {
        new Thread(new TalkSend(6666,"localhost",9999)).start();
        new Thread(new TalkReceive(8888,"Teacher")).start();
    }
}
package com.volcano.net.chat;

public class Teacher {
    public static void main(String[] args) {
        new Thread(new TalkSend(7777,"localhost",8888)).start();
        new Thread(new TalkReceive(9999,"Student")).start();
    }
}

image.png

URL

统一资源定位符

package com.volcano.net;

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

public class TestURL {
    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());//参数
    }
}

image.png

下载网络资源

package com.volcano.net;

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

public class UrlDown {
    public static void main(String[] args) throws IOException {
        //1.下载地址
        URL url = new URL("xxxxxxx");//填写一个有效资源url
        //2.连接到这个资源 HTTP
        HttpURLConnection urlConnection=(HttpURLConnection)url.openConnection();

        InputStream inputStream = urlConnection.getInputStream();
        FileOutputStream outputStream=new FileOutputStream("a.txt");
        byte[] buffer=new byte[1024];
        int len;
        while((len=inputStream.read(buffer))!=-1){
            outputStream.write(buffer,0,len);
        }
        outputStream.close();
        inputStream.close();
        urlConnection.disconnect();
    }
}