JAVA网络编程总结

一、相关概念

  • 网络通信:两台设备通过网络进行数据传输;
  • 网络:多台设备通过物理设备连接成网络;
  • ip地址:计算机的唯一标识,由网络地址和主机地址组成,占4个字节32位;
  • 域名:ip地址的映射,ip地址相当于身份证号,域名就是名字,都是唯一表示,只是为了方便记忆;
  • 端口:计算机上特定的网络程序(特定功能);ip地址是家,端口就是不同的房间,进厨房是做饭,进客厅是看电视,进卧室是睡觉; 
  • 网络协议:举个例子,人与人之间的交流,是文字(相当于程序的数据)以一定的形式组织起来(即语言)进行交流,文字的组织形式即语言,就是协议。程序与程序之间的交流,是数据以一定的形式组织起来进行传输(交流),数据的组织形式就是协议;
  • TCP协议:传输控制协议,相当于打电话,三个特点:

        1.通过“三次握手”的方式建立数据传输通道,可靠

        2.可传输大量数据

        3.需要释放连接,效率低

  • UDP协议:用户数据协议,相当于发信息,三个特点:

        1.将数据封装成数据包,无需连接,不可靠;

        2.数据包在64k以内,不能传输大量数据;

        3.无需释放连接,效率高(速度快);

二、InetAddress类

1.是什么?

是一个用来获取主机ip地址和主机名的类;

2.怎么用?

四个方法:InetAddress对象就是主机名+ip地址

三、Socket端点

(1).是什么?

  是两台机器(服务端 客服端)之间用来通讯(读写数据)的插头,网络通讯就是把网络当成一个流,在两个Socket之间进行通讯,即数据在两个Socket之间用IO流传输(InputStream和OutputStream),网络通讯其实就是两个Socket之间的通讯;举个例子:Socket就像是两个邻居房间的大门

什么是服务端、客户端?发起通讯请求的是客户端,接收通讯请求的是服务端;

(2).有什么用?

实现客户端和服务端之间的通讯(UDP是实现接收端和发送端之间的通讯);

(3).怎么用?

Socket编程有两种方式,一种是TCP编程(可靠),另一种是UDP编程(不可靠),又分别分为字节流和字符流

 第一种:TCP编程

数据读取:调用socket.getInputStream()来获得输入流对象来读取数据,调用socket.getOutputStream()来获得输出流对象来写入数据;可以使用包装流,也可以根据实际情况使用转换流将字节流转换成字符流;

具体过程:演示客户端连接服务端,客户端写入数据到数据通道,服务端从数据通道读取数据;

服务端:创建SocketSocket对象,传入端口,然后调用SocketSocket对象的accept()方法判断是否于客户端连接,如果连接了,就返回一个socket接口,用来获取一个IO流对象,用IO流对象来调用读写数据的方法,最后关闭IO流和socket(服务端的ServeSocket也要关闭)

客户端:和服务端差不多,创建一个Socket对象,用InetAddress.getLocalHost()方法传入IP地址和需要连接的端口,连接后生成Socket,通过Socket.getInputStream(), 获得一个与Socket有关的输入流对象,最后关闭IO流和socket

注意:

  1. 服务器的ServeSocket对象有什么用? 可以解决多并发的问题,它可以创建多个服务端socket端口来连接多个客户端socket端口,当客户端连接成功,就会通过accept()方法返回一个socket端口,注意最后也需要关闭
  2. 第二个socket端口有什么用?是真正用来通讯(读写数据)的端口,通过调用方法获得IO流对象,从而调用读写方法实现通讯
  3. 什么时候设置结束标志?输出流输出完后,要设置结束标志socket.shutdownOutput(),如果不设置,读取数据的端口不知道数据什么时候写完,就会出现卡顿;注意结束标志是端口调用的,不是输出流对象

TCP字节流案例如下:

import java.net.ServerSocket;
import java.net.Socket;//需要导入一个包

public class SocketTPC01Server {
    public static void main(String[] args)throws IOException {
        //思路;
        //1.创建SocketSocket对象,传入端口
        ServerSocket serverSocket = new ServerSocket(9999);
        //这个ServerSocket是用来解决多并发的问题,它可以创建多个服务端socket端口来连接多个客户端socket
        System.out.println("Server started");
        //2.等待客户端连接,如果未连接,程序阻塞;
        //如果连接了,返回一个Socket对象,程序继续(怎么返回一个Socket?用服务端的端口来调用,定义一个socket来接收)
        Socket socket=serverSocket.accept();
        System.out.println("Client connected");
        //3.获得一个IO流对象
        InputStream inputStream = socket.getInputStream();
        //4.通过输入流,读取客户端写到数据通道的数据,并显示
        byte[] buffer = new byte[1024];
        int readLen = 0;
        while ((readLen = inputStream.read(buffer)) != -1) {
            System.out.println(new String(buffer, 0, readLen));
        }
        //5.关闭输入流和Socket
        serverSocket.close();//不要忘记这个也要关闭
        socket.close();
        inputStream.close();

    }
}
package Socket;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;//注意先导入包

public class SocketTPC01Client {
    public static void main(String[] args) throws IOException {
        //思路:
        //1.创建一个Socket对象,传入IP地址和需要连接的端口
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("client"+socket.getClass());
        //2.连接后生成Socket,通过Socket.getInputStream(),
        // 获得一个与Socket有关的输入流对象
         OutputStream is = socket.getOutputStream();
        //3.通过输出流获取数据
        is.write("hello,server".getBytes());
        //4.关闭Socket和输出流
        is.close();
        socket.close();
    }
}

TCP字符流案例如下:

//韩顺平670集(TPC字符流编程)
//演示服务端9999连接客服端,读取数据
package Socket;

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

public class SocketTPC03Server {
    public static void main(String[] args)throws IOException {
        //思路;
        //1.创建Socket对象,传入端口(怎么创建Socket对象?)
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("Server started");
        //2.等待客户端连接,如果未连接,程序阻塞;
        //如果连接了,返回一个Socket对象,程序继续(怎么返回一个Socket?用服务端的端口来调用,定义一个socket来接收)
        Socket socket=serverSocket.accept();
        System.out.println("Client connected");
        //3.获得一个IO流对象
        InputStream inputStream = socket.getInputStream();
        //4.通过字符输入流,读取客户端写到数据通道的数据,并显示
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
       String s= bufferedReader.readLine();
        System.out.println(s);
        //5.获取Socket相关联的输出流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));//通过转换流将字节流转换成字符流
        bufferedWriter.write(s);
        bufferedWriter.newLine();//相当于结束标记,但对方必须用readLine()来读!!!
        bufferedWriter.flush();  //写完要手动刷新一下,否则数据不会写入数据通道
        //设置结束标记
        socket.shutdownOutput();
        //6.关闭输入流和Socket
        serverSocket.close();
        socket.close();
        bufferedWriter.close(); //用外层流来关闭
        bufferedReader.close();
        System.out.println("服务端退出");

    }
}
package Socket;

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

public class SocketTPC03Client {
    public static void main(String[] args) throws IOException {
        //思路:
        //1.创建一个Socket对象,传入IP地址和需要连接的端口
        Socket socket = new Socket(InetAddress.getLocalHost(),9999);
        System.out.println("client"+socket.getClass());
        //2.连接后生成Socket,通过Socket.getInputStream(),
        // 获得一个与Socket有关的输出流对象
         OutputStream is = socket.getOutputStream();
        //3.通过输出流获取数据
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(is));
        bufferedWriter.write("Hello server 字符流");
        bufferedWriter.newLine();//
        bufferedWriter.flush();//千万不要忘了,输出流要刷新
        //设置结束标记(结束标记写在哪?输出流的后面)
        socket.shutdownOutput();
        //4.获得一个与Socket有关的输入流对象
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String s=bufferedReader.readLine();
        System.out.println(s);
        //5.关闭Socket和输出流
        bufferedWriter.close();
        socket.close();
        bufferedReader.close();
        System.out.println("客户端退出");
    }
}

网络上传图片文件案例分析

代码思路:首先客户端,通过socket获得一个输入流对象,将磁盘上的图片读取到程序中,再将图片转换成字节数组,通过socket获得一个输出流对象,将字节数组写入数据通道;服务端,过socket获得一个输入流对象,将字节数组读取到程序中,然后写入文件中,最后再过socket获得一个输出流对象,返回消息收到图片

学习一定要趁热打铁,及时复习、刷题和巩固,不然基础会打不牢

第二种:UDP编程

   1.说明:UDP编程没有说明客户端和服务端,只有数据的接收端和发送端,那UDP是怎么进行数据的接收和发送的?是通过DategramSocket对象的发送和接收方法,发送端将数据封装到DategramSocket对象中(或者叫装包),接收端接收到DategramSocket对象,就对其拆包,取出数据(接收和发送的都是DategramPacket对象)注意DategramSocket对象可以指定哪个端口接收数据;

   DategramSocket和DategramPacket是什么?DategramSocket就是UDP编程的端口(发送端和接收端),DategramPacket是数据包,是用来封装数据的

 

2.通讯创建流程

3.案例分析

简单总结:接收端要接收数据,就先创建(定义)一个数据包packet来接收数据(数据包),然后拆包就可以显示数据了;而发送端要发送数据,也要先创建一个数据包packet,将要发送的数据放到到数据包里,然后发送即可

    package UDP;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    //韩顺平677集(演示UDP通讯)
    public class UDPReceiver {
        public static void main(String[] args) throws Exception {
            //1.创建DatagramSocket对象,准备在9999等待接收数据,9999是自己的端口
            DatagramSocket socket = new DatagramSocket(9999);
            //怎么接收数据?先创建一个数据包来储存数据
            //2.创建一个DatagramPacket对象数据包(本质是一个字节数组),将数组传给对象,用来储存数据
            byte[] buf = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            //3调用方法接收数据
            System.out.println("接收端A,等待接收");
            socket.receive(packet);//将接收到的数据放进数据包
            //4.拆包,调用packet方法获得接收到的数据字节大小和数据,创建一个字符串对象传进去
            int length = packet.getLength();
            byte[] data = packet.getData();
            String s = new String(data, 0, length);
            System.out.println(s);
            //5.接收端退出
            System.out.println("接收端A关闭");
            socket.close();
        }
    }
    ckage UDP;
    
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    //韩顺平677集(演示UDP通讯)
    public class UDPSender {
        public static void main(String[] args) throws Exception {
            //1.创建一个DatagramSocket对象,在9998端口等待接收数据
            //为什么不是在9999端口接收?接收端和发送端不能是同一个端口
            DatagramSocket socket = new DatagramSocket(9998);
            //2.装包,将要发送的数据封装到数据包里
            //怎么写我们要发送的数据?将我们要发送的数据先转换成字节数组(调用getByte方法),再将数据、数据字节长度、主机地址、要发送的端口传进数据包对象里
            byte[] data = "你好,小医仙".getBytes();
            DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("127.0.0.1"), 9999);
            //3.发送数据
            System.out.println("发送端B,等待发送");
            //将我们要发送的数据封装到packet里,然后将packet数据包发送出去
            socket.send(packet);
            //4.发送端退出
            System.out.println("发送端B关闭");
            socket.close();
        }
    }

    4.TCP和UDP的区别

      UDP是通过数据包的装包和拆包进行通讯,而TCP是通过IO流,创建数据通道进行通讯

    (4).何时用?

    四、相关知识点 

    1.netstat指令

        netstat -an :指令是用来查看主机网络情况的,端口连接情况和网络连接情况

        netstat -an |more :分页显示

        在win+r 命令窗口中打开;

    说明:

    • listering 表达有某个端口在监听
    • 如果有客户端连接到主机,就会显示一个外部地址
    • ctrl+c 退出程序

    2.当客户端连接服务端时,实际上也是通过一个端口与服务端进行连接的,但是这个端口是TCP/ip随机分配的,不是确定的(这就是为什么学高并发时,端口是有限的,端口会出现冲突)

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值