Java网络编程

一:什么是网络编程?

可以让设备中的程序与网络上其他设备中的程序进行数据交互(实现网络通信的)。

二:基本的通信架构

1.基本的通信架构有两种形式:CS架构(Client客户端/Server服务端)、BS架构(Browser浏览器/Server服务端)。

2.Client客户端:①需要程序员开发②用户需要安装。

3.Server服务端:需要程序员开发实现。

4.Browser浏览器:①不需要程序员开发实现。②用户需要安装浏览器。

三:网络通信的关键三要素

1.IP:设备在网络中的地址,是唯一的标识。

2.端口:应用程序在设备中唯一的标识。

3.协议:连接和数据在网络中传输的规则。

四:IP地址

1.IP:全称“互联网协议地址”,是分配给上网设备的唯一标志。

2.IP地址有两种形式:IPv4、IPv6

①IPv4:32位、点分十进制表示法 例如:192.168.1.66

②IPv6:128位、分八段表示,每段每四位编码成一个十六进制位表示,数之间用冒号(:)分开 例如:2001:0db8:0000:0023:0008:200c:417a

3.IP域名:如百度:http://www.baidu.com

4.公网IP,内网IP:

①公网IP:是可以连接互联网的IP地址。

②内网IP:也叫局域网IP,只能组织机构内部使用。

192.168. 开头的就是常见的局域网地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用。

5.特殊IP地址:

127.0.0.1、localhost:代表本机,只会寻找当前所在的主机

6.IP常用命令:

①ipconfig:查看本机IP地址

②ping IP地址:检查网络是否连通

7.InetAddress

①代表IP地址

②常见方法:

getLocalHost() 获取本机IP,会以一个InetAddress的对象返回

getByName(String host) 根据IP地址或者域名,返回一个InetAdress对象

getHostName() 获取该IP地址对象对应的主机名

getHostAddress() 获取该IP地址对象中的IP地址信息

isReachable(int timeout) 在指定毫秒内,判断主机与该IP对应的主机是否能连通

8.示例:

import java.net.InetAddress;

public class Test1 {
    public static void main(String[] args) throws Exception {
        InetAddress l1 = InetAddress.getLocalHost();

        InetAddress l2 = InetAddress.getByName("www.bilibili.com");

        System.out.println(l1.getHostName());
        System.out.println(l2.getHostName());

        System.out.println(l1.getHostAddress());
        System.out.println(l2.getHostAddress());

        System.out.println(l2.isReachable(8000));
    }
}

五:端口

1.标记正在计算机设备上运行的应用程序的,被规定为一个16位的二进制,范围是0~65535。

2.周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21)

3.注册端口:1024~49151,分配给用于进程或某些应用程序。

4.动态端口:49152到65535,之所以称为动态端口,是因为它一般不固定分配某种进程,而是动态分配。

注意:我们自己开发的程序一般选择使用注册端口,且同一个设备中不能出现两个程序的端口号一样,否则出错。

六:通信协议

1.网络上通信的设备,事先规定的连接规则,以及传输数据的规则被称为网络通信协议。

2.开放式网络互联标准:OSI网络参加模型

①OSI网络参考模型:全球网络互联标准。

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

3.传输层的两个通信协议

①UDP:用户数据报协议(通信效率高!语音通话 视频直播)

·特点:无连接、不可靠通信

·不事先建立连接,数据按照包发,一包数据包含:自己的IP、程序端口,目的地IP、程序端口和数据(限制在64KB内)等。

·发送方不管对方是否在线,数据在中间丢失也不管,如果接收方收到数据也不返回确认,故是不可靠的。

②TCP协议(通信效率不高!网页、文件下载、支付)

·特点:面向连接、可靠通信。

·TCP的最终目的:要保证在不可靠的信道上实现可靠的传输。

·TCP主要有三个步骤实现可靠传输:三次握手建立连接,传输数据进行确认,四次挥手断开连接。

TCP协议:三次握手建立可靠连接(确定通信双方,收发消息都是正常无问题的!(全双工))

四次挥手断开连接——目的:确保双方数据的收发都已经完成!

七:UDP通信

1.特点:无连接、不可靠通信。

2.不事先建立连接;发送端每次把要发生的数据(限制在64KB内)、接收端IP、等信息封装成一个数据包,发出去就不管了。

3.Java提供了一个java.netDatagramSocket类来实现UDP通信。

4.

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

构造器:

DatagramSocket() 创建客户端的Socket对象,系统会随机分配一个端口号

DatagramSocket(int port) 创建服务端的Socket对象,并指定端口号

方法:

send(DatagramSocket dp) 发送数据包

receive(DatagramSocket p) 使用数据包接受数据

DatagramSocket:创建数据包

构造器:

DatagramPacket(byte[] buf , int length , InetAddress address , int port) 创建发出去的数据包对象

DatagramPacket(byte[] buf , int length) 创建用来接受数据的数据包

方法:

getlength() 获取数据包,实际接收到的字节个数

5.示例:

①一发一收

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("----服务端启动----");

        DatagramSocket ds = new DatagramSocket(6666);

        byte[] bytes = new byte[1024*64];
        DatagramPacket Package = new DatagramPacket(bytes,bytes.length);

        ds.receive(Package);

        int len = Package.getLength();

        String rs = new String(bytes,0,len);
        System.out.println(rs);

        ds.close();
    }
}
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Client {
    public static void main(String[] args) throws Exception {
        DatagramSocket ds = new DatagramSocket();

        byte[] bytes = "小小蔡建宇".getBytes();
        DatagramPacket Package = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),6666);

        ds.send(Package);

        System.out.println("客户端数据发送成功!");

        ds.close();
    }
}

②多发多收


import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("----服务端启动----");

        DatagramSocket ds = new DatagramSocket(6666);

        while (true) {
            byte[] bytes = new byte[1024*64];
            DatagramPacket Package = new DatagramPacket(bytes,bytes.length);

            ds.receive(Package);

            int len = Package.getLength();

            String rs = new String(bytes,0,len);
            System.out.println(rs);

            System.out.println(Package.getAddress().getHostAddress());
            System.out.println(Package.getPort());
            System.out.println("-----------------------------");
        }
    }
}
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {
        DatagramSocket ds = new DatagramSocket();

        Scanner sc = new Scanner(System.in);

        while (true) {
            System.out.println("请说:");
            String msg = sc.nextLine();
            if (msg.equals("exit")){
                System.out.println("欢迎下次光临!");
                ds.close();
                break;
            }
            byte[] bytes = msg.getBytes();
            DatagramPacket Package = new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),6666);

            ds.send(Package);
        }
        System.out.println("客户端数据发送成功!");
    }
}

注意:要让Client类能多启动!

八:TCP通信

1.特点:面向连接、可靠通信。

2.通信双方事先会采用“三次握手”方式建立可靠连接,实现端到端的通信;底层能保证数据成功传给服务端。

3.Java提供了一个java.net.Socket类来实现TCP通信。

4.客户端开发

客户端程序就是通过java.net包下的Socket类来实现的。

构造器:

Socket(String host , int port) 根据指定的服务器IP、端口号与服务端建立连接,连接通过,就获得可客户端Socket

方法:

getOutputStream() 获得字节输出流对象

getInputStream() 获得字节输入流对象

5.服务端程序的开发

服务端是通过java.net包下的ServerSocket类实现的。

构造器:

ServerSocket(int port) 为服务端注册端口

方法:

accept() 阻塞等待客户端的连接请求,一旦与某个客户端成功连接,则返回服务端这边的Socket对象

getRemoteSocketAddress() 获取客户端的IP地址

6.示例:

①单发单收:

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

public class Server2 {
    public static void main(String[] args) throws Exception {
        ServerSocket socket = new ServerSocket(8888);

        //等待客户端的连接请求
        Socket accept = socket.accept();

        InputStream is = accept.getInputStream();

        DataInputStream dis = new DataInputStream(is);

        String rs = dis.readUTF();
        System.out.println(rs);
        //获取客户端的IP地址
        System.out.println(accept.getRemoteSocketAddress());

        dis.close();
        socket.close();
    }
}
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client2 {
    public static void main(String[] args) throws Exception {
        System.out.println("--------服务端启动-------");
        Socket socket = new Socket("127.0.0.1",8888);

        OutputStream os = socket.getOutputStream();

        DataOutputStream dos = new DataOutputStream(os);

        dos.writeUTF("哈哈哈哈哈");

        dos.close();
        socket.close();
    }
}

②多发多收:

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

public class Server2 {
    public static void main(String[] args) throws Exception {
        System.out.println("--------服务端启动-------");
        ServerSocket socket = new ServerSocket(8888);

        //等待客户端的连接请求
        Socket accept = socket.accept();

        InputStream is = accept.getInputStream();

        DataInputStream dis = new DataInputStream(is);

        while (true) {
            try {
                String rs = dis.readUTF();
                System.out.println(rs);
            } catch (Exception e) {
                //获取客户端的IP地址
                System.out.println(accept.getRemoteSocketAddress()+"离线了");
                dis.close();
                accept.close();
                break;
            }
        }
    }
}
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client2 {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1",8888);

        OutputStream os = socket.getOutputStream();

        DataOutputStream dos = new DataOutputStream(os);

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请说:");
            String msg = sc.nextLine();
            if (msg.equals("exit")){
                dos.close();
                socket.close();
                break;
            }else {
                dos.writeUTF(msg);
            }
        }
    }
}

③支持与多个客户端同时通信

import java.net.ServerSocket;
import java.net.Socket;

public class Server2 {
    public static void main(String[] args) throws Exception {
        System.out.println("--------服务端启动-------");
        ServerSocket socket = new ServerSocket(8888);



        while (true) {
            //等待客户端的连接请求
            Socket accept = socket.accept();

            System.out.println(accept.getRemoteSocketAddress()+"上线了");

            new MyServerThread(accept).start();
        }

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

public class MyServerThread extends Thread{
    private Socket socket;
    public MyServerThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);

            while (true) {
                try {
                    String rs = dis.readUTF();
                    System.out.println(rs);
                } catch (Exception e) {
                    System.out.println(socket.getRemoteSocketAddress()+"下线了");
                    dis.close();
                    socket.close();
                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client2 {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1",8888);

        OutputStream os = socket.getOutputStream();

        DataOutputStream dos = new DataOutputStream(os);

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请说:");
            String msg = sc.nextLine();
            if (msg.equals("exit")){
                dos.close();
                socket.close();
                break;
            }else {
                dos.writeUTF(msg);
            }
        }
    }
}

④群聊案例

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server2 {
    public static List<Socket> onlineSocket = new ArrayList<>();
    public static void main(String[] args) throws Exception {
        System.out.println("--------服务端启动-------");
        ServerSocket socket = new ServerSocket(8888);



        while (true) {
            //等待客户端的连接请求
            Socket accept = socket.accept();
            onlineSocket.add(accept);
            System.out.println(accept.getRemoteSocketAddress()+"上线了");

            new MyServerThread(accept).start();
        }

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

public class MyServerThread extends Thread{
    private Socket socket;
    public MyServerThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);

            while (true) {
                try {
                    String rs = dis.readUTF();
                    System.out.println(rs);
                    sendMsgToAll(rs);
                } catch (Exception e) {
                    System.out.println(socket.getRemoteSocketAddress()+"下线了");
                    Server2.onlineSocket.remove(socket);
                    dis.close();
                    socket.close();
                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sendMsgToAll(String rs) throws IOException {
        for (Socket socket : Server2.onlineSocket) {
            OutputStream os = socket.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF(rs);
            dos.flush();
        }
    }
}
import java.io.DataInputStream;
import java.io.InputStream;
import java.net.Socket;

public class MyClientThread extends Thread{
    private Socket socket;
    public MyClientThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);

            while (true) {
                try {
                    String rs = dis.readUTF();
                    System.out.println(rs);

                } catch (Exception e) {
                    System.out.println(socket.getRemoteSocketAddress()+"下线了");
                    dis.close();
                    socket.close();
                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client2 {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1",8888);

        new MyClientThread(socket).start();

        OutputStream os = socket.getOutputStream();

        DataOutputStream dos = new DataOutputStream(os);

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请说:");
            String msg = sc.nextLine();
            if (msg.equals("exit")){
                dos.close();
                socket.close();
                break;
            }else {
                dos.writeUTF(msg);
            }
        }
    }
}

⑤实现BS架构

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

public class MyServerRunnable implements Runnable{
    private Socket socket;
    public MyServerRunnable(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {

        try {
            OutputStream is = socket.getOutputStream();
            PrintStream ps = new PrintStream(is);
            ps.println("HTTP/1.1 200 OK");
            ps.println("Content-Type:text/html;charset=UTF-8");
            ps.println();
            ps.println("<div style='color:red;font-size:120px;text-align:center'>蔡建宇666<div>");
            ps.close();
            socket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class Server2 {
    public static List<Socket> onlineSocket = new ArrayList<>();
    public static void main(String[] args) throws Exception {
        System.out.println("--------服务端启动-------");
        ServerSocket socket = new ServerSocket(8888);

        ThreadPoolExecutor pool = new ThreadPoolExecutor(16 * 2, 16 * 2, 0, TimeUnit.SECONDS,
                                                         new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

        while (true) {
            //等待客户端的连接请求
            Socket accept = socket.accept();
            onlineSocket.add(accept);
            System.out.println(accept.getRemoteSocketAddress()+"上线了");

            pool.execute(new MyServerRunnable(accept));
        }

    }
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值