java实现简单的 cs架构

1.首先放上我项目目录(java原生  不需要第三方依赖)

1.首先代码我一一附上

(1)StartServer.java

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

public class StartServer {

//    服务端的启动类
    public static void main(String[] args) {
        // 服务端
        try{
            //创建服务器socket连接
            ServerSocket serverSocket=new ServerSocket(18889);

            //这里写成while循环  是为了  让一个客户端连接后  另一个客户端还可以连接
            int i=0;
            while(true){
                Socket socket=serverSocket.accept();
                new SocketServerThread(socket).start();
                i++;
                System.out.println("当前有"+i+"个客户端,与服务器建立了连接。");
            }

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

(2)StartClient.java

import java.net.Socket;

public class StartClient {

//    客户端的启动类
    public static void main(String[] args) {
//        这里 我启动了两个客户端  便于测试   一般写一个就可以了

        //客户端1
        try{
            //创建socket连接  服务器的地址是127.0.0.1:18889
            Socket socket=new Socket("127.0.0.1",18889);
            //启动客户端
            new SocketClient(socket).startSocketClient();

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

        //客户端2
        try{
            //创建socket连接  服务器的地址是127.0.0.1:18889
            Socket socket=new Socket("127.0.0.1",18889);
            //启动客户端
            new SocketClient(socket).startSocketClient();

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

}

(3)SocketUtils.java

public class SocketUtils {
//    cs架构的  工具类  后续可以根据自己的需求  写工具方法
    public static final String streamEncoding = "utf-8";
}

(4)SocketServerThread.java

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

//服务器线程类
public class SocketServerThread extends Thread{
    private Socket socket;
    public SocketServerThread(Socket socket){
        this.socket=socket;
    }

    public Socket getSocket() {
        return socket;
    }

    public void setSocket(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run(){
//        这里写成循环  是因为 如果不写循环 处理发生错误  本条线程就结束  也就和客户端失去了联系
//        写成循环  只要socket对象存在  InputStreamReader  OutputStreamWriter 就可以重新建立  继续发送接受消息
        while (true){
            try{
                //从socket获取 接收 和发送消息的流
                BufferedReader bfr = new BufferedReader(new InputStreamReader(socket.getInputStream(), SocketUtils.streamEncoding));
                BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), SocketUtils.streamEncoding));

                //从客户端接收消息   这里需要注意
//                这里的循环  只要没有出现Exception  用户和客户端的连接没有断开  下面这个循环 就不会终止
//                以前 我以为   服务端每接收一条消息然后回复出去  这个while就会终止   但实际不是这样的   这个InputStream 和 OutputStream 是一直保持连接的
//                是需要一直循环  从里面获取消息和发送消息的
                String line = "";
                while((line = bfr.readLine())!=null){
                    bfw.write("我已收到你的消息【"+line+"】");
                    bfw.newLine();
                    bfw.flush();

                    System.out.println("接收到了客户发来的消息:"+line);
                    System.out.println("同时向客户端回复了:我已收到你的消息【"+line+"】");
                }

            }catch(Exception e){
                System.out.println("连接断开!");
                if(socket!=null){
                    try{
                        if(!socket.isClosed()){
                            socket.close();
                        }
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                }
                break;
            }
        }
    }



}

  (5)SocketClient.java

import java.net.Socket;

public class SocketClient {

    private Socket socket;

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


//    对于客户端来说   启动客户端 就需要启动两个线程  一个是发送线程  一个是接收线程  因为
//    发送消息后  需要等待 服务端回消息    在等待过程中 就需要接收线程监听    与此同时 发送线程还可以继续发送消息
//    对于服务端而言  就只需要一条线程   即 接受到客户端消息-》处理-》回复
    public void startSocketClient(){
        try{
            new SocketClientSendThread(socket).start();
            new SocketClientReceiveThread(socket).start();
        }catch(Exception e){
            e.printStackTrace();
        }

    }
}

  (6)SocketClientSendThread.java

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;

//向服务端发送消息线程
public class SocketClientSendThread  extends Thread{

    private Socket socket;

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

    @Override
    public void run(){
        while (true){
            try{
//                等待3秒
                Thread.sleep(3000);
//                然后把信息写到 OutputStream 流里面   然后服务器就能从这个流里读取数据
                String send = "客户(线程)"+Thread.currentThread().getName()+"向 \n 服务器发送消息。";
                BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                bfw.write(send);
                bfw.newLine();
                bfw.flush();

                System.out.println("给服务端发送的信息:"+send);
            }catch(Exception e){
                System.out.println("链接断开");
                if(socket!=null){
                    try{
                        if(!socket.isClosed()){
                            socket.close();
                        }
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                }
                break;
            }
        }


    }
}

  (7)SocketClientReceiveThread.java

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

// 客户端接收线程
public class SocketClientReceiveThread  extends Thread{

    private Socket socket;

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

    @Override
    public void run(){
//        这个循环也是   只要socket存在  出现异常 也会立即新建  InputStream接收流  及时获取服务器的信息
        while(true){
            try{
//                服务端会把回复消息写到 这个InputStream 流里面
//                这里客户端从这里就能获取服务端回复的消息
                BufferedReader bfr = new BufferedReader(new InputStreamReader(socket.getInputStream(), SocketUtils.streamEncoding));
                String line = "";
//                同服务端一样 这里的循环只要连接保持  这个循环就不会终止   需要一直遍历 从里面 读取服务端消息
                while((line = bfr.readLine())!=null){
                    System.out.println("接收到服务器回复过来的消息:"+line);
                }

            }catch(Exception e){
                System.out.println("链接断开");
                if(socket!=null){
                    try{
                        if(!socket.isClosed()){
                            socket.close();
                        }
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    }
                }
                break;
            }
        }
    }
}

2.系统的各种解释 我已经在代码的注释里写清楚了  但是这里有一点需要注意

我从流里读取消息使用的是  .readLine()   也就是一行读取一次,默认 一行就是一个消息,如果你一个消息里有个   \n  回车  他就会当作两个消息处理  所以使用的时候要注意,

这里我提供两个建议 1.客户端和服务端发送消息时候   替换  \n  为其他字符  输出时候再替换回来

2.将 BufferedReader  替换为其他输入流  一次性读取所有的消息    例如.read(new byte[2048])

如果代码里有不懂的地方  欢迎评论区留言。

猜你喜欢

转载自blog.csdn.net/q18792880831/article/details/125132500