关于Java Socket网络编程和ReadLine的坑

https://blog.csdn.net/zeng308041977/article/details/76650935

https://blog.csdn.net/github_39655029/article/details/79953606

https://blog.csdn.net/qq_34178998/article/details/76958137

 

使用Java Socket+多线程实现简单服务器一对多个客户端响应

 

服务器

public class Server {
    public static void main(String[] args) {

        Socket socket=null;
        try {
            //设置服务器端口号
            ServerSocket serverSocket=new ServerSocket(9999);


            while (true){
                System.out.println("等待客户端连接...");

                //等待客户端连接
                socket=serverSocket.accept();

                //创建一个线程
                ClientThread loginThread=new ClientThread(socket);

                //开始线程
                loginThread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

客户端线程类

public class ClientThread extends Thread {

    Socket socket=null;

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

    @Override
    public void run() {

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        Scanner input=new Scanner(System.in);
        InputStream is=null;
        OutputStream os=null;
        try {


                //获取客户端的ip地址
                System.out.println(socket.getInetAddress()+"已经成功连接到此服务器上."+df.format(new Date()));

                //打开输入/输出流
                is=socket.getInputStream();
                os=socket.getOutputStream();

                //获取客户端信息,即从输入流读取信息
                BufferedReader br=new BufferedReader(new InputStreamReader(is));

                String info=null;
                while (!((info= br.readLine()) ==null)){
                    System.out.println(socket.getInetAddress()+":"+info);

                }

                //服务器响应客户端
                System.out.println("本机服务器:");

                String reply="服务器成功回应!!";
                os.write(reply.getBytes());



        } catch (IOException e) {

            System.out.println("网络出现了故障.....!!");
            e.printStackTrace();
        }finally {

            try {
                if(is!=null)
                is.close();
                if(os!=null)
                os.close();

                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

客户端1,客户端2,...类似,此处以客户端1为例

public class Client2 {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        Socket socket= null;
        OutputStream os=null;
        InputStream is=null;
        try {

            while (true){
                socket = new Socket("localhost",9999);

                //打开输入/输出流
                os=socket.getOutputStream();
                is=socket.getInputStream();

                //发送客户端登录信息,即向输出流写入信息
                System.out.println("------欢迎进入聊天室------");
                System.out.println("客户端:");

                String info=input.next();
                os.write(info.getBytes());
                socket.shutdownOutput();

                //接收服务器的响应,即从输入流中读取信息
                String reply=null;
                BufferedReader br=new BufferedReader(new InputStreamReader(is));
                while (!((reply=br.readLine()) ==null)){
                    System.out.println("服务器:"+reply);
                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                if(is!=null)
                    is.close();
                if(os!=null)
                    os.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

关于Socket中使用ReadLine的坑

   结果运行的时候,当开启服务端和客户端后,在客户端的控制台 键盘输入 内容,服务端却没有显示内容

原因:

1.原来readLine()方法在进行读取一行时,只有遇到回车(\r)或者换行符(\n)才会返回读取结果,这就是“读取一行的意思”,重要的是readLine()返回的读取内容中并不包含换行符或者回车符;

2.由于在客户端使用的readLine()来读取用户输入,所以当用户按下回车键是,readLine() 返回读取内容,但此时返回的内容并不包含换行符(查看readLine()源码,会将\r,\n或者\r\n去除掉),而当在服务器端用readLine()再次读取时,由于读取的内容没有换行符,所以readLine()方法会一直阻塞等待换行符,这就是服务器端没有输出的原因。

 

解决方法:

在客户端每次输入回车后,手动给输入内容加入"\n"或"\r",再写入服务器;

关于Java Socket网络编程和ReadLine的坑_第1张图片

 

注意:

1、误以为readLine()是读取到没有数据时就返回null(因为其它read方法当读到没有数据时返回-1),而实际上readLine()是一个阻塞函数,当没有数据读取时,就一直会阻塞在那,而不是返回null。没有数据时会阻塞,在数据流异常或断开时才会返回null

2、readLine()只有在数据流发生异常或者另一端被close()掉时,才会返回null值。
如果不指定buffer大小,则readLine()使用的buffer有8192个字符。在达到buffer大小之前,只有遇到"/r"、"/n"、"/r/n"才会返回。
3、使用socket之类的数据流时,要避免使用readLine(),以免为了等待一个换行/回车符而一直阻塞

你可能感兴趣的:(关于Java Socket网络编程和ReadLine的坑)