Java网络编程

网络编程

1.网络通信概述
(1)网络编程中的两个要素

①IP和端口号

②网络通信协议:TCP/IP协议–应(表、会)、传、网、数、物

(2)IP地址(唯一标识)–Java中InetAddress类代表IP,用来封装一个IP地址
1.IP地址的分类

分类方式一:

IPV4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已 经用尽。以点分十进制表示,如192.168.0.1

IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示, 数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984

分类方式二:

公网地址(万维网使用)和私有地址(局域网使用)。192.168. 开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机 构内部使用

注:

1.Internet上的主机有两种方式表示地址:①域名(hostName):www.atguigu.com ②IP 地址(hostAddress):202.108.35.210

2.DNS–域名解析服务器

3.本地回路地址:127.0.0.1 对应域名为–localhost

2.实例化InetAddress及常用方法
1.InetAddress InetAddress.getByName("主机号或域名")--造对象
2.InetAddress InetAddress.getLocalHost()--获取本机IP地址
3.String 对应变量.getHostName()--获取指定ip地址的主机名。如果是本机则是计算机名,否则为主机名,如果没有域名则是ip地址
4.String 对应变量.getHostAddress()--获得原始ip地址,返回值是字符串格式
public class test {
    public static void main(String[] args) {
        //InetAddress没有提供公共的构造器来让我们造对象,我们可以使用InetAddress.getByName("主机号或域名")来造对象
        try {
            InetAddress byAddress = InetAddress.getByName("192.168.11.14");
            InetAddress byName = InetAddress.getByName("www.baidu.com");
            //InetAddress.getLocalHost();获取本机IP地址
            InetAddress localHost = InetAddress.getLocalHost();
            System.out.println(byAddress);
            System.out.println(byName);
            System.out.println(localHost);
            System.out.println("ip地址:"+localHost.getHostAddress());
            System.out.println("主机名:"+localHost.getHostName());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}
(3)端口号
1.说明
端口号标识正在计算机上运行的进程(程序)
1.不同的进程有不同的端口号被规定为一个 16 位的整数 0~655352。端口分类:
(1)公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21Telnet占用端口23)
(2)注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080MySQL占用端口3306Oracle占用端口1521等)。
(3)动态/私有端口:49152~65535。
(4)端口号与IP地址的组合得出一个网络套接字:Socket
2.TCP协议的网络编程

客户端服务器连接过程

客户端:

1.创建socket对象指明服务器端ip和端口号

2.获取输出流用于数据数据

3.写数据

4.资源关闭

服务器端:

1.创建ServerSocket指明自己的端口号

2.调用accept方法接口来自客户端的socket

3.获取输入流

4.读取输入流中的数据,并进行相关操作

5.资源关闭

常用构造器及方法

一、服务器端ServerSocket:负责监听某台计算机的某个端口号,创建对象后调用accept方法接收来自客户端的请求,然后使用getInputStream产生输出流,并对流进行相关操作(可以使用ByteArrayOutputStream来写入)

1.ServerSocket serverSocket = new ServerSocket(0~65535,int bakclog,InetAddress ba)--用于创建一个服务器程序。指定一个服务器明自己的端口号范围0~65535(如果端口号为0则系统会分配一个空闲的端口号);backlog用于指定保持连接请求的等待客户数量,不写默认为50;ba用于为多个网卡和多个ip的指定,一般使用的很少
2.Socket serverSocket.accept()--用来接口来对应端口号自客户端的socket。在客户端连接之前一直处于阻塞状态,如果有客户端连接就会返回一个与之对应的socket对象
3.InetAddress serverSocket/socket(调用accpet后的变量).getInetAddress()--返回一个InetAddress对象,该对象中封装了ServerSocket绑定的IP地址
4.boolean serverSocket.isClosed--用于判断ServerSocket是否为关闭状态(关:TRUE,开:false)
5.void serverSocket.bind(SocketAddress endpoint)--将serverSocket对象绑定到指定IP地址和端口号,endpoint封装了IP地址和端口号

二、客户端socket:实例化后用getOutputStream并调用write(String.getbytes())方法在write中来写相关内容
1.Socket socket = new Socket(InetAddress host, 8899)--主机号,端口号(与要链接的服务器一致)
2.socket.getInputStream、getOutPutStream用于获取输入流和输出流,读取客户端或服务器端接收的数据与向客户端或服务器端发送数。因为客户端与服务器建立连接后数据是以IO流的形式进行交互的。 
3.int getPort()--返回socket对象与服务器端连接的端口号
4.InetAddress getLocalAddress()--返回socket对象绑定的本地ip地址
5.void close()--关闭通信
6.socket.getInputStream()--关闭数据的输入
7.socket.getOutputStream()--关闭数据的输出
练习1.客户端与服务器之间通讯
//先运行服务器在运行客户端,端口号一样
@Test
    public void cilent() {
        Socket socket = null;
        OutputStream os = null;
        try {
            InetAddress in = InetAddress.getByName("127.0.0.1");
            //指明IP地址以及服务器的端口号
            socket = new Socket(in, 8899);
            //进行流的传输
            os = socket.getOutputStream();
            os.write("你好我是客户端MM".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void server() {
        ServerSocket serverSocket = null;
        Socket accept = null;
        InputStream is = null;
        ByteArrayOutputStream bos = null;

        try {
            serverSocket = new ServerSocket(8899);
            accept = serverSocket.accept();
            is = accept.getInputStream();
            //不建议这样写,因为汉字站3个字节,可能不能放到一个数组中而导致乱码
//        byte[] b = new byte[1024];
//        int len;
//        while ((len = is.read(b)) != -1) {
//            String s = new String(b, 0, len);
//            System.out.println(s);
//        }
            //在使用ByteArrayOutputStream存放字符串时,每一个数组暂时先不做处理,等到把所有的数据都拿到把各个数组都拼起来在做处理,因此不会出现乱码
            bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int len;
            while ((len = is.read(b)) != -1) {
                bos.write(b, 0, len);
            }
            //输出bos中的所有的数据--即byte数组
            System.out.println(bos.toString());
            System.out.println("收到了来自于" + accept.getInetAddress().getHostAddress() + "的数据");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (accept != null) {
                    accept.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
练习2.客户端发送文件给服务端,服务端将文件保存在本地。输入流拿到要读取文件,输出流写文件,在读取和写时使用对应流的读和写方法进行拷贝,服务器给客户端传输图片已接收的信息
   @Test
    public void cilents() {
        Socket socket = null;
        OutputStream os = null;
        FileInputStream fis = null;
        ByteArrayOutputStream baos = null;
        InputStream inputStream = null;
        try {
            socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);
            os = socket.getOutputStream();
            fis = new FileInputStream("test.jpg");
            byte[] b = new byte[1024];
            int len;
            while ((len = fis.read(b)) != -1) {
                os.write(b, 0, len);
            }
            //socket.getInputStream()关闭数据的输出
            socket.shutdownOutput();

            inputStream = socket.getInputStream();
            byte[] b1 = new byte[1024];
            int len1;
            baos = new ByteArrayOutputStream();
            while ((len1 = inputStream.read(b1)) != -1) {
                baos.write(b1, 0, len1);
            }
            System.out.println(baos.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void servers() {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream is = null;
        FileOutputStream fos = null;
        OutputStream outputStream = null;
        try {
            serverSocket = new ServerSocket(9999);
            socket = serverSocket.accept();
            is = socket.getInputStream();
            fos = new FileOutputStream("os2.jpg");
            int len;
            byte[] b = new byte[1024];
            while ((len = is.read(b)) != -1) {
                fos.write(b, 0, len);
            }
            outputStream = socket.getOutputStream();
            outputStream.write("照片已收到".getBytes());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
3.UDP协议的网络编程
一、常用方法
1.public DatagramSocket(int port)创建数据报套接字并将其绑定到本地主机上的指定端口。套接字将被绑定到通配符地址,IP 地址由内核来选择。
2.public DatagramSocket(int port,InetAddress laddr)创建数据报套接字,将其绑定到指定的本地地址。本地端口必须在 065535 之间(包括两者)。如果 IP 地址为 0.0.0.0,套接字将被绑定到通配符地址,IP 地址由内核选择。
3.public void close()关闭此数据报套接字。
4.public void send(DatagramPacket p)从此套接字发送数据报包。DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。
5.public void receive(DatagramPacket p)从此套接字接收数据报包。当此方法返回时,DatagramPacket的缓冲区填充了接收的数据。数据报包也包含发送方的 IP 地址和发送方机器上的端口号。 此方法在接收到数据报前一直阻塞。数据报包对象的 length 字段包含所接收信息的长度。如果信息比包的长度长,该信息将被截短。
6.public InetAddress getLocalAddress()获取套接字绑定的本地地址。
7.public int getLocalPort()返回此套接字绑定的本地主机上的端口号。
8.public InetAddress getInetAddress()返回此套接字连接的地址。如果套接字未连接,则返回 null9.public int getPort()返回此套接字的端口。如果套接字未连接,则返回 -110.public DatagramPacket(byte[] buf,int length)构造 DatagramPacket,用来接收长度为 length 的数据包。 length 参数必须小于等于 buf.length。
11.public DatagramPacket(byte[] buf,int length,InetAddress address,int port)构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。length参数必须小于等于 buf.length。
12.public InetAddress getAddress()返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
13.public int getPort()返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。
14.public byte[] getData()返回数据缓冲区。接收到的或将要发送的数据从缓冲区中的偏移量 offset 处开始,持续 length 长度。
15.public int getLength()返回将要发送或接收到的数据的长度。

二、实现过程
发送端:
1.创建DatagramSocket对象
2.创建DatagramPacket对象并设置其参数DatagramPacket(data,数据开始位置,数据结束位置,目标ip地址,使用的端口号)
3.datagramSocket.send(datagramPacket);
4.关闭DatagramSocket
接收端:
1.创建DatagramSocket对象并指定端口号(与发送端设置的端口号一致)
2.创建DatagramPacket对象并设置参数DatagramPacket(b, 0, b.length)
3.receive
4.其他操作
5.关闭DatagramSocket

三、使用
public class Test {
    @org.junit.Test
    public void sender() {
        DatagramSocket datagramSocket = null;
        try {
            //DatagramSocket不用放端口号,因为我们会把数据封装到DatagramPacket中
            datagramSocket = new DatagramSocket();
            String data = "发送测试";
            byte[] b = new byte[1024];
            b = data.getBytes();
            //DatagramPacket datagramPacket = new DatagramPacket(data,数据开始位置,数据结束位置,目标ip地址,使用的端口号)
            DatagramPacket datagramPacket = new DatagramPacket(b, 0, b.length, InetAddress.getLocalHost(), 9090);
            datagramSocket.send(datagramPacket);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (datagramSocket != null) {
                datagramSocket.close();
            }
        }
    }

    @org.junit.Test
    public void receiver() {
        DatagramSocket datagramSocket = null;
        try {
            datagramSocket = new DatagramSocket(9090);
            byte[] b = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(b, 0, b.length);
            datagramSocket.receive(datagramPacket);
            System.out.println(new String(datagramPacket.getData(), 0, datagramPacket.getLength()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (datagramSocket != null) {
                datagramSocket.close();
            }
        }
    }
}
4.URL网络编程

URL:统一资源定位符,它表示 Internet 上某一 资源的地址。

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

URL对象的创建及常用方法

一、URL构造器
URL类的构造器都声明抛出非运行时异常,必须要对这一异常进行处理,通常是用 try-catch 语句进行捕获。
1.public URL (String spec):通过一个表示URL地址的字符串可以构造一个URL对象。
例如:URL url = new URL ("http://www. atguigu.com/"); 
2.public URL(URL context, String spec):通过基 URL 和相对 URL 构造一个 URL 对象。
例如:URL downloadUrl = new URL(url, “download.html")
3.public URL(String protocol, String host, String file);
例如:new URL("http", "www.atguigu.com", “download. html");
4.public URL(String protocol, String host, int port, String file); 
例如: URL gamelan = newURL("http", "www.atguigu.com", 80, “download.html");
二、常用方法
一个URL对象生成后,其属性是不能被改变的,但可以通过它给定的方法来获取这些属性:
1.public String getProtocol()-- 获取该URL的协议名
2.public String getHost()--获取该URL的主机名
3.public String getPort()--获取该URL的端口号
4.public String getPath()--获取该URL的文件路径
5.public String getFile()--获取该URL的文件名
6.public String getQuery()--获取该URL的查询名
7.URLConnection url.openConnection()--获取服务器的连接
8.URLConnection:表示到URL所引用的远程对象的连接。当与一个URL建立连接时,首先要在一个 URL 对象上通过方法 openConnection() 生成对应的 URLConnection对象。如果连接过程失败,将产生IOException. 
三、使用
URL url = new URL("http://localhost:8080/examples/myTest.txt");
System.out.println("getProtocol() :"+url.getProtocol());
System.out.println("getHost() :"+url.getHost());
System.out.println("getPort() :"+url.getPort());
System.out.println("getPath() :"+url.getPath());
System.out.println("getFile() :"+url.getFile());
System.out.println("getQuery() :"+url.getQuery());
                         
四、从某个服务器上下载资源
过程:
1.创建URL对象并指定网址
2.url.openConnection()连接服务器
3.2强转换为具体协议的URL连接如HttpURLConnection
4. huc.connect()连接
5.建立输入流以及输出文件流,并传数据
6.关闭流以及强壮之后的URL--HttpURLConnection

使用: 
    @org.junit.Test
    public void URLtest() {
        HttpURLConnection huc = null;
        InputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            URL url = new URL("http://www. atguigu.com/");
            URLConnection urlConnection = url.openConnection();
            huc = (HttpURLConnection) urlConnection;
            huc.connect();
            inputStream = huc.getInputStream();
            fileOutputStream = new FileOutputStream("OS3.jpg");
            int len;
            byte[] b = new byte[1024];
            while ((len = inputStream.read(b)) != -1) {
                fileOutputStream.write(b, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (huc != null) {
                    huc.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值