12、网络编程

12、网络编程

概述:

网络编程中的两个主要问题:

  1. 如何准确定位网络上的主机,定位主机上的应用:

    • IP + 端口号
  2. 找到主机后如何可靠高效的进行数据传输

    • 网络通信协议 TCP/IP参考模型

      image-20220407162553445

通信要素一:IP和端口号

 IP:唯一标识Internet上的计算机 (127.0.0.1本地回环地址)

 IP分类:IPv4 与 IPv6 ;万维网 与 局域网

 Java中 InetAddress类 代表IP,

//实例化InetAddress
getByName(String host)//ip 或 域名
getLocalhost()    //获取本机地址
//两个常用方法
 .getHostName()
 .getHostAddress()

 端口号: 标识正在计算机上运行的进程(程序) 0~65535。
公认端口 0~1023 ,注册端口 1024~49151,动态/私有端口 49152~65535

 端口号与IP 地址的组合得出一个网络套接字Socket

通信要素二:网络通信协议

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

Socket:
把网络连接当成一个流,数据在两个Socket间通过IO传输
流套接字(stream socket):使用TCP提供可依赖的字节流服务
数据报套接字(datagram socket):使用UDP提供“尽力而为”的数据报服务

TCP网络编程

客户端:

  1. 创建Socket对象,指明服务器端的 ip 和 端口号
  2. 获取一个输出流,用于输出数据
  3. 写出数据操作
  4. 关闭资源

客户端:

  1. 创建服务器端的 ServerSocke,指明自己的端口号
  2. 调用accept( ) 表示接收来自客户端的socke
  3. 读取输入流中的数据
  4. 关闭资源
image-20220407184743895

传输文件:

public void client() throws Exception {
    //1.创建socket对象,指明服务器端的 ip+端口
    Socket socket = new Socket(InetAddress.getLocalHost(), 4545);
    //2.获取输出流 ,写出数据
    OutputStream os = socket.getOutputStream();
    FileInputStream fis = new FileInputStream("1.jpg"); //获取图片数据
    int len;
    byte[] buffer = new byte[1024];
    while ( (len=fis.read(buffer))!=-1 ){
        os.write(buffer,0,len);     //写入输出流
    }
    //3.关闭资源
    fis.close();
    os.close();
    socket.close();
}

public void server() throws Exception {
    //1.创建服务器端的 ServerSocket,指明自己的端口号
    ServerSocket ss = new ServerSocket(4545);
    //2.调用accept() 表示接收来自客户端的socket
    Socket socket = ss.accept();
    //3.获取输出流中的数据
    InputStream is = socket.getInputStream();
    FileOutputStream fos = new FileOutputStream("2.jpg");
    int len;
    byte[] buffer = new byte[1024];
    while ( (len=is.read(buffer))!=-1 ){
        fos.write(buffer,0,len);
    }
    //4.关闭资源
    fos.close();
    is.close();
    socket.close();
    ss.close();
}

服务器接收完文件后,给客户端返回信息:

public void client() throws Exception {
    //1.创建socket对象,指明服务器端的 ip+端口
    Socket socket = new Socket(InetAddress.getLocalHost(), 4545);
    //2.获取输出流 ,写出数据
    OutputStream os = socket.getOutputStream();
    FileInputStream fis = new FileInputStream("1.jpg"); //获取图片数据
    int len;
    byte[] buffer = new byte[1024];
    while ( (len=fis.read(buffer))!=-1 ){
        os.write(buffer,0,len);     //写入输出流
    }
    //通知服务器,传输完毕
    socket.shutdownOutput();    //表示客户端传输完毕,不再输出数据,服务端可以发送数据
	
    //接收服务器返回的信息 并打印
    InputStream is = socket.getInputStream();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    while ( (len=is.read(buffer))!=-1 ){
        baos.write(buffer,0,len);
    }
    System.out.println(baos.toString());

    //3.关闭资源
    fis.close();
    os.close();
    socket.close();
    baos.close();is.close();
}

public void server() throws Exception {
    //1.创建服务器端的 ServerSocket,指明自己的端口号
    ServerSocket ss = new ServerSocket(4545);
    //2.调用accept() 表示接收来自客户端的socket
    Socket socket = ss.accept();
    //3.获取输出流中的数据
    InputStream is = socket.getInputStream();
    FileOutputStream fos = new FileOutputStream("2.jpg");
    int len;
    byte[] buffer = new byte[1024];
    while ( (len=is.read(buffer))!=-1 ){    //read是一个阻塞式方法,需要标识是否传输完毕
        fos.write(buffer,0,len);
    }

    //接收完成后,给客户端发送信息
    OutputStream os = socket.getOutputStream();
    os.write("照片接收已完成~".getBytes());

    //4.关闭资源
    fos.close();
    is.close();
    socket.close();
    ss.close();
    os.close();
}

UDP网络编程

  1. DatagramSocket与DatagramPacket
  2. 建立发送端,接收端
  3. 建立数据包
  4. 调用Socket的发送、接收方法
  5. 关闭Socket

 发送端与接收端是两个独立的运行程序

public void sender() throws Exception {
    //1.建立一个Socket
    DatagramSocket socket = new DatagramSocket();
    //2.建包,封装数据
    byte[] data = "我是UDP连接方式~".getBytes();
    InetAddress ip = InetAddress.getLocalHost();
    //封装数据报                  DatePacket(字节数据,数据开始,数据结束,ip,端口)
    DatagramPacket packet = new DatagramPacket(data,0,data.length,ip,5454);
    //3.发送包
    socket.send(packet);
    //4.关闭资源
    socket.close();
}

public void receiver() throws IOException {
    //1.创建socket对象,指明端口号
    DatagramSocket socket = new DatagramSocket(5454);
    //2.建包,准备接收数据
    byte[] buffer = new byte[1024];
    DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
    //3.接收数据
    socket.receive(packet);  //此时数据已经存在 buffer中了
    //   System.out.println(new String(packet.getData(),0,packet.getLength()));
    System.out.println(new String(buffer,0,buffer.length));
    //4.关闭资源
    socket.close();
}

URL网络编程

 URL(Uniform Resource Locator):统一资源定位符,定位 Internet 上某一资源的地址。

 URL由五部分组成:传输协议://主机名: 端口号/文件名 #片段名 ?参数列表

常用方法:

public String getProtocol( ) 获取该URL的协议名
public String getHost( ) 获取该URL的主机名
public String getPort( ) 获取该URL的端口号
public String getPath( ) 获取该URL的文件路径
public String getFile( ) 获取该URL的文件名
public String getQuery( ) 获取该URL的查询名

下载网站资源

public void URL_download() throws Exception{
    //1.创建URL对象,获取连接对象
    String ur = "http://m10.music.126.net/20220407201631/edf99a1e630704529b26cfb1cadddab5/ymusic/560e/5352/0f5b/ad656bf54ad8b8b421b4811622f27cb7.mp3";
    URL url = new java.net.URL(ur);
    
    HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
    urlConnection.connect();
    //2.获取网站资源
    InputStream is = urlConnection.getInputStream();
    FileOutputStream fos = new FileOutputStream("url.jpg");
    byte[] buffer = new byte[1024];
    int len;
    while ( (len=is.read(buffer))!=-1 ){
        fos.write(buffer,0,len);
    }
    //3.关闭资源,关闭连接
    fos.close();
    is.close();
    urlConnection.disconnect();
}

PS: 附:忽略网站信任证书 工具类:HttpsURLValidator

点击查看代码
/**     忽略证书信任问题
 *  一个信任 https证书的工具类,
在urlConnection请求前 加入一条语句 : HttpsURLValidator.httpsRequestTrue(url); //url为https请求地址
 */
//import lombok.extern.slf4j.Slf4j;
import sun.net.www.protocol.https.HttpsURLConnectionImpl;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

//@Slf4j
public class HttpsURLValidator {
    HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String urlHostName, SSLSession session) {
            System.out.println("Warning: URL Host: " + urlHostName + " vs. "
                               + session.getPeerHost());
            return true;
        }
    };

    /**
     * https忽略SSL的方法
     * @param url
     */
    public static void httpsRequestTrue(String url){//访问https地址直接调用这个方法
        try {
            //忽略https证书的再请求
            HttpsURLValidator.trustAllHttpsCertificates();
            HostnameVerifier hv = new HostnameVerifier() {
                public boolean verify(String urlHostName, SSLSession session) {
                    return true;
                }
            };
            URL u = new URL(url);
            HttpsURLConnection.setDefaultHostnameVerifier(hv);
            URLConnection urlConnection = (HttpsURLConnectionImpl)u.openConnection();
        }catch (Exception e){
            e.printStackTrace();
            //     log.error(e.getMessage());
        }
    }

    protected final String retrieveResponseFromServer(final URL validationUrl,
                                                      final String ticket) {
        HttpURLConnection connection = null;
        try {
            connection = (HttpURLConnection) validationUrl.openConnection();
            final BufferedReader in = new BufferedReader(new InputStreamReader(
                connection.getInputStream()));

            String line;
            final StringBuffer stringBuffer = new StringBuffer(255);

            synchronized (stringBuffer) {
                while ((line = in.readLine()) != null) {
                    stringBuffer.append(line);
                    stringBuffer.append("\n");
                }
                return stringBuffer.toString();
            }

        } catch (final IOException e) {
            //    log.error(e.getMessage());
            e.printStackTrace();
            return null;
        } catch (final Exception e1){
            //   log.error(e1.getMessage());
            e1.printStackTrace();
            return null;
        }finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
    protected static void trustAllHttpsCertificates() throws Exception {
        javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
        javax.net.ssl.TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
            .getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
                                                                    .getSocketFactory());
    }

    static class miTM implements javax.net.ssl.TrustManager,
    javax.net.ssl.X509TrustManager {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(
            java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(
            java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(
            java.security.cert.X509Certificate[] certs, String authType)
            throws java.security.cert.CertificateException {
            return;
        }

        public void checkClientTrusted(
            java.security.cert.X509Certificate[] certs, String authType)
            throws java.security.cert.CertificateException {
            return;
        }
    }
}
posted @   simp1e1  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示