java网络编程

java 网络编程

一、概述

(一)、计算机网络

​ 把分布在不同地理区域的计算机胡专门的外部设备用通信线路互连城一个规模大、功能强的网络系统,从而使总多计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源。

(二)、网络编程的目的

直接或间接地通过网络协议与其他计算机进行通讯 。

(三)、网络编程的主要两个问题

  1. 如何准确的定位网络上一台或多台主机。
  2. 找到主机后如何可靠高效地进行数据传输。

二、通讯要素

(一)、IP和port

1. Ip地址
  • 唯一的标识Internet上的计算机。
  • 本地回环地址(hostAddress): 127.0.0.1 主机名(hostName)、localhost。
2. 端口号
  • 标识正在计算机上运行的进程(程序)。

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

  • 被规定为一个16位整数的0~65535, 0-1023被预先定义的服务铜线占用,所以我们要用的话就选择1024-65535之间的某一个端口尽心通信,以免端口冲突。

IP和端口号组合得到一个网络套接字。

(二)、网络通信协议

​ 计算机网络中实现通信必须要有一些约定,这就是通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。

1. TCP/IP协议簇
  • 传输控制协议TCP
    • 使用TCP之前,必须建立TCP连接,形成传输数据通道。
    • 传输前,采用“三次握手‘方式,是可靠的。
    • TCP协议进行通信的两个应用进程:客户端、服务端。
    • 在连接中可进行大数据量的传输。
    • 传输完毕,必须释放已建立的连接,效率低。
  • 用户数据包协议UDP

    • 将数据、源、目的封装成数据包,不需要建立连接。
    • 每个数据包的大小限制在64K内。
    • 不需要连接,不可靠。
    • 发送数据结束时不需要释放资源,速度快。

      1. IP协议是网络层的主要协议,支持网间互连的数据通信。
      2. TCP/IP四层体系结构:物理链路层、IP层、传输层和应用层

三、InetAddress类

1. InetAddress 类的方法

这个类表示互联网协议(IP)地址。下面列出了 Socket 编程时比较有用的方法:

序号方法描述
1static InetAddress getByAddress(byte[] addr) 在给定原始 IP 地址的情况下,返回 InetAddress 对象。
2static InetAddress getByAddress(String host, byte[] addr) 根据提供的主机名和 IP 地址创建 InetAddress。
3static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。
4String getHostAddress() 返回 IP 地址字符串(以文本表现形式)。
5String getHostName() 获取此 IP 地址的主机名。
6static InetAddress getLocalHost() 返回本地主机。
7String toString() 将此 IP 地址转换为 String。

2. InetAddress类的创建和使用

  1. 创建

    package lj.socket;
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    /**
    * Class InetAddressTest ...
    * @author LiJun
    * Created on 2018/8/10
    * InetAddress:位于java.net包下
    * 1.InetAddress用来代表IP地址,一个InetAddress对象就代表着一个IP地址
    * 2.创建InetAddress对象:getName(String host)
    * 3. getHostName() getHostAddress
    */
    public class InetAddressTest {
       public static void main(String[] args) throws UnknownHostException {
           // 获取的时候先先找本地的hosts,是否有输入的域名地址,没有的话,通过DNS服务器,找到主机
           // 本地hosts文件目录 C:\Windows\System32\drivers\etc\hosts
           InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
           // 结果为:www.baidu.com
           System.out.println(inetAddress.getHostName());
           // 结果为:180.97.33.107
           System.out.println(inetAddress.getHostAddress());
    
           // 获取本地主机
           InetAddress inetAddress1 = InetAddress.getLocalHost();
           System.out.println(inetAddress1.getHostName());
           System.out.println(inetAddress1.getHostAddress());
       }
    }
  2. 2.

四、TCP-UDP

(一)、Socket

  • 利用套接字(socket)开发应用程序,是当前的标准了。
  • 通信的两端都要有Socket,是两台机器间通信的端点。
  • 网络通信其实就是Socket间的通信。
  • Socket允许程序把网络连接当成一个流,数据在两个Socket间通过I/O传输。
  • 一般主动发起通讯的应用程序属客户端,等待通信请求的属服务端。
1.ServerSocket 类的方法

服务器应用程序通过使用 java.net.ServerSocket 类以获取一个端口,并且侦听客户端请求。

ServerSocket 类有四个构造方法:

序号方法描述
1public ServerSocket(int port) throws IOException 创建绑定到特定端口的服务器套接字。
2public ServerSocket(int port, int backlog) throws IOException 利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
3public ServerSocket(int port, int backlog, InetAddress address) throws IOException 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
4public ServerSocket() throws IOException 创建非绑定服务器套接字。
5public int getLocalPort() 返回此套接字在其上侦听的端口。
6public Socket accept() throws IOException 侦听并接受到此套接字的连接。
7public void setSoTimeout(int timeout) 通过指定超时值启用/禁用 SO_TIMEOUT,以毫秒为单位。
8public void bind(SocketAddress host, int backlog) 将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
2.Socket 类的方法

java.net.Socket 类代表客户端和服务器都用来互相沟通的套接字。客户端要获取一个 Socket 对象通过实例化 ,而 服务器获得一个 Socket 对象则通过 accept() 方法的返回值。

Socket 类有五个构造方法.

序号方法描述
1public Socket(String host, int port) throws UnknownHostException, IOException. 创建一个流套接字并将其连接到指定主机上的指定端口号。
2public Socket(InetAddress host, int port) throws IOException 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
3public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException. 创建一个套接字并将其连接到指定远程主机上的指定远程端口。
4public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException. 创建一个套接字并将其连接到指定远程地址上的指定远程端口。
5public Socket() 通过系统默认类型的 SocketImpl 创建未连接套接字
6public void connect(SocketAddress host, int timeout) throws IOException 将此套接字连接到服务器,并指定一个超时值。
7public InetAddress getInetAddress() 返回套接字连接的地址。
8public int getPort() 返回此套接字连接到的远程端口。
9public int getLocalPort() 返回此套接字绑定到的本地端口。
10public SocketAddress getRemoteSocketAddress() 返回此套接字连接的端点的地址,如果未连接则返回 null。
11public InputStream getInputStream() throws IOException 返回此套接字的输入流。
12public OutputStream getOutputStream() throws IOException 返回此套接字的输出流。
13public void close() throws IOException 关闭此套接字。

(二)、TCP-Socket

  1. 实现内容客户端给服务端发送消息,服务端接收并显示出来

    package lj.socket;
    
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
    * Class TCPTest1 ...
    * 实现内容客户端给服务端发送消息,服务端接收并显示出来
    *
    * @author LiJun
    * Created on 2018/8/10
    */
    public class TCPTest1 {
    
       /**
        * 客户端
        */
       @Test
       public void client() {
           Socket socket = null;
           OutputStream outputStream = null;
           try {
               // 创建一个Socket的对象,通过构造器指明服务端的Ip地址,以及其接收程序的端口号
               socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
               // getOutputStream() 发送数据
               outputStream = socket.getOutputStream();
               // 具体的输出过程
               outputStream.write("我是客户端".getBytes());
           } catch (Exception e) {
               e.printStackTrace();
           } finally {
               // 关闭响应的流和socket
               if (outputStream != null) {
                   try {
                       outputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if (socket != null) {
                   try {
                       socket.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
           }
       }
    
       /**
        * 服务端
        */
       @Test
       public void server() {
           ServerSocket serverSocket = null;
           Socket socket = null;
           InputStream inputStream = null;
           try {
               // 创建一个ServerSocket的对象,通过构造器指明自身的端口号
               serverSocket = new ServerSocket(9090);
               // 调用accept方法,返回一个Socket对象
               socket = serverSocket.accept();
               // 调用Socket的getInputStream方法获取从服务端发送过来的输入流
               inputStream = socket.getInputStream();
               // 处理获取到的数据
               byte[] bytes = new byte[20];
               int len = 0;
               while ((len = inputStream.read(bytes)) != -1) {
                   String string = new String(bytes, 0, len);
                   System.out.println(string);
               }
           } catch (IOException e) {
               e.printStackTrace();
           } finally {
               // 关闭相应的流和Socket、ServerSock而对象
               if (inputStream != null) {
                   try {
                       inputStream.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();
                   }
               }
           }
    
       }
    }
    
  2. 实现客户端给服务端发送消息,服务端接收并显示出来并反馈信息

    package lj.socket;
    
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
    * Class TCPTest2 ...
    * 实现客户端给服务端发送消息,服务端接收并显示出来并反馈信息
    *
    * @author LiJun
    * Created on 2018/8/10
    */
    public class TCPTest2 {
    
       /**
        * 客户端
        */
       @Test
       public void client() {
           Socket socket = null;
           OutputStream outputStream = null;
           InputStream inputStream = null;
           try {
               // 创建一个Socket的对象,通过构造器指明服务端的Ip地址,以及其接收程序的端口号
               socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
               // getOutputStream() 发送数据
               outputStream = socket.getOutputStream();
               // 具体的输出过程
               outputStream.write("我是客户端".getBytes());
    /**********************************************************/
               socket.shutdownOutput();
    /**********************************************************/
               inputStream = socket.getInputStream();
               byte[] bytes = new byte[20];
               int len = 0;
               while ((len = inputStream.read(bytes)) != -1) {
                   String string = new String(bytes, 0, len);
                   System.out.println(string);
               }
    
           } catch (Exception e) {
               e.printStackTrace();
           } finally {
               // 关闭响应的流和socket
               if (inputStream != null) {
                   try {
                       inputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if (outputStream != null) {
                   try {
                       outputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if (socket != null) {
                   try {
                       socket.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
           }
       }
    
       /**
        * 服务端
        */
       @Test
       public void server() {
           ServerSocket serverSocket = null;
           Socket socket = null;
           InputStream inputStream = null;
           OutputStream outputStream = null;
           try {
               // 创建一个ServerSocket的对象,通过构造器指明自身的端口号
               serverSocket = new ServerSocket(9090);
               // 调用accept方法,返回一个Socket对象
               socket = serverSocket.accept();
               // 调用Socket的getInputStream方法获取从服务端发送过来的输入流
               inputStream = socket.getInputStream();
               // 处理获取到的数据
               byte[] bytes = new byte[20];
               int len = 0;
               while ((len = inputStream.read(bytes)) != -1) {
                   String string = new String(bytes, 0, len);
                   System.out.println(string);
               }
               outputStream = socket.getOutputStream();
               outputStream.write("我已经收到了".getBytes());
    
           } catch (IOException e) {
               e.printStackTrace();
           } finally {
               // 关闭相应的流和Socket、ServerSock而对象
               if (outputStream != null) {
                   try {
                       outputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if (inputStream != null) {
                   try {
                       inputStream.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();
                   }
               }
           }
    
       }
    }

    重点在于客户端发送了消息后的 socket.shutdownOutput();

  3. 从客户端发送文件给服务端,服务端保存包本地,反馈消息给客户端。

    package lj.socket;
    
    import org.junit.Test;
    
    import java.io.*;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
    * Class TCPTest3 ...
    *
    * @author LiJun
    * Created on 2018/8/10
    */
    public class TCPTest3 {
    
       /**
        * 客户端
        */
       @Test
       public void client() {
           Socket socket = null;
           OutputStream outputStream = null;
           FileInputStream fileInputStream = null;
           InputStream inputStream = null;
           try {
               socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
               outputStream = socket.getOutputStream();
               fileInputStream = new FileInputStream(new File("D://1.txt"));
               byte[] bytes = new byte[1024];
               int len = 0;
               while ((len = fileInputStream.read(bytes)) != -1) {
                   outputStream.write(bytes, 0, len);
               }
               // 表明客户端发送成功
               socket.shutdownOutput();
    
               inputStream = socket.getInputStream();
               len = 0;
               while ((len = inputStream.read(bytes)) != -1) {
                   String string = new String(bytes, 0, len);
                   System.out.println(string);
               }
    
           } catch (Exception e) {
               e.printStackTrace();
           } finally {
               // 关闭响应的流和socket
               if (inputStream != null) {
                   try {
                       inputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if (fileInputStream != null) {
                   try {
                       fileInputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if (outputStream != null) {
                   try {
                       outputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if (socket != null) {
                   try {
                       socket.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
           }
       }
    
       /**
        * 服务端
        */
       @Test
       public void server() {
           ServerSocket serverSocket = null;
           Socket socket = null;
           InputStream inputStream = null;
           FileOutputStream fileOutputStream = null;
           OutputStream outputStream = null;
           try {
               serverSocket = new ServerSocket(9090);
               socket = serverSocket.accept();
               inputStream = socket.getInputStream();
               fileOutputStream = new FileOutputStream(new File("D://2.txt"));
               byte[] bytes = new byte[1024];
               int len = 0;
               while ((len = inputStream.read(bytes)) != -1) {
                   fileOutputStream.write(bytes, 0, len);
               }
               outputStream = socket.getOutputStream();
               outputStream.write("我已经成功接收".getBytes());
    
           } catch (IOException e) {
               e.printStackTrace();
           } finally {
               // 关闭相应的流和Socket、ServerSock而对象
               if (outputStream != null) {
                   try {
                       outputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if (fileOutputStream != null) {
                   {
                       try {
                           fileOutputStream.close();
                       } catch (IOException e) {
                           e.printStackTrace();
                       }
                   }
               }
               if (inputStream != null) {
                   try {
                       inputStream.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();
                   }
               }
           }
    
       }
    }
    

(三)、UDP

  • 类DatagramSocket和 DatagramPacket实现UDP协议。
  • UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能安全传输,也不能确定什么时候能传输成功。
  • DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
  • UDP协议中每个数据报都给出了完整的地址信息,无须建立发送方和接收方的连接。
package lj.socket;

import org.junit.Test;

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

/**
 * Class UDPTest ...
 *
 * @author LiJun
 * Created on 2018/8/10
 */
public class UDPTest {
    /**
     * 发送端
     */
    @Test
    public void send() {

        DatagramSocket datagramSocket = null;
        try {
            datagramSocket = new DatagramSocket();

            byte[] bytes = "hello world".getBytes();
            DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length,
                    InetAddress.getByName("127.0.0.1"), 9090);

            datagramSocket.send(datagramPacket);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (datagramSocket != null) {
                datagramSocket.close();
            }
        }


    }

    /**
     * 接收端
     */
    @Test
    public void receive() {
        DatagramSocket datagramSocket = null;
        try {
            datagramSocket = new DatagramSocket(9090);
            byte[] bytes = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length);
            datagramSocket.receive(datagramPacket);

            String string = new String(datagramPacket.getData(), 0, datagramPacket.getLength());
            System.out.println(string);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (datagramSocket != null) {
                datagramSocket.close();
            }
        }
    }
}

五、URL编程

  • URL

    统一资源定位符,他表示Internet上某一资源的地址。通过URL我们可以访问Internet上的各种网络资源,比如常见的www、ftp站点。浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源。

  • URL的j基本结构(5部分)

    <传输协议>://<主机名>:<端口号>/<文件名>

    eg:http://39.106.200.103:8080/test/index.html

package lj.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

/**
 * Class URLTest ...
 *
 * @author LiJun
 * Created on 2018/8/10
 */
public class URLTest {

    public static void main(String[] args) {
        // 1.创建一个URL对象
        URL url = null;
        URLConnection urlConnection = null;
        InputStream inputStream = null;
        try {
            url = new URL("https://dzs.qisuu.la/txt/31268.txt");
            urlConnection = url.openConnection();

            // 获取该URL的协议名
            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.getRef());
            // 获取该URL的查询名
            System.out.println(url.getQuery());


            // 如何将服务端的文件保存下来

            // 处理读取中文的时候可能要乱码的问题 utf-8和gbk都试试
            inputStream = urlConnection.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
            String string;
            while ((string = br.readLine()) != null) {
                System.out.println(string);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值