JAVA题目笔记(二十五)网络编程综合小练qa!3EF TG6U8.L;

发布于:2024-12-18 ⋅ 阅读:(11) ⋅ 点赞:(0)

一、多发多收

客户端:

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

public class Test1_2 {
    public static void main(String[] args) throws IOException {
        //TCP发送端
        Scanner sc=new Scanner(System.in);
        String b;
        //创建Socket对象
        Socket socket=new Socket("127.0.0.1",1000);
        OutputStream ops = socket.getOutputStream();
        //多次发送数据
        while(true){
            //从连接通道中获取输出流
            System.out.print("输入信息:");
            b=sc.nextLine();
            ops.write((b+"\r\n").getBytes());
            ops.flush();
            if(b.equals("886"))
                break;
        }
        socket.close();

    }
}

服务器:

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

public class Test1 {
    public static void main(String[] args) throws IOException {
        //TCP接收端
        //创建ServerSocket对象
        ServerSocket ss=new ServerSocket(1000);
        //接收数据
        Socket socket = ss.accept();
        //获取通道中的输入流
        InputStreamReader isr=new InputStreamReader(socket.getInputStream());
        int b;
        //多发多收
        while ((b = isr.read()) != -1) {
            System.out.print((char)b);
        }
        socket.close();
        ss.close();
    }
}

 Tips:

BufferedWriter
OutputStreamWriter

这类因为自身带有缓冲区,因此只有当缓冲区填满时或者流关闭时才会向服务器传输数据。不适合多发多收。

二、接收和反馈

客户端:

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

public class Test2_2 {
    public static void main(String[] agrs) throws IOException {
        //TCP协议发送端

        //创建Socket对象
        //在创建对象的同时会连接服务器
        //如果连接不上,代码会报错
        Socket socket=new Socket("127.0.0.1",1000);

        //从连接通道种获取输出流
        OutputStream ops=socket.getOutputStream();

        Scanner sc=new Scanner(System.in);
        //写出数据
        String s=sc.nextLine();
        ops.write(s.getBytes());

        //关闭通道中输出流
        socket.shutdownOutput();

        //等待接收端反馈信息
        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String str = br.readLine();
        System.out.println(str);
        socket.close();
    }
}

服务器:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Test2 {
    public static void main(String[] args) throws IOException {
        //TCP协议接收端

        //创建ServerSocket对象
        ServerSocket ss=new ServerSocket(1000);

        //监听客户端的链接
        Socket socket=ss.accept();

        //从连接通道中获取输入流,读取数据(不能传中文)
        //使用转换流转化为字符流
        InputStreamReader isr=new InputStreamReader(socket.getInputStream());
        //为了读取效率,再套一个缓冲流
        BufferedReader br=new BufferedReader(isr);
        String s;
        while((s=br.readLine())!=null){
            System.out.println(s);
        }
        //关闭通道中的输入流
        socket.shutdownInput();

        //反馈
        //获取通道中的输出流
        socket.getOutputStream();
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write("已经接收到了信号");
        bw.close();
        socket.close();
    }
}

Tips: 

//读取结束标记
socket.shutdownInput();
//写入结束标记
socket.shutdownOutput();

通道中的输出流和输入流两边都可以调取并使用

三、上传文件

客户端:

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

public class Test3_2 {
    public static void main(String[] args) throws IOException {
        //发送端

        //创建Socket对象
        Socket socket=new Socket("127.0.0.1",1000);
        OutputStream ops=socket.getOutputStream();
        //根据通道输出流转换成字符流再转换成字符缓冲流
        BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
        //读取本地文件
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream("src\\MIUI10.jpg"));
        int len;
        byte[] bytes=new byte[1024];
        while((len=bis.read(bytes))!=-1){
            bos.write(bytes,0,len);
            bos.flush(); //刷新缓冲区
        }
        //本地文件读取结束
        bis.close();
        //输出流结束标记
        socket.shutdownOutput();
        
        //接收反馈信号
        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String b;
        while((b=br.readLine())!=null){
            System.out.println(b);
        }
        br.close();
        socket.close();
    }
}

服务器:

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

public class Test3 {
    public static void main(String[] args) throws IOException {
        //接收端

        //创建服务器对象
        ServerSocket ss=new ServerSocket(1000);
        //通道对象
        Socket socket = ss.accept();
        //获取通道的输入流
        BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
        //写入本地文件
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("COPY.jpg"));
        int len;
        byte[] bytes=new byte[1024];
        while((len=bis.read(bytes))!=-1){
            //拷贝
            bos.write(bytes,0,len);
            bos.flush();//刷新缓冲区
        }
        bos.close();
        //读取结束标志
        socket.shutdownInput();

        //发送反馈
        //获取通道中的输出流
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write("文件接收完毕");
        bw.close();//刷新缓冲区
        //释放资源
        socket.close();
    }
}

四、解决三中重名问题

只需要修改服务器

服务器:

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

public class Test3 {
    public static void main(String[] args) throws IOException {
        //接收端

        //创建服务器对象
        ServerSocket ss=new ServerSocket(1000);
        //通道对象
        Socket socket = ss.accept();
        //获取通道的输入流
        BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
        //写入本地文件
        String name=UUID.randomUUID().toString().replace("-","");
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(name+".jpg"));
        int len;
        byte[] bytes=new byte[1024];
        while((len=bis.read(bytes))!=-1){
            //拷贝
            bos.write(bytes,0,len);
            bos.flush();//刷新缓冲区
        }
        bos.close();
        //读取结束标志
        socket.shutdownInput();

        //发送反馈
        //获取通道中的输出流
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write("文件接收完毕");
        bw.close();//刷新缓冲区
        //释放资源
        socket.close();
    }
}

Tips:

String name=UUID.randomUUID().toString().replace("-","");
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(name+".jpg"));

UUID类中的randomUUID方法:生成随机且唯一的序列号

五、上传文件(多线程版)

 服务器:

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

public class Test5 {
    public static void main(String[] args) throws IOException {
        //接收端

        //创建服务器对象
        ServerSocket ss=new ServerSocket(1000);
        while(true){
            //阻塞状态:等待客户端连接
            Socket socket = ss.accept();

            new MyThread(socket).start();
        }
    }
}

线程对象:

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

public class MyThread extends Thread{

    private Socket socket;

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

    @Override
    public void run() {
        //通道对象

        try {
            //获取通道的输入流
            BufferedInputStream bis = new BufferedInputStream(this.socket.getInputStream());
            //写入本地文件
            String name = UUID.randomUUID().toString().replace("-", "");
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(name + ".jpg"));
            int len;
            byte[] bytes = new byte[1024];
            while ((len = bis.read(bytes)) != -1) {
                //拷贝
                bos.write(bytes, 0, len);
                bos.flush();//刷新缓冲区
            }
            bos.close();
            //读取结束标志
            this.socket.shutdownInput();

            //发送反馈
            //获取通道中的输出流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(this.socket.getOutputStream()));
            bw.write("文件接收完毕");
            bw.close();//刷新缓冲区
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //释放资源
            if(socket!=null){
                //避免空指针异常
                //若socket为null 对其调用close方法,则会导致空指针异常
                try {
                    this.socket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }

    }
}

六、上传文件(线程池版)

 服务器:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Test6 {
    public static void main(String[] args) throws IOException {
        //接收端
        //创建线程池对象
        ThreadPoolExecutor pool=new ThreadPoolExecutor(
                3,//核心线程数量 不能小于0
                16,//最大线程数 不能小于0,最大数量必须要大于等于核心数量
                60,//空闲线程的最大存活时间
                TimeUnit.SECONDS,//时间单位
                new ArrayBlockingQueue<>(3),//任务队列
                Executors.defaultThreadFactory(),//创建线程工厂
                new ThreadPoolExecutor.AbortPolicy()  //创建任务的拒绝策略(新建一个类的内部类)
        );
        //创建服务器对象
        ServerSocket ss=new ServerSocket(1000);
        while(true){
            //阻塞状态:等待客户端连接
            Socket socket = ss.accept();

            //添加入线程池
            pool.submit(new MyThread(socket));
        }
    }
}

七、多人聊天室

 客户端:

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

public class TalkRoom_client {
    public static void main(String[] args) throws IOException {
        //客户端
        //创建Socket对象
        Socket socket=new Socket("127.0.0.1",1000);

        while(true){
            show();
            Scanner sc = new Scanner(System.in);
            String choose = sc.nextLine();
            if (choose.equals("1")) {
                //登录选择
                Login(socket);
            } else if (choose.equals("2")) {
                //注册
                Register(socket);
            } else {
                //选择不对
                System.out.println("无效选择,请输入 1 或 2  ");
            }
        }

    }

    private static void Register(Socket socket) throws IOException {
        Scanner sc=new Scanner(System.in);
        //向服务器传输注册标志
        SendMessageToClient(socket,"register");
        while(true){
            //开始注册流程
            showRegister();
            System.out.print("请输入账号:");
            String account=sc.nextLine();
            System.out.println("请输入密码:");
            String password=sc.nextLine();
            int result=check(account,password);
            //1 正确   2 账号错误  3 密码错误
            if(result==1){
                //正确,进行传输
                String str=account+"="+password;
                SendMessageToClient(socket,str);
                System.out.println("注册成功");
                break;
            }else if(result==2){
                //账号违法
                System.out.println("账号违法,请重新注册");
            }else{
                //密码违法
                System.out.println("密码违法,请重新注册");
            }
        }
    }

    public static void TalkToAll(Socket socket) throws IOException {
        Scanner sc=new Scanner(System.in);
        System.out.println("开始聊天");
        while(true){
            System.out.println("请输入要说的话:");
            String str=sc.nextLine();
            SendMessageToClient(socket,str);
        }
    }
    public static int check(String account,String password){

        if(account.matches("[a-zA-Z]{6,12}")){
            if(password.matches("[a-zA-Z]\\d{2,7}")){
                //全对
                return 1;
            }else{
                //密码不对
                return 3;
            }
        }else return 2; //账号不对
    }
    public static void Login(Socket socket) throws IOException {
        Scanner sc=new Scanner(System.in);
        //字符缓冲流:用于传输账号密码信息
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //向服务器传输登录标志
        bw.write("login");
        bw.newLine();
        bw.flush();
        System.out.println("请输入您的账号:");
        String account = sc.nextLine();
        bw.write(account);
        bw.write("&");
        System.out.println("请输入您的密码:");
        String password = sc.nextLine();
        bw.write(password);
        bw.newLine();
        bw.flush();
        //接收反馈
        String s = br.readLine();
        System.out.println("结果为:"+s);
        //1 登录成功  2 密码错误 3 账号不存在
        if("1".equals(s)){
            System.out.println("登录成功");
            new ReceiveMessage(socket).start();
            //开始聊天
            TalkToAll(socket);
        }else if("2".equals(s)){
            System.out.println("密码错误");
        }else {
            System.out.println("账号不存在");
        }
    }

    public static void SendMessageToClient(Socket socket,String str) throws IOException {
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(str);
        bw.newLine();
        bw.flush();
    }
    public static void show(){
        System.out.println("=======聊天室========");
        System.out.println("1、登录");
        System.out.println("2、注册");
        System.out.println("请输入您的选择:");
    }
    public static void showRegister(){
        System.out.println("开始注册");
        System.out.println("账号要求:6~12位,纯字母");
        System.out.println("密码要求:3~8位,第一位必须为字母,其余纯数字");
    }
}

 服务器:

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

public class TalkRoom_server {
    public static void main(String[] args) throws IOException {
        //创建服务器
        ServerSocket ss=new ServerSocket(1000);
        //创建一个存放socket的集合来进行统一操作
        ArrayList<Socket> socketlist=new ArrayList<>();
        while(true){
            //等待客户端连接
            Socket socket = ss.accept();
            socketlist.add(socket);
            new ClientThread(socket,socketlist).start();
        }
    }
}

 客户端线程:

import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class ClientThread extends Thread{
    static File file=new File("tst.txt"); //存放账号信息的本地文件
    private Socket socket;
    private ArrayList<Socket> socketlist;
    private Map<String,String> map=new HashMap<>();
    public ClientThread(Socket socket,ArrayList<Socket> socketlist){
        this.socket=socket;
        this.socketlist=socketlist;
    }

    public void updateMap() throws IOException {
        //读取本地文件中的账号信息存入集合中
        BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(new FileInputStream("tst.txt")));
        String b;
        while((b=bufferedReader.readLine())!=null){
            String[] strings = b.split("=");
            map.put(strings[0],strings[1]);
        }
    }

    @Override
    public void run() {
        while(true){
            try {
                //接收用户传过来的信息
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                //第一次传输的是选择
                String choose = br.readLine();
                switch (choose) {
                    case "login":
                        System.out.println("用户选择登录");
                        //登录操作
                        //先更新本地文件map
                        updateMap();
                        login(br, socket, map);
                        break;
                    case "register":
                        //注册操作
                        System.out.println("用户选择注册");
                        register(br,socket,file);
                        break;
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void register(BufferedReader br,Socket socket,File file) throws IOException {
        //接收传过来的注册信息
        String b=br.readLine();
        //写入本地文件
        BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file,true)));
        bufferedWriter.write(b);
        bufferedWriter.newLine();
        bufferedWriter.close();
        //更新本地文件
        updateMap();
    }
    public void login(BufferedReader br,Socket socket,Map<String,String> map) throws IOException {
        ArrayList<String> list=new ArrayList<>();
        //获取传输过来的账号密码信息
        String info=br.readLine();  //account&password
        String[] split = info.split("&");
        System.out.println("用户输入账号为:"+split[0]);
        System.out.println("用户输入密码为:"+split[1]);
        list.add(split[0]);
        list.add(split[1]);

        if(map.get(list.get(0))!=null){
            //账号存在
            if(map.get(list.get(0)).equals(list.get(1))){
                //密码正确
                System.out.println("用户"+list.get(0)+"登录成功");
                SendMessageToClient("1");
                //开始聊天
                //接收
                ReceiveMessageFromClient(list.get(0),socketlist);

            }else {
                //密码错误
                System.out.println("密码错误");
                SendMessageToClient("2");
            }
        }else{
            //根本不存在账号
            System.out.println("账号不存在");
            SendMessageToClient("3");
        }
    }

    public void SendMessageToClient(String str,ArrayList<Socket> socketlist) throws IOException {
        for (Socket s : socketlist) {
            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            bw.write(str);
            bw.newLine();
            bw.flush();
        }
    }
    public void SendMessageToClient(String str) throws IOException {
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(str);
        bw.newLine();
        bw.flush();
    }
    public void ReceiveMessageFromClient(String name,ArrayList<Socket> socketlist) throws IOException {
        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String b;
        while((b=br.readLine())!=null){
            System.out.println("用户"+name+"发送了信息:"+b);
            //广播给所有用户
            SendMessageToClient("用户"+name+"发送了信息:"+b,socketlist);
        }
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到