网络编程详解

网络编程其实就是要两台计算机之间进行数据传递。

那么两台计算机之间如何进行数据传递呢?

依赖于网络三要素

网络三要素

1.IP地址

2.端口号

3.协议

IP地址

IP地址全称互联网协议地址,是设备在网络中的唯一标识,注意域名会先经过DNS服务器解析成IP地址返回给我们的主机,然后在拿到IP地址后才能访问相应网址。

IP地址分为IPV4和IPV6

IPv4一共32位(4个字节),分为4组,采用点分十进制法表示。

由于IPV4只有32位至多能表示2^32,约等于42亿的地址,不够用了,然后推出了IPv6。

IPv4一共128位(16个字节),分为8组,采用冒分16进制法表示,会省略前导0,若是多个连续的0会用::表示。

在java中InetAddress类代表IP地址

获得实例对象的静态方法通过实例对象获得IP地址的方法通过实例对象获得主机名的方法
InetAddress.getByName(主机名)getHostAddress()getHostName()

端口号

端口号是应用程序在设备中的唯一标识

端口号是一个2个字节表示的整数,范围在0-65535(0-2^16-1)

其中0-1023被知名网络应用使用了,我们自己使用要使用1024及以上的端口号

协议

协议是计算机中连接和通信的规则

UDP协议

定义概述:

用户数据报协议(User Datagram Protocol)

UPD是面向无连接通信协议

特点:

速度快,一次至多传输64K,数据不安全,易丢失数据。

编程案例:
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        //1.找到快递公司
        DatagramSocket ds = new DatagramSocket();
        String s = null;
        while ((s = sc.nextLine()).equals("886") == false) {
            byte[] bytes = s.getBytes();
            //2.包装物品,填写地址
            DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"), 10000);
            //3.发送物品
            ds.send(datagramPacket);
        }
        //4.释放资源
        ds.close();
    }
}
​
public class SeverDemo {
    public static void main(String[] args) throws IOException {
        //1.找到快递公司
        DatagramSocket socket = new DatagramSocket(10000);
        while (true) {
            byte[] bytes = new byte[1024];
            //2.准备一个箱子装东西
            DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
            //3.接受快递,并装到新箱子里面去
            socket.receive(datagramPacket);
            //4.获得物品
            byte[] data = datagramPacket.getData();
            int length = datagramPacket.getLength();
            System.out.println(new String(data,0,length));
​
        }
        //5.释放资源
​
    }
}

注意:

1.要先启动接收端,才能启动发送端发送

2.接收端启动以后会一直停在接收方法处,等待发送端发送

3.在接收数据时要调用

UDP的三种通讯方式

1.单播:电脑通过路由器发送到一台电脑,1对1

单播地址就是接收方设备的ip地址

2.组播:电脑通过路由器发送到一组电脑,1对多

组播地址:224.0.0.0 - 239.255.255.255

其中224.0.0.0-224.0.0.255为预留地址,我们要使用只能从224.0.1.0开始使用

3.广播:电脑通过路由器发送到所有电脑,1对所有

广播地址:255.255.255.255

单播代码实例
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        //1.找到快递公司
        DatagramSocket ds = new DatagramSocket();
        String s = null;
        while ((s = sc.nextLine()).equals("886") == false) {
            byte[] bytes = s.getBytes();
            //2.包装物品,填写地址
            DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"), 10000);
            //3.发送物品
            ds.send(datagramPacket);
        }
        //4.释放资源
        ds.close();
    }
}
​
public class SeverDemo {
    public static void main(String[] args) throws IOException {
        //1.找到快递公司
        DatagramSocket socket = new DatagramSocket(10000);
        while (true) {
            byte[] bytes = new byte[1024];
            //2.准备一个箱子装东西
            DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
            //3.接受快递,并装到新箱子里面去
            socket.receive(datagramPacket);
            //4.获得物品
            byte[] data = datagramPacket.getData();
            int length = datagramPacket.getLength();
            System.out.println(new String(data,0,length));
​
        }
        //5.释放资源
    }
}
组播代码实例
public class CilentDemo01 {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket();
        String s = "组播";
        byte[] bytes = s.getBytes();
        InetAddress ip = InetAddress.getByName("224.0.1.0");
        int port = 10000;
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,ip,port);
        ds.send(dp);
        ds.close();
    }
}
​
public class SeverDemo01 {
    public static void main(String[] args) throws IOException {
        MulticastSocket ms = new MulticastSocket(10000);
​
        DatagramPacket datagramPacket = new DatagramPacket(new byte[1024], 1024);
​
        //把当前计算机加入到组里面
        ms.joinGroup(InetAddress.getByName("224.0.1.0"));
​
        ms.receive(datagramPacket);
​
        byte[] data = datagramPacket.getData();
        int length = datagramPacket.getLength();
​
​
        System.out.println(new String(data,0,length));
​
        ms.close();
​
    }
}
​
广播代码实例
public class CilentDemo02 {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket();
        String s = "广播";
        byte[] bytes = s.getBytes();
        InetAddress ip = InetAddress.getByName("255.255.255.255");
        int port = 10000;
        DatagramPacket dp = new DatagramPacket(bytes,bytes.length,ip,port);
        ds.send(dp);
        ds.close();
    }
}
​
public class SeverDemo02 {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(10000);
​
        DatagramPacket datagramPacket = new DatagramPacket(new byte[1024], 1024);
​
​
        ds.receive(datagramPacket);
​
        byte[] data = datagramPacket.getData();
        int length = datagramPacket.getLength();
​
​
        System.out.println(new String(data,0,length));
​
        ds.close();
​
    }
}

总结:

发送端代码:

单播、组播、广播的发送方都是1,代码也基本一致,只是DatagramPacket中的ip地址不同,单播传入的ip地址是接收方设备的ip地址,组播则是组播地址224.0.0.0-239.255.255.255,其中224.0.0.0-224.0.0.255为预留地址,我们程序中使用的是224.0.1.0-239.255.255.255,广播则是地址255.255.255.255

接收端代码:

单播和广播的接收端代码一致使用的是DatagramSocket,而组播使用的是MulticastSocket,因为多了一个把当前计算机加入到组中的操作,需要该类里面的joinGroup(InetAddress对象),InetAddress是那个组播地址的对象就加入到哪个组中,其他代码差不多一致,都是使用DatagramPacket来装数据。

TCP协议

定义概述

全称Transmisstion Control Protocol传输控制协议

TCP是面向连接的通信协议

特点

速度慢,没有大小限制,数据安全。

tcp编程案例
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //1.创建Socket对象
        Socket s = new Socket("127.0.0.1",10010);
​
        //2.获取输出流写出数据
        OutputStream os = s.getOutputStream();
        os.write("我是你爸爸".getBytes());
​
​
        //3.关闭资源,输出流关闭时会往接收端写一个结束标记
        os.close();
        s.close();
​
    }
}
​
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //1.创建Socket对象
        ServerSocket ss = new ServerSocket(10010);
​
        //2.等待客户端连接
        Socket accept = ss.accept();
​
        //3.获取输入流对象,读取数据
        InputStream is = accept.getInputStream();
        byte[] bytes = new byte[1024];
        int len = 0;
        while((len = is.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
​
        System.out.println("啊啊啊啊啊");
​
        //4.关闭流
        is.close();
        ss.close();
    }
}

注意:

1.accept()方法是阻塞的,会等待客户端的连接

2.tcp协议的客户端和服务端是通过三次握手来确保连接建立的

3.read()方法也是阻塞的,当客户端输出流关闭之前,没有获得结束标记,该方法会陷入阻塞,当输出流关闭之后客户端会给服务端写一个结束标记,此时read方法读取到结束标记-1才会结束循环

4.断开连接时通过四次挥手来确定连接终止

三次握手
四次挥手

挥手为什么比握手多一次?

当前客户端发送断开连接请求之后,服务器接受并响应收到消息,然后先处理数据,再确认断开,多了一个处理数据的过程。

客户端服务器数据响应案例

客户端上传文件到服务器,服务器响应一个数据

public class ClientDemo2 {
    public static void main(String[] args) throws IOException {
        //1.创建Socket
        Socket s = new Socket("127.0.0.1",10020);
​
        //2.从本地读取数据文件边读边写
        BufferedInputStream bi = new BufferedInputStream(new FileInputStream("D:\\project\\java\\demo1\\A\\1.txt"));
        OutputStream os = s.getOutputStream();
​
        int b ;
        while((b = bi.read())!=-1){
            os.write(b);
        }
        s.shutdownOutput();
​
​
        //3.等待服务器响应的数据,用输入流读取
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String line = null;
        while((line = br.readLine())!=null){
            System.out.println(line);
        }
​
        //4.关闭流
        //本地流要手动关闭
        bi.close();
        //网络流只需要关闭socket
        s.close();
    }
}
​
public class ServerDemo2 {
    public static void main(String[] args) throws IOException {
        //1.创建Socket对象
        ServerSocket ss = new ServerSocket(10020);
​
        //2.等待客户端连接
        Socket accept = ss.accept();
​
        //3.获取输入流对象,读取数据,并写入到本地
        InputStream is = accept.getInputStream();
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\project\\java\\demo1\\B\\2.txt"));
​
        int c;
        while((c = is.read())!=-1){
            bos.write(c);
        }
​
        //4.获取输出流对象,写数据给客户端
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
        bw.write("上传成功");
        bw.newLine();
        bw.flush();
​
        //5.关闭流
        bos.close();
        accept.close();
        ss.close();
    }
}
​

注意:

1.网络流是指与socket有关在网络中输入输入的流,本地流是将程序与本地进行输入输出的流

2.网络流的关闭只需要关闭socket对象即可,本地流需要手动关闭

3.网络流写数据时记得shutdownOutput关闭流并写结束标记

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值