什么是网络编程?

可以让设备中的程序与网络上的其他设备中的成勋数据交互(实现网络通讯)

java提供了哪些网络编程的解决方案

java.net.*包下提供了网络编程的解决方案

基本通讯架构

  • CS架构:(Client客户端   /   Server服务端)
  • BS架构: (Browser浏览器  /  Server服务端)

网络通讯的三要素

ip地址:(cmd -> ipconfig:IPv4(32字节))

        设备在网络中的唯一标识(上网设备上的身份号码)

        IP地址的两种形式:IPv4(32字节)、IPv6(128位):号称可以为地球上每一粒沙子编号

        IP域名:记录了服务器的ip

        公网IP:是可以链接互联网的IP地址

        内网ip也局域网ip,只能组织机构内部使用

        192.168.开头的都是常见的局域网地址

        192.168.00--192.168.255.255专门为组织机构内部使用

        127.0.0.1 、 localhost本机IP,只会寻找当前所在主机

  •  IP常见命令:

    •  ipconfig:查看IP地址

    •  ping IP地址:看链接通不通
  • IP地址相关的类:

    • InetAddress的常用方法如下:

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


public class InetAddressText {
    public static void main(String[] args) throws IOException {
        //获取本机的IP地址对象
        InetAddress ip1 = InetAddress.getLocalHost();
        System.out.println(ip1.getHostName());
        System.out.println(ip1.getHostAddress());

        ///获取指定的ip或则域名的IP地址对象
        InetAddress ip2 = InetAddress.getByName("www.baidu.com");
        System.out.println(ip2.getHostName());
        System.out.println(ip2.getHostAddress());

        //相当于ping
        System.out.println(ip2.isReachable(6000));
    }
}

端口:(可以标志0-65535个应用程序)(自己开发的程序用注册端口号)

应用程序在设备中唯一的标识

周知端口:0-1023,被预先定义的知名应用占用(http80、ftp21)
注册端口:1024-49151,分配给用户进程或某些应用程序
动态端口:49152-65535,之所以被称为动态端口,是因为她一般不固定分配某种进程,而是动态分配

协议:

链接和数据在网络中传输的规则

开放式网络互连标准:()

osi网络参考模型:全球网络互联网标准

TCP/IP网络模型:事实上的国际标准

传输层2个通讯协议

UDP(用户数据协议),TCP传输控制协议

UDP协议:

  • 特点:无连接,不可靠通讯
  • 不事先建立链接,数据按照包发,一包数据包含:自己的ip、程序端口、目的IP、程序端口和数据(限制在64KB内)等等。
  • 发送不管对方是否在线,数据在中间丢失也不管,如果接受方收到数据也不返回确认
  • 通讯效率高,视频,通话应用

TCP协议:

  • 特点:面向链接,可靠通讯
  • tcp的最终目的:要保证在不可靠的信道上实现可靠传输 
  • YCP主要有三个步骤实现可靠传输:三次握手建立链接,传输数据进行确认。四次挥手断开连接
  • 三次握手:发出链接请求、返回一个响应、发出确认信息,确认链接、
  • 四次挥手:发出断开请求、返回一个响应:稍等、返回一个响应,确认断开、发出正式确认断开链接

UDP通讯

java提供了Java.net.DatagramSocket类来实现UDP通讯

DatagramSocket类:用于创建客户端、服务端:

客户端:

package com.Game_All.UDP;

import java.io.IOException;
import java.net.*;

public class Client {
    public static void main(String[] args) throws IOException {
        //1、创建客户端对象
        DatagramSocket socket = new DatagramSocket();
        //2、创建数据包对象
        /*public DatagramPacket(byte buf[], int length,
        InetAddress address, int port) {
            this(buf, 0, length, address, port);*/

        byte[] bytes = "我是快乐的客户端,我爱你黄洁".getBytes();
       /*
        参数一:封装要发出去的数据。
        参数二:发送出去的数据大小(字节个数)
        参数三:服务端的TP地址(找到服务端主机)
        参数四:服务端程序的端口
        */
        DatagramPacket packet = new DatagramPacket(bytes,bytes.length,InetAddress.getLocalHost(),6666);

        //3、发送
        socket.send(packet);
        System.out.println("客户端发送完毕");
        socket.close();//释放资源
    }
}

服务端:

package com.Game_All.UDP;

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

public class Server {
    public static void main(String[] args) throws IOException {
        //1、创建一个服务端(注册端口)
        DatagramSocket socket = new DatagramSocket(6666);

        //2、创建一个数据包对象,用于接收数据的
        byte[] buffer = new byte[1024*64];//64kb
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        //3、接收
        socket.receive(packet);

        //4、从字节数组中,吧即受到的数据直接打印出来
        //接收到多少就到处多少
        int len = packet.getLength();
        String rs = new String(buffer,0,len);
        System.out.println(rs);
        System.out.println(packet.getAddress().getHostAddress());
        System.out.println(packet.getPort());

        socket.close();

    }
}

先运行服务端!!!!

多发多收

package com.Game_All.UDP;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        //1、创建客户端对象
        DatagramSocket socket = new DatagramSocket();
        //2、创建数据包对象
        /*public DatagramPacket(byte buf[], int length,
        InetAddress address, int port) {
            this(buf, 0, length, address, port);*/
       /*
        参数一:封装要发出去的数据。
        参数二:发送出去的数据大小(字节个数)
        参数三:服务端的TP地址(找到服务端主机)
        参数四:服务端程序的端口
        */
        Scanner scan = new Scanner(System.in);
        while (true){
            System.out.println("请说:");
            String msg = scan.nextLine();

            if ("exit".equals(msg)){
                System.out.println("欢迎下次光临!退出成功");
                socket.close();
                break;
            }
            byte[] bytes = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(bytes,bytes.length,InetAddress.getLocalHost(),6666);
            //3、发送
            socket.send(packet);
        }
    }
}



package com.Game_All.UDP;

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

public class Server {
    public static void main(String[] args) throws IOException {
        //1、创建一个服务端(注册端口)
        DatagramSocket socket = new DatagramSocket(6666);

        //2、创建一个数据包对象,用于接收数据的
        byte[] buffer = new byte[1024*64];//64kb
        DatagramPacket packet = new DatagramPacket(buffer,buffer.length);

        while (true) {
            //3、接收
            socket.receive(packet);

            //4、从字节数组中,吧即受到的数据直接打印出来
            //接收到多少就到处多少

            int len = packet.getLength();
            String rs = new String(buffer,0,len);
            System.out.println(rs);
            System.out.println(packet.getAddress().getHostAddress());
            System.out.println(packet.getPort());
            System.out.println("=======================");
        }

    }
}



TCP

package com.Game_All.TCP;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        //1、创建Socket对象,并同时请求与服务端程序的链接
        Socket socket = new Socket("127.0.0.1",8888);

        //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
        OutputStream os = socket.getOutputStream();

        //3、把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        //4、开始写数据出去了
        dos.writeUTF("在一起,好嘛");
        dos.close();

        socket.close();
    }
}

package com.Game_All.TCP;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        //1、创建Socket对象,并同时请求与服务端程序的链接
        Socket socket = new Socket("127.0.0.1",8888);

        //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
        OutputStream os = socket.getOutputStream();

        //3、把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        //4、开始写数据出去了
        dos.writeUTF("在一起,好嘛");
        dos.close();

        socket.close();
    }
}
package com.Game_All.TCP;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        //1、创建ServerSocket的对象,同时为服务端的注册端口
        ServerSocket serverSocket = new ServerSocket(8888);

        //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求
        Socket socket = serverSocket.accept();

        //3、从socke通信管道中的一个字节输入流
        InputStream is = socket.getInputStream();

        //4、把原始的字节输入流包装成数据输入流
        DataInputStream dis = new DataInputStream(is);

        //5、使用数据输入流读取客户端发送过来的消息
        String re = dis.readUTF();

        System.out.println(re);
        //获取客户端IP地址
        System.out.println(socket.getRemoteSocketAddress());
        dis.close();
        socket.close();
    }
}

多发多收

package com.Game_All.TCP;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        //1、创建ServerSocket的对象,同时为服务端的注册端口
        ServerSocket serverSocket = new ServerSocket(8888);

        //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求
        Socket socket = serverSocket.accept();

        //3、从socke通信管道中的一个字节输入流
        InputStream is = socket.getInputStream();

        //4、把原始的字节输入流包装成数据输入流
        DataInputStream dis = new DataInputStream(is);

        while (true){
            try {
                //5、使用数据输入流读取客户端发送过来的消息
                String re = dis.readUTF();

                System.out.println(re);
                //获取客户端IP地址
                System.out.println(socket.getRemoteSocketAddress());
                System.out.println("---------------------");
            } catch (IOException e) {
                System.out.println(socket.getRemoteSocketAddress()+"离线了");
                dis.close();
                socket.close();
                break;
            }
        }

    }
}



package com.Game_All.TCP;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        //1、创建Socket对象,并同时请求与服务端程序的链接
        Socket socket = new Socket("127.0.0.1",8888);

        //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
        OutputStream os = socket.getOutputStream();

        //3、把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        Scanner scanner = new Scanner(System.in);
        //4、开始写数据出去了
        while (true){
            System.out.println("请说:");
            String msg = scanner.nextLine();

            if ("exit".equals(msg)){
                dos.close();
                socket.close();
                break;
            }
            dos.writeUTF(msg);
            dos.flush();
        }


    }
}

不支持多个客户一个服务器

TCP通信-多线程

服务端

package com.Game_All.TCP;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        //1、创建ServerSocket的对象,同时为服务端的注册端口
        ServerSocket serverSocket = new ServerSocket(8888);


        while (true) {
            try {
                //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求
                Socket socket = serverSocket.accept();
                System.out.println("有人上线了"+socket.getRemoteSocketAddress());
                //3、把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
                new ServiceReaderThread(socket).start();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }

    }
}


package com.Game_All.TCP;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class ServiceReaderThread extends Thread{
    private Socket socket;
    public ServiceReaderThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        InputStream is = null;
        try {
            is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            while (true){
                try {
                    String msg = dis.readUTF();
                    System.out.println(msg);
                } catch (IOException e) {
                    System.out.println("有人下线了"+socket.getRemoteSocketAddress());
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

客户端两个:

package com.Game_All.TCP;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        //1、创建Socket对象,并同时请求与服务端程序的链接
        Socket socket = new Socket("127.0.0.1",8888);

        //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
        OutputStream os = socket.getOutputStream();

        //3、把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        Scanner scanner = new Scanner(System.in);
        //4、开始写数据出去了
        while (true){
            System.out.println("请说:");
            String msg = scanner.nextLine();

            if ("exit".equals(msg)){
                dos.close();
                socket.close();
                break;
            }
            dos.writeUTF(msg);
            dos.flush();
        }


    }
}


package com.Game_All.TCP;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client1 {
    public static void main(String[] args) throws IOException {
        //1、创建Socket对象,并同时请求与服务端程序的链接
        Socket socket = new Socket("127.0.0.1",8888);

        //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
        OutputStream os = socket.getOutputStream();

        //3、把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        Scanner scanner = new Scanner(System.in);
        //4、开始写数据出去了
        while (true){
            System.out.println("请说:");
            String msg = scanner.nextLine();

            if ("exit".equals(msg)){
                dos.close();
                socket.close();
                break;
            }
            dos.writeUTF(msg);
            dos.flush();
        }


    }
}

TCP-端口转发

客户端

package com.Game_All.TCP;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        //1、创建Socket对象,并同时请求与服务端程序的链接
        Socket socket = new Socket("127.0.0.1",8888);

        //创建一个独立的线程,随机负责从socket中获取服务端发送过拉力的信息
        new ClientReaderThread(socket).start();

        //2、从socket通信管道中得到一个字节输出流,用来发数据给服务端程序
        OutputStream os = socket.getOutputStream();

        //3、把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        Scanner scanner = new Scanner(System.in);
        //4、开始写数据出去了
        while (true){
            System.out.println("请说:");
            String msg = scanner.nextLine();

            if ("exit".equals(msg)){
                dos.close();
                socket.close();
                break;
            }
            dos.writeUTF(msg);
            dos.flush();
        }


    }
}
package com.Game_All.TCP;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class ClientReaderThread extends Thread{
    private Socket socket;

    public ClientReaderThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);


            while (true){
                try {
                    String msg = dis.readUTF();
                    System.out.println(msg);
                } catch (IOException e) {
                    System.out.println("有人下线了"+socket.getRemoteSocketAddress());
                    Server.onLineSocket.remove(socket);
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端

package com.Game_All.TCP;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server {


    public static List<Socket> onLineSocket = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        //1、创建ServerSocket的对象,同时为服务端的注册端口
        ServerSocket serverSocket = new ServerSocket(8888);


        while (true) {
            try {
                //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求
                Socket socket = serverSocket.accept();
                System.out.println("有人上线了"+socket.getRemoteSocketAddress());

                onLineSocket.add(socket);
                //3、把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
                new ServiceReaderThread(socket).start();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }

    }
}
package com.Game_All.TCP;

import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class ServiceReaderThread extends Thread{
    private Socket socket;

    public ServiceReaderThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        InputStream is = null;
        try {
            is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            while (true){
                try {
                    String msg = dis.readUTF();
                    System.out.println(msg);
                    //把这个信息分发给所有客户端接收
                    sendMsgToAll(msg);
                } catch (IOException e) {
                    System.out.println("有人下线了"+socket.getRemoteSocketAddress());
                    Server.onLineSocket.remove(socket);
                    dis.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    private void sendMsgToAll(String msg) throws IOException {
        //发送给全部在线的socket管道接收
        for (Socket onlineSocket : Server.onLineSocket) {
            OutputStream os = onlineSocket.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF(msg);
            dos.flush();

        }

    }
}

BS架构原理

package com.Game_All.TCP;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Server {




    public static void main(String[] args) throws IOException {
        //1、创建ServerSocket的对象,同时为服务端的注册端口
        ServerSocket serverSocket = new ServerSocket(8888);

        //创建一个县城其,负责处理铜鼓县你管道任务
        ThreadPoolExecutor pool = new ThreadPoolExecutor(16*2,16*2,0, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(8), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

        while (true) {

            //2、使用ServerSocket对象,调用一个accpte方法等待对象的客户链接请求
            Socket socket = serverSocket.accept();



            //3、把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
            pool.execute(new ServiceReaderRunnable(socket));


        }

    }
}
package com.Game_All.TCP;

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

public class ServiceReaderRunnable implements Runnable {
    private Socket socket;

    public ServiceReaderRunnable(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            OutputStream os = socket.getOutputStream();
            PrintWriter out = new PrintWriter(os, true);

            out.println("HTTP/1.1 200 OK");
            out.println("Content-Type: text/html; charset=UTF-8");
            out.println();
            out.println("<div style='color:red; font-size: 24px; text-align: center;'>Hello, World!</div>");

            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

  • 11
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1号全栈玩家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值