Java-readLine()阻塞问题

socket编程中readLine()阻塞问题

readLine()的API说明:

public String readLIne() throws IOException

中文版:

  • 读一行文字。 一行被视为由换行符(’\ n’),回车符(’\ r’)中的任何一个或随后的换行符终止。

  • 返回:包含行的内容的字符串,不包含任何行终止字符,如果到达流末尾,则为null

英文版:

  • Reads a line of text. A line is considered to be terminated by any one of a line feed (’\n’), a carriage return (’\r’), or a carriage return followed immediately by a linefeed.

  • Returns:

    A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached

遇到的问题

  1. 当使用socket写一个双向通信的服务端时,总是接收不到来自用户的消息,和书上比对才发现是readLine()的问题,
  2. 还有就是客户端和服务端的初始状态问题(一个为初始为“发送”,一个为“接收”)
第一种情况:
  • 一个客户端,一个服务端。当服务端使用readLine()读消息时,需要读到一个换行符(‘\n’,或’\r’)才会结束。否则回一直阻塞,主线程就挂在这儿了

    解决方法:在客户端发送消息的时候,外加一个换行符

//用户发送消息的线程
class SentMessage extends Thread{
        private Socket socket;
        private BufferedWriter bw;
        private BufferedReader mysc;
        SentMessage(Socket socket){
            this.socket = socket;
            try {
                bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
                mysc = new BufferedReader(new InputStreamReader(System.in));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void run(){
            try{
                while (true){
                    String mymessage = mysc.readLine();
                    bw.write(mymessage+"\n");
                    bw.flush();
                    if("bye".equals(mymessage)){
                        break;
                    }
                }
            }catch (IOException e){
                e.printStackTrace();
            }finally {
                try{
                    if(mysc!=null){
                        mysc.close();
                    }
                    if(bw!=null){
                        bw.close();
                    }
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
第二种:
  • 当用服务器转发来自每个用户的消息到聊天室时,如果就用一个"转发消息"方法也会出现问题,就是使用了readLine()的阻塞
  • 思考:一个客户都应有一个自己”转发消息“通道(线程),不和其他客户共用一个”转发通道“(会导致阻塞
  • 解决,用一个线程来做转发
//内置线程类用于接收消息,并广播
    class AcceptMessage extends Thread{
        private Socket clientsocket;
        private BufferedReader br;
        AcceptMessage(Socket clientsocket){
            this.clientsocket = clientsocket;
        }
        /**
         * 服务器将所有接收的消息广播(显示在每一个客户的聊天窗口中
         * 注意:如果这里不用线程,会出现问题,思考---其实就是readLine()阻塞的问题
         */
        private void tellEveryone(Socket socket){
            try{
                //先从发送消息的客户读内容
                br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String message = br.readLine();
                chatArea.append("用户"+socket.getPort()+": "+message+"\n");
                //然后将内容广播到每一个客户接口
                Iterator<Socket> it = list.iterator();
                while (it.hasNext()){
                    Socket socket2 = it.next();
                    //对自己就不要广播了
                    if(socket!=socket2){
                        bw = new BufferedWriter(new OutputStreamWriter(socket2.getOutputStream()));
                        bw.write(socket2.getInetAddress().getHostAddress()+": "+message+"\n");
                        bw.flush();
                    }
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        @Override
        public void run(){
            while (true){
                //接收并广播
                tellEveryone(clientsocket);
            }
        }
    }
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值