重温Java网络编程(实现简易TCP,UDP应用)

关于TCP以及UDP的相关知识,在此就不做相关总结,如有需要可以参考https://blog.csdn.net/li_ning_/article/details/52117463



一、使用TCP实现一个简易登录功能

1.创建一个实体类 User.java

package com.tcp.multithreadingTcp;

import java.io.Serializable;

public class User implements Serializable {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

2.服务器端代码 LoginServer.java

package com.tcp.multithreadingTcp;

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

public class LoginServer {
    public static void main(String[] args) throws IOException {
        //创建一个ServerSocket,指定监听的端口
        ServerSocket serverSocket = new ServerSocket(8888);

        int i = 0;
        while (true) {
            //使用ServerSocket监听用户请求
            Socket socket = serverSocket.accept();//如果没有请求则阻塞
            //启动一个登录线程
            new Thread(new LoginThread(socket)).start();

            System.out.println("你是访问该服务器的第" + ++i + "个用户,你的ip地址为"
                    + socket.getInetAddress().getHostAddress());
            socket.close();
        }
    }
}

3.登录线程代码 LoginThread.java

package com.tcp.multithreadingTcp;

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

public class LoginThread implements Runnable {
    private Socket socket;

    LoginThread(Socket socket) {
        this.socket = socket;
    }

    //处理用户请求
    @Override
    public void run() {
        //接收来自客户端的数据并输出
        try {
            ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
            User user = (User) objectInputStream.readObject();
            System.out.println(user.toString());

            //发送反馈
            DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
            if ("zhangsan".equals(user.getUsername()) && "1234".equals(user.getPassword())) {
                dataOutputStream.writeUTF("登录成功");
            } else {
                dataOutputStream.writeUTF("登录失败");
            }

            //关闭资源
            dataOutputStream.close();
            objectInputStream.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

4.客户端代码 LoginClient.java

package com.tcp.multithreadingTcp;

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

public class LoginClient {
    public static void main(String[] args) throws IOException {
        //创建一个Socket,指定服务器端的ip与端口
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);

        Scanner sc = new Scanner(System.in);
        System.out.print("请输入用户名:");
        String username = sc.nextLine();
        System.out.print("请输入密码:");
        String password = sc.nextLine();
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        //发送登录信息
        OutputStream outputStream = socket.getOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(user);

        //接收数据
        InputStream inputStream = socket.getInputStream();
        DataInputStream dataInputStream = new DataInputStream(inputStream);
        String res = dataInputStream.readUTF();
        System.out.println(res);

        //关闭资源
        dataInputStream.close();
        inputStream.close();
        objectOutputStream.close();
        outputStream.close();
        socket.close();
    }
}

运行结果:(客户端)

请输入用户名:zhangsan
请输入密码:1234
登录成功

运行结果:(服务端)

User{username='zhangsan', password='1234'}
你是访问该服务器的第1个用户,你的ip地址为xxx.xxx.xxx.xxx


二、使用UDP实现一个简易聊天室功能

UDP相较于TCP实现简单一些,所以代码量也稍微的少一些

1.服务端代码

package com.udp.moreThanOneUdp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

/**
 * 功能:在线客服.
 * 技能:使用UDP网络编程完成
 * 注意
 * 1. UDP编程中客户端和服务器端区分不明显,双方代码差别不大
 * 2.主动发起请求的一段是客户端,接收请求的是服务器端;一旦通信开始,客户端和服务器端无差别
 * 3.不涉及IO流
 * 4.主要API
 * - DatagramSocket:socket,作用是发送和接收DatagramPacket
 * - DatagramPacket:数据报(封装数据,目的地址,源地址,端口号)
 */
public class AskServer {
    public static void main(String[] args) throws IOException {
        //创建一个DatagramSocket,用来发送和接收数据
        DatagramSocket socket = new DatagramSocket(8888);//服务器端接收数据的端口
        Scanner sc = new Scanner(System.in);
        while (true) {
            //使用DatagramSocket接收一个DatagramPacket
            byte[] buf = new byte[1024];
            DatagramPacket datagramPacket1 = new DatagramPacket(buf, buf.length);
            socket.receive(datagramPacket1);
            System.out.println("对方说:" + new String(datagramPacket1.getData(), 0, datagramPacket1.getLength()));

            //使用DatagramSocket发送一个DatagramPacket
            System.out.print("请您输入:");
            String info = sc.nextLine();
            InetAddress inetAddress = datagramPacket1.getAddress();
            int port = datagramPacket1.getPort();
            DatagramPacket datagramPacket2 = new DatagramPacket(info.getBytes(), info.getBytes().length, inetAddress, port);
            socket.send(datagramPacket2);
            if (info.equals("bye")) {
                break;
            }
        }
        System.out.println("聊天结束");

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

2.客户端代码

package com.udp.moreThanOneUdp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class AskClient {
    public static void main(String[] args) throws IOException {
        //创建一个DatagramSocket,用来发送和接收数据
        DatagramSocket socket = new DatagramSocket(8889);//客户端接收数据的端口,可以省略,会自动分配
        Scanner sc = new Scanner(System.in);
        while (true) {
            //使用DatagramSocket发送一个DatagramPacket
            System.out.print("请您输入:");
            String info = sc.nextLine();
            InetAddress inetAddress = InetAddress.getLocalHost();
            DatagramPacket datagramPacket1 = new DatagramPacket(info.getBytes(), info.getBytes().length, inetAddress, 8888);
            socket.send(datagramPacket1);
            if (info.equals("bye")) {
                break;
            }

            //使用DatagramSocket接收一个DatagramPacket
            byte[] buf = new byte[1000];
            DatagramPacket datagramPacket2 = new DatagramPacket(buf, buf.length);
            socket.receive(datagramPacket2);
            System.out.println("对方说:" + new String(buf, 0, datagramPacket2.getLength()));
        }
        System.out.println("聊天结束");

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

运行结果:(客户端)

请您输入:你好呀
对方说:你是谁
请您输入:我是张三,你呢
对方说:我是李四
请您输入:好的,我要忙了
对方说:bye
请您输入:bye
聊天结束

运行结果:(服务端)

对方说:你好呀
请您输入:你是谁
对方说:我是张三,你呢
请您输入:我是李四
对方说:好的,我要忙了
请您输入:bye
聊天结束


三、使用TCP实现文件上传以及文件下载功能

  • 文件上传的本质:文件从客户端到服务器端的复制
  • 文件下载的本质:文件从服务器端到客户端的复制
  • 文件的上传和下载都是两次文件复制

1.文件上传功能服务端代码

package com.tcp.uploadTcp;

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

public class UploadServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);
        Socket socket = serverSocket.accept();

        //创建一个输入流和一个输出流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File("/test1.txt")));

        //使用输入流和输出流完成文件复制
        //中转站
        int n;

        //读取末尾的一个字节的内容赋给n
        n = bufferedInputStream.read();
        while (n != -1){
            //写一个字节
            bufferedOutputStream.write(n);
            System.out.println(1);
            //读一个字节
            n = bufferedInputStream.read();
        }

        //关闭资源
        bufferedInputStream.close();
        bufferedOutputStream.close();
        socket.close();
        serverSocket.close();
    }
}

2.文件上传功能客户端代码

package com.tcp.uploadTcp;

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

public class UploadClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(),8888);

        //创建一个输入流和一个输出流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(new File("/test.txt")));
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());

        //关闭资源
        bufferedInputStream.close();
        bufferedOutputStream.close();
        socket.close();
    }
}

1.文件下载功能服务端代码

package com.tcp.downloadTcp;

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

public class DownloadServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);
        Socket socket = serverSocket.accept();

        //创建一个输入流和一个输出流
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File("/test.txt")));
        BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());

        //使用输入流和输出流完成文件复制
        //中转站
        int n;

        //读取末尾的一个字节的内容赋给n
        n = bufferedInputStream.read();
        while (n != -1){
            //写一个字节
            bufferedOutputStream.write(n);

            //读一个字节
            n = bufferedInputStream.read();
        }

        //关闭资源
        bufferedInputStream.close();
        bufferedOutputStream.close();
        socket.close();
        serverSocket.close();
    }
}

2.文件下载功能客户端代码

package com.tcp.downloadTcp;

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

public class DownloadClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(),8888);

        //创建一个输入流和一个输出流
        BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File("/test1.txt")));

        //关闭资源
        bufferedInputStream.close();
        bufferedOutputStream.close();
        socket.close();
    }
}

其实上传功能和下载功能的逻辑是相同的,只不过一个是文件c => s,一个是文件s => c



参考视频:https://www.bilibili.com/video/av31123719/

你可能感兴趣的:(数据结构与算法,计算机网络)