网络编程相关基础

2018-10-09  本文已影响26人  吾乃韩小呆

一、理论基础

1、网络参考模型

OSI 参考模型:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
TCP/IP 参考模型:应用层、传输层、网络层、物理层

2、网络编程三要素

IP 地址、 端口、协议(规则)

IP地址:网络中、计算机唯一标识;
IP地址组成:网络号段+主机号段 第一部分为网络号段、第二部分为主机号段;
IP地址分类:5 类 ;

IP地址与主机名称相互获取 :

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Objects;

//根据计算机名称获取计算机ip地址
//根据计算机ip地址获取计算机名称
public class Main {

    public static void main(String[] args) {
        InetAddress inetAddress = null;
        try {
            //传名称----》ip地址
            //传ip地址----》名称
            inetAddress = InetAddress.getByName("DESKTOP-UQ42018");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        //ip地址
        String ipAddress = Objects.requireNonNull(inetAddress).getHostAddress();
        //主机名称
        String ipName = inetAddress.getHostName();
        System.out.println(ipName + "----------" + ipAddress);

    }
}

3、协议

UDP 协议:将数据打包、数据有限制为64k、不建立链接、速度快、不可靠

TCP 协议:建立连接、数据无限制、速度慢、可靠

4、Scoket 套接字编程 网络编程

1)、原理机制
通信两端都有 Scoket ;
网络通信其实就是 Scoket 间通信;
数据在两个 Scoket 键通过 IO 传输;

简易版 socket udp 通信:

发送端代码:

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

public class SendMessage {

    public static void main(String[] args) {

        //发送数据
        sendMessage();
    }

    //socket  udp  通信发送端
    private static void sendMessage() {
        //1、创建发送端 Socket 对象
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket();
        } catch (SocketException e) {
            e.printStackTrace();
        }

        //创建数据
        byte[] bytes = "hello udp".getBytes();
        //长度
        int length = bytes.length;
        //ip 地址对象
        InetAddress address = null;
        try {
            address = InetAddress.getByName("DESKTOP-UQ42018");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        //端口号
        int port = 100;
        //2、创建数据,并且进行打包
        DatagramPacket packet = new DatagramPacket(bytes, length, address, port);
        //3、发送数据
        try {
            Objects.requireNonNull(ds).send(packet);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //4、释放资源
        Objects.requireNonNull(ds).close();
    }
}

接收端代码:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Objects;

public class ReceiveMessage {

    public static void main(String[] args) {
        //接收数据
        receiveMessage();
    }

    //接收 udp 接收端
    private static void receiveMessage() {

        //1、创建接收端 socket 对象
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket(100);
        } catch (SocketException e) {
            e.printStackTrace();
        }
        //2、创建数据包接收器
        byte[] bytes = new byte[1024];
        int length = bytes.length;

        DatagramPacket packet = new DatagramPacket(bytes, length);

        //3、接收数据包
        try {
            Objects.requireNonNull(ds).receive(packet);// 阻塞方法
        } catch (IOException e) {
            e.printStackTrace();
        }

        //获取发送端的ip
        InetAddress address = packet.getAddress();
        String ip = address.getHostAddress();


        //4、解析数据
        // public byte[] getData();  获取数据缓冲区
        //public int getLength(); 获取数据实际长度
        byte[] bytes2 = packet.getData();
        int len = packet.getLength();
        String str = new String(bytes2, 0, len);

        System.out.println(ip + " : " + str);

        //5、释放资源
        Objects.requireNonNull(ds).close();
    }
}
实现循环聊天系统:

发送端:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.Objects;

public class SendMessage {

    public static void main(String[] args) {
        try {
            sendMessage();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //循环发送 聊天数据
    private static void sendMessage() throws IOException {
        //1、创建发送端 Socket 对象
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket();
        } catch (SocketException e) {
            e.printStackTrace();
        }
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        while ((line = br.readLine()) != null) {
            //输入再见,跳出循环
            if ("再见".endsWith(line)) {
                break;
            }
            
            byte[] bytes = line.getBytes();
            int length = bytes.length;
            InetAddress address = InetAddress.getByName("DESKTOP-UQ42018");
            int port = 100;
            //2、创建数据,并且进行打包
            DatagramPacket packet = new DatagramPacket(bytes, length, address, port);
            //3、发送数据
            Objects.requireNonNull(ds).send(packet);
        }
        //4、释放资源
        Objects.requireNonNull(ds).close();
    }

}

接收端

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Objects;

public class ReceiveMessage {

    public static void main(String[] args) {
        try {
            receiveMessage();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //循环接收  聊天数据
    private static void receiveMessage() throws IOException {
        //1、创建接收端 socket 对象
        DatagramSocket ds = new DatagramSocket(100);
        while (true) {
            //2、创建数据包接收器
            byte[] bytes = new byte[1024];
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
            //3、接收数据包
            Objects.requireNonNull(ds).receive(packet);// 阻塞方法
            //4、解析数据
            String str = new String(packet.getData(), 0, packet.getLength());
            System.out.println(packet.getAddress().getHostAddress() + " : " + str);
        }
        //5、释放资源,循环聊天系统,接收方是不能关闭的。
        //        Objects.requireNonNull(ds).close();
    }
}
实现单窗口聊天室

启动程序

import java.net.DatagramSocket;
import java.net.SocketException;

//聊天室启动程序

public class CharRoom {
    public static void main(String[] args) {
        DatagramSocket socketSend = null;
        DatagramSocket socketReceive = null;
        try {
            socketSend = new DatagramSocket();
            socketReceive = new DatagramSocket(100);
        } catch (SocketException e) {
            e.printStackTrace();
        }
        SendRoom sendRoom = new SendRoom(socketSend);
        ReceiveRoom receiveRoom = new ReceiveRoom(socketReceive);

        Thread send = new Thread(sendRoom);
        Thread receive = new Thread(receiveRoom);

        send.start();
        receive.start();
    }
}

信息发送端程序

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Objects;

//信息发送端
public class SendRoom implements Runnable {

    private DatagramSocket socket;
    SendRoom(DatagramSocket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String line;
            while ((line = br.readLine()) != null) {
                //输入再见,跳出循环
                if ("再见".endsWith(line)) {
                    break;
                }
                byte[] bytes = line.getBytes();
                int length = bytes.length;
                InetAddress address = InetAddress.getByName("DESKTOP-UQ42018");
                int port = 100;
                //2、创建数据,并且进行打包
                DatagramPacket packet = new DatagramPacket(bytes, length, address, port);
                //3、发送数据
                Objects.requireNonNull(socket).send(packet);
            }
            //4、释放资源
            Objects.requireNonNull(socket).close();
        } catch (IOException e) {
            System.out.println("发送端出现异常");
        } finally {
            //4、释放资源
            Objects.requireNonNull(socket).close();
        }
    }
}

信息接收端程序

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Objects;

//信息接收端程序

public class ReceiveRoom implements Runnable {
    
    private DatagramSocket socket;
    ReceiveRoom(DatagramSocket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            while (true) {
                //2、创建数据包接收器
                byte[] bytes = new byte[1024];
                DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
                //3、接收数据包
                Objects.requireNonNull(socket).receive(packet);// 阻塞方法
                //4、解析数据
                String str = new String(packet.getData(), 0, packet.getLength());
                System.out.println(packet.getAddress().getHostAddress() + " : " + str);
            }
        } catch (IOException e) {
            System.out.println("接收端出现异常");
        } finally {
            socket.close();
        }
    }
}

5、TCP 相关

简单的通信例子,但是必须先运行服务端,再运行客户端,否则会产生错误。

简单版 cs 交互代码

服务端代码

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

public class TCPServer {

    public static void main(String[] args) throws IOException {

        //1、创建接收端 Socket 对象
        ServerSocket serverSocket = new ServerSocket(1000);

        //2、监听客户端连接,返回 Socket 对象
        Socket socket = serverSocket.accept();//阻塞式

        //3、获取输入流,
        InputStream is = socket.getInputStream();

        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
        String str = new String(bytes, 0, len);
        System.out.println("IP地址:" + socket.getInetAddress().getHostAddress() + " : " + str);

        //4、释放资源
        socket.close();
        //  serverSocket.close();关闭服务器
    }
}

客户端代码

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

//TCP 的客户端

public class TcpClient {

    public static void main(String[] args) throws IOException {
        //1、创建发送端 Scoket 对象   指定  IP地址和端口号
        Socket socket = new Socket("192.168.1.5", 1000);

        //2、创建输出流对象
        OutputStream os = socket.getOutputStream();
        os.write("你好呀,我是tcp客户端".getBytes());

        //3、关闭资源
        socket.close();
    }

}
可录入式 cs 结构

客户端代码:

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

//TCP 的客户端

public class TcpClient {

    public static void main(String[] args) throws IOException {
        //1、创建发送端 Scoket 对象   指定  IP地址和端口号
        Socket socket = new Socket("192.168.0.127", 1000);

        //输入数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //2、创建输出流对象----通道内流------进行封装
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        String line;
        while ((line = br.readLine()) != null) {

            //聊天终止条件
            if ("再见".equals(line)) {
                break;
            }

            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //3、关闭资源
        //        bw.close();  由于bw依附于 socket 对象存在,所有socket 关闭,就不需要关闭 bw。
        //        br.close();  由于跳出循环,不在进行键盘录入,所有 不需要进行关闭
        socket.close();
    }
}

服务端代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {

    public static void main(String[] args) throws IOException {

        //1、创建接收端 Socket 对象
        ServerSocket serverSocket = new ServerSocket(1000);

        //2、监听客户端连接,返回 Socket 对象-----服务器
        Socket socket = serverSocket.accept();//阻塞式
        //3、接收读取数据-----通道内的流-----进行包装
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }

        //        br.close();
        //        serverSocket.close();
        socket.close();
    }
}
将输入数据写入文件保存

客户端代码:

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

//TCP 的客户端

public class TcpClient {

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.0.127", 123);

        //封装录入数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //通道内的数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        String line;

        while ((line = br.readLine()) != null) {
            if ("再见".equals(line)) {
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        socket.close();
    }
}

服务端代码:

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

public class TCPServer {

    public static void main(String[] args) throws IOException {
        //创建服务器端 socket 对象
        ServerSocket serverSocket = new ServerSocket(123);
        Socket socket = serverSocket.accept();
        //读取通道内数据
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        br.close();
        socket.close();
    }
}
上传文本文件

客户端代码

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

//TCP 的客户端

public class TcpClient {

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.0.127", 123);
        //封装录入数据
        BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\Hxd\\Desktop\\AddDeviceActivity.java"));
        //通道内的数据
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        br.close();
        socket.close();
    }
}

服务端代码

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

public class TCPServer {

    public static void main(String[] args) throws IOException {
        //创建服务器端 socket 对象
        ServerSocket serverSocket = new ServerSocket(123);
        Socket socket = serverSocket.accept();
        //读取通道内数据
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
        String line;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        br.close();
        socket.close();
    }
}
多个客户端向服务端上传文件

客户端代码

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

//TCP 的客户端
public class TcpClient {

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.43.133", 123);
        //封装录入数据
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\Hxd\\Desktop\\1.jpg"));
        //将图片数据封装到通道
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
            bos.flush();
        }
        //通知服务器,不在上传数据
        socket.shutdownOutput();
        //读取服务器中的数据反馈
        InputStream is = socket.getInputStream();
        byte[] bytes1 = new byte[1024];
        int len1 = is.read(bytes1);
        System.out.println(new String(bytes1, 0, len1));
        bis.close();
        socket.close();
    }
}

服务端代码

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

//服务器接收端
public class TCPServer {

    public static void main(String[] args) throws IOException {
        //创建服务器端 socket 对象
        ServerSocket serverSocket = new ServerSocket(123);
        while (true) {
            Socket socket = serverSocket.accept();
            new Thread(new CsThread(socket)).start();
        }
    }
}

服务器端开启的线程

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

public class CsThread implements Runnable {

    private Socket socket;
    CsThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            //读取通道内数据
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            String name = System.currentTimeMillis() + ".jpg";
            //将读到的数据还原为图片
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(name));
            byte[] bytes = new byte[1024];
            int len;
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
                bos.flush();
            }
            //提供一个接收完成的反馈
            OutputStream os = socket.getOutputStream();
            os.write("图片上传成功".getBytes());
            bis.close();
            socket.close();
        } catch (IOException e) {
            System.out.println(e.toString());
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读