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 OutputStream()));
mysc =new BufferedReader(new InputStreamReader(System.in));
}catch(IOException e){
e.printStackTrace();
}
}
@Override
public void run(){
try{
while(true){
String mymessage = adLine();
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{socket编程聊天室基本流程
//先从发送消息的客户读内容
br =new BufferedReader(new InputStream()));
String message = br.readLine();
chatArea.append("⽤户"+Port()+": "+message+"\n");
//然后将内容⼴播到每⼀个客户接⼝
Iterator<Socket> it = list.iterator();
while(it.hasNext()){
Socket socket2 = it.next();
//对⾃⼰就不要⼴播了
if(socket!=socket2){
bw =new BufferedWriter(new OutputStream()));                        bw.InetAddress().getHostAddress()+": "+message+"\n");
bw.flush();
}
}
}catch(IOException e){
e.printStackTrace();
}
}
@Override
public void run(){
while(true){
//接收并⼴播
tellEveryone(clientsocket);
}
}
}