尚硅谷java学习笔记——14.网络编程

来源:互联网 发布:访问通用顶级域名 编辑:程序博客网 时间:2024/05/19 16:07

Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在 Java 的本机安装系统里,由 JVM 进行控制。并且 Java 实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。

网络中的主机相互通信必须解决:
1、通信双方地址
2、一定的规则:
OSI参考模型:模型过于理想化,未能在因特网上进行广泛推广
TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。

网络通信协议
这里写图片描述

这里写图片描述

通讯要素1:IP 和 端口号

  • IP 地址:InetAddress
    唯一的标识 Internet 上的计算机
    本地回环地址(hostAddress):127.0.0.1
    主机名(hostName):localhost
  • 端口号标识正在计算机上运行的进程(程序)
    不同的进程有不同的端口号
    被规定为一个 16 位的整数 0~65535。其中,0~1023被预先定义的服务通信占用(如MySql占用端口3306,http占用端口80等)。除非我们需要访问这些特定服务,否则,就应该使用 1024~65535 这些端口中的某一个进行通信,以免发生端口冲突。
  • 端口号与IP地址的组合得出一个网络套接字。
/* * 网络通信的第一个要素:IP地址。通过IP地址,唯一的定位互联网上一台主机 * InetAddress:位于java.net包下 * 1.InetAddress用来代表IP地址。一个InetAdress的对象就代表着一个IP地址 * 2.如何创建InetAddress的对象:getByName(String host) * 3.getHostName(): 获取IP地址对应的域名 *   getHostAddress():获取IP地址 */public class TestInetAddress {    public static void main(String[] args) throws Exception {        //创建一个InetAddress对象:getByName()        InetAddress inet = InetAddress.getByName("www.atguigu.com");        //inet = InetAddress.getByName("42.121.6.2");        System.out.println(inet);        //两个方法        System.out.println(inet.getHostName());        System.out.println(inet.getHostAddress());        //获取本机的IP:getLocalHost()        InetAddress inet1 = InetAddress.getLocalHost();        System.out.println(inet1);        System.out.println(inet1.getHostName());        System.out.println(inet1.getHostAddress());    }}

通讯要素2:网络通信协议

  • TCP协议,传输控制协议(Transmission Control Protocol):
    使用TCP协议前,须先建立TCP连接,形成传输数据通道
    传输前,采用“三次握手”方式,是可靠的
    TCP协议进行通信的两个应用进程:客户端、服务端
    在连接中可进行大数据量的传输
    传输完毕,需释放已建立的连接,效率低
  • UDP协议,用户数据报协议(User Datagram Protocol):
    将数据、源、目的封装成数据包,不需要建立连接
    每个数据报的大小限制在64K内
    因无需连接,故是不可靠的
    发送数据结束时无需释放资源,速度快

Socket

基于TCP的Socket通信

这里写图片描述

Socket类的常用方法
这里写图片描述

ServerSocket类的常用方法
这里写图片描述

练习:

//1.服务端读取图片并发送给客户端,客户端保存图片到本地public class TestTcp {    @Test    public void client(){        Socket socket=null;        OutputStream os=null;        FileInputStream fis=null;        InputStream is=null;        try {            //1.创建Socket的对象            socket = new Socket(InetAddress.getByName("127.0.0.1"), 9898);            //2.从本地获取一个文件发送给服务端            os = socket.getOutputStream();            fis = new FileInputStream(new File("1.jpg"));            byte[] b = new byte[1024];            int len;            while((len = fis.read(b)) != -1){                os.write(b,0,len);            }            socket.shutdownOutput();//显式的告诉服务端发送完毕!            //3.接收来自于服务端的信息            is = socket.getInputStream();            byte[] b1 = new byte[1024];            int len1;            while((len1 = is.read(b1)) != -1){                String str = new String(b1,0,len1);                System.out.print(str);            }        }catch (IOException e) {            e.printStackTrace();        }finally{            //4.关闭相应的流和Socket对象            if(is!=null){                try {                    is.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            if(os!=null){                try {                    os.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(fis!=null){                try {                    fis.close();                } catch (IOException e) {                    e.printStackTrace();                }            }if(socket!=null){                try {                    socket.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    @Test    public void server(){        ServerSocket ss=null;        Socket s=null;        InputStream is=null;        FileOutputStream fos=null;        OutputStream os=null;        try {            //1.创建一个ServerSocket的对象            ss = new ServerSocket(9898);            //2.调用其accept()方法,返回一个Socket的对象            s = ss.accept();            //3.将从客户端发送来的信息保存到本地            is = s.getInputStream();            fos = new FileOutputStream(new File("3.jpg"));            byte[] b = new byte[1024];            int len;            while((len = is.read(b)) != -1){                fos.write(b, 0, len);            }            System.out.println("收到来自于" + s.getInetAddress().getHostAddress() + "的文件");            //4.发送"接收成功"的信息反馈给客户端            os = s.getOutputStream();            os.write("你发送的图片我已接收成功!".getBytes());        } catch (IOException e) {            e.printStackTrace();        }finally{            //5.关闭相应的流和Socket及ServerSocket的对象            if(os!=null){                try {                    os.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(fos!=null){                try {                    fos.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(is!=null){                try {                    is.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(s!=null){                try {                    s.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(ss!=null){                try {                    ss.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}
//客户端给服务端发送文本,服务端会将文本转成大写在返回给客户端。//如下程序为了保证相应的流及socket的关闭(即使在关闭之前出现异常,也一定要保证相应的资源的关闭),要求是用//try-catch-finally进行操作。要求将关闭的信息写在finally里!public class TestTCP {    @Test    public void client() {        // 1.        Socket socket = null;        // 2.        OutputStream os = null;        Scanner scanner = null;        // 4.接收来自于服务端的数据        InputStream is = null;        try {            socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);            os = socket.getOutputStream();            // 3.向服务端发送数据            // os.write("abc".getBytes());            System.out.println("请输入多个字符:");            scanner = new Scanner(System.in);            String str = scanner.next();            os.write(str.getBytes());            socket.shutdownOutput();            is = socket.getInputStream();            byte[] b = new byte[10];            int len;            while ((len = is.read(b)) != -1) {                String str1 = new String(b, 0, len);                System.out.print(str1);            }        } catch (IOException e) {            e.printStackTrace();        } finally {            // 5.            if(is != null){                try {                    is.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(scanner != null){                scanner.close();            }            if(os != null){                try {                    os.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(socket != null){                try {                    socket.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    @Test    public void server() {        // 1.        ServerSocket ss = null;        // 2.        Socket s = null;        // 3.接收来自于客户端的信息        InputStream is = null;        // 4.返回给客户端        OutputStream os = null;        try {            ss = new ServerSocket(9090);            s = ss.accept();            is = s.getInputStream();            byte[] b = new byte[10];            int len;            String str = new String();            while ((len = is.read(b)) != -1) {                String str1 = new String(b, 0, len);                str += str1;            }            String strUpperCase = str.toUpperCase();            os = s.getOutputStream();            os.write(strUpperCase.getBytes());        } catch (IOException e) {            e.printStackTrace();        }finally{            if(os != null){                try {                    os.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(is != null){                try {                    is.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(s != null){                try {                    s.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(ss != null){                try {                    ss.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }        // 5.    }}

UDP网络通信

  • 类 DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序。
  • UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
  • DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
  • UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
//UDP编程的实现public class TestUDP {    // 发送端    @Test    public void send() {        DatagramSocket ds = null;        try {            ds = new DatagramSocket();            byte[] b = "你好,我是要发送的数据".getBytes();            //创建一个数据报:每一个数据报不能大于64k,都记录着数据信息,发送端的IP、端口号,以及要发送到            //的接收端的IP、端口号。            DatagramPacket pack = new DatagramPacket(b, 0, b.length,                    InetAddress.getByName("127.0.0.1"), 9090);            ds.send(pack);        }catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            if(ds != null){                ds.close();            }        }    }    // 接收端    @Test    public void rceive() {        DatagramSocket ds = null;        try {            ds = new DatagramSocket(9090);            byte[] b = new byte[1024];            DatagramPacket pack = new DatagramPacket(b, 0, b.length);            ds.receive(pack);            String str = new String(pack.getData(), 0, pack.getLength());            System.out.println(str);        }catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            if(ds != null){                ds.close();            }        }    }}

URL编程

URL(Uniform Resource Locator):统一资源定位符,它表示 Internet 上某一资源的地址。浏览器通过解析给定的 URL 可以在网络上查找相应的文件或其他资源。

URL的基本结构由5部分组成:
<传输协议>://<主机名>:<端口号>/<文件名>
例如: http://192.168.1.100:8080/helloworld/index.jsp

一个URL对象生成后,其属性是不能被改变的,但可以通过它给定的方法来获取这些属性:
public String getProtocol( ) 获取该URL的协议名
public String getHost( ) 获取该URL的主机名
public String getPort( ) 获取该URL的端口号
public String getPath( ) 获取该URL的文件路径
public String getFile( ) 获取该URL的文件名
public String getRef( ) 获取该URL在文件中的相对位置
public String getQuery( ) 获取该URL的查询名

URL的方法 openStream():能从网络上读取数据
若希望输出数据,例如向服务器端的 CGI (公共网关接口-Common Gateway Interface-的简称,是用户浏览器和服务器端的应用程序进行连接的接口)程序发送一些数据,则必须先与URL建立连接,然后才能对其进行读写,此时需要使用 URLConnection 。
URLConnection:表示到URL所引用的远程对象的连接。当与一个URL建立连接时,首先要在一个 URL 对象上通过方法 openConnection() 生成对应的 URLConnection 对象。如果连接过程失败,将产生IOException.
URL netchinaren = new URL (“http://www.atguigu.com/index.shtml“);
URLConnectonn u = netchinaren.openConnection( );

通过URLConnection对象获取的输入流和输出流,即可以与现有的CGI程序进行交互。
public Object getContent( ) throws IOException
public int getContentLength( )
public String getContentType( )
public long getDate( )
public long getLastModified( )
public InputStream getInputStream( )throws IOException
public OutputSteram getOutputStream( )throws IOException

public class TestURL {    public static void main(String[] args) throws Exception {        //1.创建一个URL的对象        URL url = new URL("http://127.0.0.1:8080/examples/HelloWorld.txt?a=b");//File file = new File("文件的路径");        /*         *  public String getProtocol(  )     获取该URL的协议名            public String getHost(  )           获取该URL的主机名            public String getPort(  )            获取该URL的端口号            public String getPath(  )           获取该URL的文件路径            public String getFile(  )             获取该URL的文件名            public String getRef(  )             获取该URL在文件中的相对位置            public String getQuery(   )        获取该URL的查询名         *///      System.out.println(url.getProtocol());//      System.out.println(url.getHost());//      System.out.println(url.getPort());//      System.out.println(url.getFile());//      System.out.println(url.getRef());//      System.out.println(url.getQuery());        //如何将服务端的资源读取进来:openStream()        InputStream is = url.openStream();        byte[] b = new byte[20];        int len;        while((len = is.read(b)) != -1){            String str = new String(b,0,len);            System.out.print(str);        }        is.close();        //如果既有数据的输入,又有数据的输出,则考虑使用URLConnection        URLConnection urlConn = url.openConnection();        InputStream is1 = urlConn.getInputStream();        FileOutputStream fos = new FileOutputStream(new File("abc.txt"));        byte[] b1 = new byte[20];        int len1;        while((len1 = is1.read(b1)) != -1){            fos.write(b1, 0, len1);        }        fos.close();        is1.close();    }}
0 0