网络编程及案例

基本概念

IP:对应着网络中唯一的主机

端口号: 端口号用来标识正在计算机上运行的进程(程序),范围是0~65535

InetAddress类

This class represents an Internet Protocol (IP) address.在Java中,使用InetAdress类来表示一个IP地址。

InetAddress类构造器私有化了,需要通过getByName(String host)、getLocalHost()来实例化对象。

常用的方法有getHostName()、getHostAddress();

public class InetDemo {
    public static void main(String[] args){
        try {
            /*
            类似于File file = new File("hello.txt");
            InetAddress对象对应着一个具体的IP地址的值
            缺点,通过IP地址访问,不太容易记忆
            */
            InetAddress inet1 = InetAddress.getByName("192.168.10.11");
            System.out.println(inet1);

            /*
            通过域名访问,方便记忆
             */
            InetAddress inet2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inet2);

            /*
            本地回路地址:127.0.0.1 对应着localhost(本机)
             */
            InetAddress inet3 = InetAddress.getByName("localhost");
            System.out.println(inet3);

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

网络通信协议

TCP和UDP

TCP协议
1、使用TCP协议前, 需先建立TCP连接,形成传输数据通道。
2、传输前,采用**“三次握手”**方式,点对点通信,是可靠的
3、TCP协议进行通信的两个应用进程:客户端、服务端
4、在连接中可进行大数据量的传输
5、传输完毕,需释放已建立的连接,效率低
UDP协议
1、将数据、源、目的封装成数据包,不需要建立拦截。
2、每个数据报的大小限制在64kb
3、发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
4、可以广播发送
5、发送数据结束时无序释放资源,开销小,速度快

TCP/IP

案例一:通过TCP实现服务端与客户端通信

客户端:

package com.inet.demo5;

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

public class Client {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream out = null;
        try {
            //1、创建一个socket对象,指明服务器端的ip和端口号
            socket = new Socket("127.0.0.1", 6666);
            //2、获取一个输出流,用于输出数据
            out = socket.getOutputStream();
            //写数据
            out.write("你好,服务端!".getBytes());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {//关闭资源
            try {
                if (out != null) {
                    out.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

服务器端:

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

public class Server {
    public static void main(String[] args) {
        ServerSocket ss = null;
        Socket socket = null;
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            ss = new ServerSocket(6666);
            socket = ss.accept();
            in = socket.getInputStream();
        /*
        不建议采用这种写法,如果byte数组给的小,则一次性读不完,会乱码
        byte[] b = new byte[1024];
        int len ;
        while ((len = in.read(b)) != -1) {
           String str = new String(b,0,len);
           System.out.print(str);
        }
        */
            //这样先把数据读到byte数组中去,整体读完才去转换成字符串,不会乱码
            out = new ByteArrayOutputStream();
            byte[] b = new byte[5];
            int len;
            while ((len = in.read(b)) != -1) {
                out.write(b, 0, len);
            }
            System.out.println(out.toString());
            System.out.println("收到了来自"+socket.getInetAddress().getHostAddress()+"的消息");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源  为了保证资源关闭必须执行,所以要用try-catch-finally来执行,不能通过throws来抛出
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
                if (socket != null) {
                    socket.close();
                }
                if (ss != null) {
                    ss.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

案例二:实现客户端向服务器端发送文件,服务器向客户端返回 “接收成功信息” 在客户端打印输出

客户端

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

public class Client {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream out = null;
        FileInputStream fis = null;
        InputStream in = null;
        ByteArrayOutputStream bos = null;
        try {
            //1、创建一个socket对象,指明ip和端口
            socket = new Socket(InetAddress.getByName("127.0.0.1"), 6666);
            //2、获取输出流
            out = socket.getOutputStream();
            //3、从外部读取文件
            fis = new FileInputStream("D:\\1.mp4");
            byte[] b = new byte[1024];
            int len;
            while ((len = fis.read(b)) != -1) {
                out.write(b, 0, len);
            }
            //4、在这里关闭数据的输出,服务端就得到了明确的指示,不会阻塞等待
            socket.shutdownOutput();
            //5、获取输入流
            in = socket.getInputStream();
            //6、读取服务端返回的数据
            bos = new ByteArrayOutputStream();
            byte[] b1 = new byte[1024];
            int length;
            while ((length = in.read(b1)) != -1) {
                bos.write(b1, 0, length);
            }
            System.out.println(bos.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally { //7、关闭资源
            try {
                if (bos != null) {
                    bos.close();
                }
                if (in != null) {
                    in.close();
                }
                if (fis != null) {
                    fis.close();
                }
                if (out != null) {
                    out.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

服务器端

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

public class Server {
    public static void main(String[] args) {
        ServerSocket ss = null;
        Socket socket = null;
        InputStream in = null;
        FileOutputStream fos = null;
        OutputStream out = null;
        try {
            //1、创建服务器端的ServerSocket,指明自己的端口号
            ss = new ServerSocket(6666);
            //2、调用accept()表示接收来自于客户端的socket
            socket = ss.accept();
            //3、获取输入流
            in = socket.getInputStream();
            //4、将客户端传来的文件保存到本地
            fos = new FileOutputStream("D:\\temp\\2.mp4");
            byte[] b = new byte[1024];
            int len;
            /*
                重点注意! read()方法是一个阻塞式的方法
                意思就是你没有告诉我结束的时候,我就不会停止循环
                当读完一个文件时,它还是会继续阻塞,等待客户端给它发送数据
                因为客户端并没有给一个明确的指示说传送完毕
                所以服务器端还停留在while循环当中,就会阻塞在这
                下面的语句也就不会执行
             */
            while ((len = in.read(b)) != -1) {
                fos.write(b, 0, len);
            }
            System.out.println("视频传输完成");
            //5、获取输出流
            out = socket.getOutputStream();
            if (in.read(b) == -1) {//如果文件读取完毕,则返回接收成功
                out.write("接收成功".getBytes());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally { //关闭资源
            try {
                if (out != null) {
                    out.close();
                }
                if (fos != null) {
                    fos.close();
                }
                if (in != null) {
                    in.close();
                }
                if (socket != null) {
                    socket.close();
                }
                if (ss != null) {
                    ss.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

UDP

类DatagramSocket和DatagramPacket实现了基于UDP协议网络程序。

UDP数据包通过数据包套接字DatagramSocket来接收,而DatagramPacket对象封装了UDP数据包,在数据包中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。UDP协议中每个数据包都给出了完整的地址信息,不需要建立连接,所以不可靠,但是速度快,高效。

具体流程
1、建立发送端,接收端
2、建立数据包
3、调用Socket的发送、接收方法
4、关闭Socket

UDP通信案例

发送端

package com.inet.udpdemo;

import java.io.IOException;
import java.net.*;

public class Send {
    public static void main(String[] args) throws IOException {

        DatagramSocket socket = new DatagramSocket();//不需要在socket中填数据
        String str = "来自发送端的数据";
        byte[] data = str.getBytes();//转为byte数组
        InetAddress inet = InetAddress.getLocalHost();//获取一个InetAddress对象,指明ip地址
        DatagramPacket packet = new DatagramPacket(data,0,data.length,inet,6666);
        socket.send(packet);
        socket.close();


    }
}

​ 接收端

package com.inet.udpdemo;


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


public class Receive {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(6666);//指定端口号
        byte[] b = new byte[1024];//定义一个byte数组来存放接收的数据
        DatagramPacket packet = new DatagramPacket(b,0,b.length);//读取byte数组中的数据保存到数据包中
        socket.receive(packet);//接收数据包
        System.out.println(new String(packet.getData(),0,packet.getLength()));//读取packet中的数据
        socket.close();
    }
}

URL

Uniform Resource Locator 统一资源定位符,它代表Internet上某一资源的地址

URL的五个基本组成部分:

<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表

片段名:即锚点,例如看小说,直接定位到章节

参数列表格式:参数名=参数值&参数名=参数值…

URL的一些基本操作

package com.inet;

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

public class URLDemo {
    public static void main(String[] args) {
        try {
            URL url = new URL("https://www.baidu.com/s?cl=3&tn=baidutop10&fr=top1000&wd=31%E7%9C%81%E6%96%B0%E5%A2%9E%E6%9C%AC%E5%9C%9F%E7%A1%AE%E8%AF%8A93%E4%BE%8B%3A%E6%B2%B3%E5%8C%9754%E4%BE%8B&rsv_idx=2&rsv_dl=fyb_n_homepage&hisfilter=1");
            System.out.println(url.getProtocol());//获取该URL的协议名
            System.out.println(url.getHost());//获取该URL的主机名
            System.out.println(url.getPort());//获取该URL的端口号
            System.out.println(url.getPath());//获取该URL的文件路径
            System.out.println(url.getFile());//获取该URL的文件名
            System.out.println(url.getQuery());//获取该URL的查询名
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}

案例:从网上下载图片

package com.inet.url;

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

/**
 * 从网络下载文件
 */

public class URLDemo2 {
    public static void main(String[] args) {
        HttpURLConnection urlConnection = null;
        InputStream in = null;
        FileOutputStream fos = null;
        try {
            //填入下载图片所在url
            URL url = new URL("https://pics6.baidu.com/feed/a044ad345982b2b76c7e400d4fde22e874099b95.jpeg?token=484a6fd24eae05e83005e65a6e7e045f&s=6D428B46A88BA55594F44D9303008083");
            urlConnection = (HttpURLConnection) url.openConnection();//获取服务器连接,用的是http协议,所以获得的是HttpURLConnection
            urlConnection.connect();//访问服务器
            in = urlConnection.getInputStream();
            fos = new FileOutputStream("D:\\cc.png");
            byte[] b = new byte[1024];
            int len;
            while ((len = in.read(b)) != -1) {
                fos.write(b, 0, len);
            }
            System.out.println("下载完毕");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值