JavaOnline

网络编程 TCP/IP C/S

1.1、概述

目的

无线电台。传播交流信息,数据交换。通信
1、如何确保准确定位网络上的一台主机,端口。定位到这个计算机上的某个资源
2、找到了这个主机,如何传输数据?

1.2、网络通信的要素

如何实现网络通信?
通信双方的地址:

  • ip
  • 端口
    规则:网络通信的协议
    HTTP TCP IP UDP......
    小结:
    1、主要问题
  • 如何准确的定位到网络上的一台或者多台主机
  • 找到主机之后如何进行通信
    2、网络编程中的要素
  • IP和端口号
  • 网络通信协议UDP TCP
    3、万物皆对象

1.3、IP

IP地址:inetAddress

  • 唯一定位一台网络上的计算机
  • 127.0.0.1(4个字节组成 0-255 42亿):本机localhost
  • ip地址的分类 ipv4(0-255)/ipv6(128位,8个无符号整数)
  • 公网(互联网)-私网(局域网,192.168.xx.xx)
  • 域名:记忆IP问题

应用

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

            //查询网站IP地址
            InetAddress inet4 = InetAddress.getByName("www.baidu.com");
            System.out.println(inet4);

            //常用方法
            System.out.println(inet4.getAddress());
            System.out.println(inet4.getHostAddress());
            System.out.println(inet4.getCanonicalHostName());;
            System.out.println(inet4.getHostName());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

/127.0.0.1
localhost/127.0.0.1
DESKTOP-1M52ISN/192.168.119.1
www.baidu.com/110.242.68.3
[B@1b6d3586
110.242.68.3
110.242.68.3
www.baidu.com

Process finished with exit code 0

1.4、端口

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

  • 不同的进程有不同的端口号!用来区分软件!
  • 端口被规定为0-65535
  • TCP UDP :65535*2 
  • TCP:80,UDP:80?,单个协议下端口不能冲突
  • 端口分类 公有端口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" #查看指定端口
tasklist | findstr "8696" #
public class TestInetSocketAddress {
    public static void main(String[] args) {
        InetSocketAddress inetSocketAddress1 = new InetSocketAddress("127.0.0.1", 8080);
        InetSocketAddress inetSocketAddress = new InetSocketAddress("localhost", 8080);
        System.out.println(inetSocketAddress);
        System.out.println(inetSocketAddress1);
        System.out.println(inetSocketAddress1.getHostName());//地址
        System.out.println(inetSocketAddress1.getPort());//端口
        System.out.println(inetSocketAddress1.getAddress());
    }
}

localhost/127.0.0.1:8080
/127.0.0.1:8080
127.0.0.1
8080
127.0.0.1/127.0.0.1

1.5、通信协议

速率,传输码率,代码结构,传输控制....
TCP/IP协议簇
TCP:用户传输协议
UDP:用户数据报协议
IP:网络互联协议
TCP UDP对比
TCP:打电话
链接,稳定。
三次握手 四次挥手

三次握手
A:?
B:?
A:!

四次挥手
A:断开
B:我知道了
B:真的断开吗
A:断开 

客户端、服务端
传输完成,释放连接,效率低
UDP:发短信
不链接,不稳定
客户端,服务端:没有明确的界限
不管有没有准备好,都可以发给你
导弹
DDOS:洪水攻击(饱和攻击)

1.6、TCP

客户端
1、链接服务器Socket
2、发送消息

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 = 9990;
            //2、创建一个Socket链接
            socket = new Socket(serverIP,port);
            //3、发送消息 IO源
            os = socket.getOutputStream();
            os.write("你好!!".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }


    }
}

服务器
1、建立服务的端口 ServerSocket
2、等待用户的连接 accept
3、接受用的消息

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(9990);
            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 (IOException e) {
            e.printStackTrace();
        }finally {
            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();
                }
            }
        }

    }
}

文件上传
客户端

public class TcpClientDemo02 {
    public static void main(String[] args) throws Exception {
        //1、创建一个Socket链接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9990);
        //2、创建一个输出流
        OutputStream os = socket.getOutputStream();
        //3、读入文件
        FileInputStream fis = new FileInputStream(new File("aa.jpg"));
        //4、写出文件
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer))!=-1){
            os.write(buffer,0,len);
        }

        //通知服务器我结束了
        socket.shutdownOutput();//我已经传输完了

        //确定服务器接收完毕才能退出
        InputStream inputStream = socket.getInputStream();
        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());

        fis.close();
        os.close();
        socket.close();

    }
}

服务器端

public class TcpServerDemo02 {
    public static void main(String[] args) throws Exception {
        //1、创建服务
        ServerSocket serverSocket = new ServerSocket(9990);
        //2、阻塞式监听客户端的链接
        Socket socket =  serverSocket.accept();
        //3、获取输入流
        InputStream is = socket.getInputStream();
        //4、文件输出
        FileOutputStream fos = new FileOutputStream(new File("bb.jpg"));
        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();
    }
}

java中可以开端口号,此时若要打开电脑上一个相同端口号的应用则会报错(端口号被占用)

1.7、UDP

发送消息

发短信:不用链接,只需要知道对方的地址

A端

public class UdpClientDemo01 {
    public static void main(String[] args) throws Exception {
        //1、建一个Socket
        DatagramSocket datagramSocket = new DatagramSocket(8080);//8080端口号在AB此次传送中没起作用,但是这个端口号意味着,别的计算机可以通过这个端口号给A传送信息
        //2、建一个包
        String msg ="UDP传输!";
        int port=9090;
        InetAddress localhost = InetAddress.getByName("localhost");

        DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);


        //3、发送包
        datagramSocket.send(datagramPacket);

        //关闭流
        datagramSocket.close();
    }
}

B端

public class UdpServerDemo01 {
    public static void main(String[] args) throws Exception {
        DatagramSocket datagramSocket = new DatagramSocket(9090);

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

        datagramSocket.receive(datagramPacket);

        System.out.println(datagramPacket.getAddress());
        System.out.println(new String(datagramPacket.getData(),0, datagramPacket.getLength()));
    }
}

咨询

sender

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

        //循环接收消息,直到接受到88后结束
        while(true){

            //准备接收包裹
            byte[] container = new byte[1024];

            //包
            DatagramPacket datagramPacket = new DatagramPacket(container,0,container.length);

            datagramSocket.receive(datagramPacket);//阻塞式接受包裹


            byte[] data = datagramPacket.getData();
            String receive = new String(data,0,data.length).trim();//trim可以将数据后面连续的空格删除

            System.out.println(receive);

            //接收到“88”  断开链接
            if (receive.equals("88")){
                break;
            }
        }
        datagramSocket.close();
    }
}

receiver

public class UdpReceiverDemo01 {
    public static void main(String[] args) throws Exception {

        DatagramSocket datagramSocket = new DatagramSocket(8888);

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

        //循环发送消息,直到发送88后结束
        while (true){

            String data = bufferedReader.readLine();
            byte[] datas = data.getBytes();

            //数据包
            DatagramPacket datagramPacket = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost",6666));

            datagramSocket.send(datagramPacket);

            //断开链接 “88”
            if (data.equals("88")){
                break;
            }
        }
        datagramSocket.close();
        bufferedReader.close();
    }
}

在线咨询:两者都可以是接收方,也可以都是发送方。
多线程的实现
send

public class TalkSend implements Runnable{
    DatagramSocket socket =null;
    BufferedReader bufferedReader =null;
    private int fromport;
    private int toport;
    private String toip;

    public TalkSend(int fromport, int toport, String toip) {
        this.fromport = fromport;
        this.toport = toport;
        this.toip = toip;

        try {
            socket = new DatagramSocket(fromport);
            bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        //循环发送消息,直到发送88后结束
        while (true){

            String data = null;
            try {
                data = bufferedReader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            byte[] datas = data.getBytes();

            //数据包
            DatagramPacket datagramPacket = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toip,this.toport));

            try {
                socket.send(datagramPacket);
            } catch (IOException e) {
                e.printStackTrace();
            }

            //断开链接 “88”
            if (data.equals("88")){
                break;
            }
        }
        socket.close();

    }
}

receive

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

    public TalkReceive(String msgfrom, int port) {
        this.port = port;
        this.msgfrom = msgfrom;

        try {
            socket=new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {



        //循环接收消息,直到接受到88后结束
        while(true){

            //准备接收包裹
            String receive = null;//trim可以将数据后面连续的空格删除
            try {
                byte[] container = new byte[1024];

                //包
                DatagramPacket datagramPacket = new DatagramPacket(container,0,container.length);

                socket.receive(datagramPacket);//阻塞式接受包裹


                byte[] data = datagramPacket.getData();
                receive = new String(data,0,data.length).trim();

                System.out.println(msgfrom+":"+receive);
            } catch (IOException e) {
                e.printStackTrace();
            }

            //接收到“88”  断开链接
            if (receive.equals("88")){
                break;
            }
        }
        socket.close();

    }
}

通信双方
老师

public class TalkStudent {
    public static void main(String[] args) {
        new Thread(new TalkSend(1111,2222,"localhost")).start();
        new Thread(new TalkReceive("老师",3333)).start();
    }
}

学生

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

1.8、URL

统一资源定位符:定位资源,定位互联网上的某一个资源。
DNS域名解析:将域名转换成IP
如 www.baidu.com 转换成 xxx.xx.xx.xx(IP地址)

URL组成
协议://ip地址://端口/项目名/资源
public class URLDemo01 {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("https://localhost:8080/helloword/index.jsp?username=a&password=123");
        System.out.println(url.getProtocol());//协议  https
        System.out.println(url.getHost());//主机  localhost
        System.out.println(url.getPort());//端口号 8080
        System.out.println(url.getPath());//文件  /helloword/index.jsp
        System.out.println(url.getFile());//全路径 /helloword/index.jsp?username=a&password=123
        System.out.println(url.getQuery());//参数 username=a&password=123
    }
}

下载网络资源

public class URLDown {
    public static void main(String[] args) throws Exception{

        //网易云歌曲
        URL url = new URL("https://m10.music.126.net/20220417220436/90fbe041c8a2df593f43faff5761ee58/yyaac/obj/wonDkMOGw6XDiTHCmMOi/13928008933/2a9d/c491/4dd1/a9e48ef877bab3b3a98ba7824e253c43.m4a");
        //链接这个资源HTTP
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

        InputStream inputStream = urlConnection.getInputStream();

//文件输出流
        FileOutputStream fos = new FileOutputStream("11.m4a");

        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }

        fos.close();
        inputStream.close();
        urlConnection.disconnect();
    }
}
posted @ 2022-04-17 22:05  星星淮  阅读(803)  评论(0)    收藏  举报