http://community.csdn.net/Expert/topic/5165/5165981.xml?temp=.1588404
原贴. 
再散100分解决这个问题. ...谢谢..客户端读服务器端数据报错
java.net.SocketException: socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at sun.nio.cs.StreamDecoder$CharsetSD.readBytes(StreamDecoder.java:411)
at sun.nio.cs.StreamDecoder$CharsetSD.implRead(StreamDecoder.java:453)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:183)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at com.etraveltek.common.log.SocketHandler.read(SocketHandler.java:93)
at com.etraveltek.common.log.SocketHandler.run(SocketHandler.java:118)客户端代码:
package com.etraveltek.common.log;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;public class SocketHandler extends Thread {
private Socket socket;
/** 输入流*/
private InputStream inStr;
/** 服务端ip地址*/
private String ipAdress;
/** 服务器状态标识变量*/
private boolean serverState=false;
/** socket状态表示变量*/
private boolean socketState=false;
/** 服务端端口号*/
private int port;
byte[] buf = new byte[1024];
/**
 * 构造函数设定ip与端口号
 * @param ipAdressip地址
 * @param port端口号
 */
public SocketHandler(String ipAdress, int port) {
this.ipAdress = ipAdress;
this.port = port;
}/**
 * 判断服务器是否可用,可用返回true不可用返回false
 * @return
 */
public boolean isValid() {
return serverState;
}/**
 * 连接服务器,只有用户名和密码正确才能成功连接服务器
 * @param username用户名
 * @param password密码
 */
public void connect(String username,String password) {
try {
socket=new Socket(ipAdress,port);
inStr =socket.getInputStream();
socketState= true;
StringBuffer sb = new StringBuffer();
sb.append(username).append(":").append(password);
send(sb.toString());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
socketState=false;
}
}/**
 * 把消息发送到服务端
 * @throws IOException 
 * 
 */
public void send(String sendContent) {
try {
BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())); 
bWriter.write(sendContent);
bWriter.flush();
bWriter.close();
} catch (IOException e) {
e.printStackTrace();
} }/**
 * 读服务器返回消息
 * @return
 */
public String read() {
String str;
StringBuffer sb = new StringBuffer();
if(null==inStr){
return "";
}
BufferedReader in=new BufferedReader(new InputStreamReader(inStr));try {
while((str=in.readLine())!=null){
sb.append(str);
}
} catch (IOException e) {
e.printStackTrace();
}return sb.toString();
}/**
 * 线程启动方法
 */
synchronized public void run() {
String receive;//收到的消息
int numConnected=0;//连接次数
while (true){
while(!isConnected()){//当连接
connect("111","111");
numConnected++;
if(numConnected > 5){
serverState=false;
break;
}
}
receive =read();
if(receive.equals("")){
break;
}else if(receive.equals("success")){
send("<123> 20061117102648 服务器 发送服务器信息");
}else if (receive.equals("getMsg")){
System.out.println("消息成功发送");
break;
}
break;
}
}public void close() {
try {
inStr.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}/**
 * 判断客户端是否成功连接服务端,成功连接返回true否则返回false
 * @return
 */
public boolean isConnected() {
 return socketState;
}public static void main(String []args){
SocketHandler sockethandler= new SocketHandler("192.168.0.31",1234);
sockethandler.start();
}
}
服务端代码: 
package test.com.etraveltek.common.log;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestServer extends Thread {
/** 服务器socket*/
private Socket s;/** 服务器构造函数传入socket*/
public TestServer(Socket s) {
this.s = s;
}
/**
 * 线程run方法读取客户端io流并在服务器端写文件
 */
synchronized public void run() {try {
while (true) {
BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
//BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter( s.getOutputStream())); 
String str=null;
while((str=in.readLine())!=null){
if(str.equals("111:111")){
bWriter.write("success");
System.out.println(str);
}else if(judgeStrFormat(str)){
bWriter.write("getMsg");
System.out.println(str);
}
}
bWriter.flush();
bWriter.close();
//in.close();
//s.close();
}
} catch (IOException e) {
}}/**
 * 服务器启动
 * @throws IOException
 */
public static void serverStart() throws IOException {
ServerSocket ss;
ss = new ServerSocket(1234);
while (true) {
Socket s = ss.accept();
        new TestServer(s).start();
}
}public static void main(String[] args) {
System.out.println("服务器启动");
try {
serverStart();
} catch (IOException e) {
e.printStackTrace();
System.out.println("服务器启动出错");
}
}public static boolean judgeStrFormat(String str) {
Pattern p = Pattern.compile("^<\\d+> \\d{14}( [^\\s]+){2}$");
Matcher m = p.matcher(str);
if (m.matches()) {
return true;
} else {
return false;
}
}
}
想实现客户端 跟服务端建立连接,客户端把 用户名 密码"111","111" 传到服务器端服务器端验证后返回一个"success" 客户端接受服务端回应 并接续发送数据 
我现在是在 "success"返回后 read()读到这个success 但是读得时候报上面得错误不知道原因在哪 .谢谢 指教!!!

解决方案 »

  1.   

    客户端没有关闭流
    synchronized public void run() {
    String receive;//收到的消息
    int numConnected=0;//连接次数
    while (true){
    while(!isConnected()){//当连接
    connect("111","111");
    numConnected++;
    if(numConnected > 5){
    serverState=false;
    break;
    }
    }
    receive =read();
    if(receive.equals("")){
    break;
    }else if(receive.equals("success")){
    send("<123> 20061117102648 服务器 发送服务器信息");
    }else if (receive.equals("getMsg")){
    System.out.println("消息成功发送");
    break;
    }
    break;
    }
    }服务器却关闭了流所以才会出现那样的情况synchronized public void run() {try {
    while (true) {
    BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
    //BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
    BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter( s.getOutputStream())); 
    String str=null;
    while((str=in.readLine())!=null){
    if(str.equals("111:111")){
    bWriter.write("success");
    System.out.println(str);
    }else if(judgeStrFormat(str)){
    bWriter.write("getMsg");
    System.out.println(str);
    }
    }
    bWriter.flush();
    bWriter.close();
    //in.close();
    //s.close();
    }
    } catch (IOException e) {
    }}
      

  2.   

    bWriter.write("success");
    改成
    bWriter.write("success\0");
    试一下
      

  3.   

    java.net.SocketException: socket closed 说清楚了,socket已经关闭了。
    connect("111","111")怎么放在while (true)里面啊?每次connect后的socket句柄都不同的。
      

  4.   

    谢谢你得回复 
    --
    java.net.SocketException: socket closed 说清楚了,socket已经关闭了。
    connect("111","111")怎么放在while (true)里面啊?每次connect后的socket句柄都不同的。
    ----------------
    socket已经关闭了 ,但是我并没用写关闭的代码,connect("111","111")怎么放在while (true)里面啊?每次connect后的socket句柄都不同的。(我这样想的每次连接连接不成功就抛异常做另外的事啊,怎么会有不通的句柄,一旦连接成功就不会在执行while循环的东西了啊).请指教
      

  5.   

    lowsar可能有道理,你把服务端的bWriter.flush();bWriter.close();去掉试试。
      

  6.   

    而且你服务端的while (true) 有什么意义?最好也去掉
      

  7.   

    不好意思,看错了,服务端的while (true)我理解错误。
      

  8.   

    而且你服务端的while (true) 有什么意义?最好也去掉
    -------------试了没用 ..我知道问题所在 但是不知道如何解决
    while(true)是为了一直执行来读服务端返回的消息.
    ------------------------------------
    /**
     * 把消息发送到服务端
     * @throws IOException 
     * 
     */
    public void send(String sendContent) {
    try {
    BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())); 
    bWriter.write(sendContent); 
    bWriter.flush();
    bWriter.close();                //这里关闭了,所以socket也关闭了.但是问题是.我这不  关闭的话,服务端收不到消息,用socket.shutdownOutput() ,后服务器跟客户端流断开 当想再次向服务器发送消息的时候,无法继续使用,所以不理解这里该怎么办..
    } catch (IOException e) {
    e.printStackTrace();
    }
      

  9.   

    BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 全改成:DataInputStream in = new DataInputStream(inStr);
    BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())); 全改成:DataOutputStream bWriter = new DataOutputStream(
    socket.getOutputStream());
    读写方法用readUTF();writeUTF();
    另外,我感觉你的程序结构上不合理!
      

  10.   

    inStr =socket.getInputStream();
    应该放在read()方法里面吧!!!public String read() {
    String str;
    StringBuffer sb = new StringBuffer();
    inStr =socket.getInputStream();
    if(null==inStr){
    return "";
    }
    BufferedReader in=new BufferedReader(new InputStreamReader(inStr));try {
    while((str=in.readLine())!=null){
    sb.append(str);
    }
    } catch (IOException e) {
    e.printStackTrace();
    }return sb.toString();
    }
      

  11.   

    找到地方了,问题出在客户端的read()里面。
      

  12.   

    怎么搞?其实按Robin_von(笨笨)  说的就行了 .但是为什么我的不行 晕. .
      

  13.   

    我给你调试了一下,就如fbchen所说,问题就出在代码不正确吧。
      

  14.   

    Robin_von(笨笨) 我短消息你了,给个联系方式吧.谢谢!有点问题问完你结贴!
      

  15.   

    你的程序又很多有问题.关于抛出的异常是由于你客户端的send()方法中
    public void send(String sendContent) {
    try {
    BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())); 
    bWriter.write(sendContent);
    bWriter.flush();
    bWriter.close();
    } catch (IOException e) {
    e.printStackTrace();
    } socket.getOutputStream() 发一次就要get一次...怎能不抛出异常
    另外程序虽然结构上貌似清晰.但内部结构混乱.需要很多改进
    其次输出流的读写最好用printWriter对象.
      

  16.   

    不好意思,刚才口误.不是get()的问题.是你close BufferedReader的时候连同socket也关闭了.
    呵呵
      

  17.   

    问题原因已经找到:
    1.send方法中的bWriter.close();会导致把Socket关闭,出现你贴出来的问题
    2.因为频繁使用readLine()方法,因此必须在发消息的时候加上"\r\n",否则该方法会阻塞
    如果你需要,我可以把修改过的代码贴出来!
      

  18.   

    package com.etraveltek.common.log;import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;public class SocketHandler extends Thread {
    private Socket socket;
    /** 服务端ip地址*/
    private String ipAdress;
    /** 服务器状态标识变量*/
    private boolean serverState=false;
    /** 服务端端口号*/
    private int port;
    byte[] buf = new byte[1024];

    private InputStream in;
    private OutputStream out;

    /**
     * 构造函数设定ip与端口号
     * @param ipAdressip地址
     * @param port端口号
     */
    public SocketHandler(String ipAdress, int port) {
    this.ipAdress = ipAdress;
    this.port = port;
    }

    /**
     * 判断服务器是否可用,可用返回true不可用返回false
     * @return
     */
    public boolean isValid() {
    return serverState;
    }

    /**
     * 连接服务器,只有用户名和密码正确才能成功连接服务器
     * @param username用户名
     * @param password密码
     */
    public void connect(String username,String password) throws IOException {
    try {
    socket=new Socket(ipAdress,port);
    in = socket.getInputStream();
    out = socket.getOutputStream();

    StringBuffer sb = new StringBuffer();
    sb.append(username).append(":").append(password);
    sb.append("\r\n");
    send(sb.toString());
    } catch (IOException e) {
    System.err.println("Cann't connect to server.");
    throw e;
    }
    }

    /**
     * 把消息发送到服务端
     * @throws IOException 
     * 
     */
    public void send(String sendContent) throws IOException {
    out.write(sendContent.getBytes());
    out.flush();
    }

    private String readLine(InputStream in) throws IOException {
    byte[] b = new byte[1024];

    int count = in.read(b);

    if(count<=0){
    return null;
    }

    String line = new String(b,0,count);
    return line;
    }

    /**
     * 线程启动方法
     */
    synchronized public void run() {


    try{
    System.out.println("Connecting to server...");
    connect("111","111");
    System.out.println("Receving message...");
    System.out.println("isConnected():"+socket.isConnected());
    System.out.println("isClosed():"+socket.isClosed());
    String receive = readLine(in);

    System.out.println("Receive Message:"+receive);
    in.close();
    out.close();
    close();
    }catch(IOException e){
    e.printStackTrace();
    }
    }

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

    public static void main(String []args){
    SocketHandler sockethandler= new SocketHandler("127.0.0.1",1234);
    sockethandler.start();
    }
    }package com.etraveltek.common.log;import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;public class TestServer extends Thread {
    /** 服务器socket*/
    private Socket s; /** 服务器构造函数传入socket*/
    public TestServer(Socket s) {
    this.s = s;
    }
    /**
     * 线程run方法读取客户端io流并在服务器端写文件
     */
    synchronized public void run() { try {
    InputStream in = s.getInputStream();
    OutputStream out = s.getOutputStream();

    String line = readLine(in);

    if(line.equals("111:111")){
    out.write("success".getBytes());
    out.flush();
    System.out.println(line);
    }
    in.close();
    out.close();
    s.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    private String readLine(InputStream in) throws IOException {
    byte[] b = new byte[1024];

    int count = in.read(b);

    if(count<=0){
    return null;
    }

    int index = 0;
    for(int i=0;i<count;i++){
    if(b[i]=='\r'){
    index = i;
    break;
    }
    }
    String line = new String(b,0,index);
    return line;
    }

    /**
     * 服务器启动
     * @throws IOException
     */
    public static void serverStart() throws IOException {
    ServerSocket ss;
    ss = new ServerSocket(1234);
    while (true) {
    Socket s = ss.accept();
        new TestServer(s).start();
    }
    } public static void main(String[] args) {
    System.out.println("start server...");
    try {
    serverStart();
    } catch (IOException e) {
    e.printStackTrace();
    }
    } public static boolean judgeStrFormat(String str) {
    Pattern p = Pattern.compile("^<\\d+> \\d{14}( [^\\s]+){2}$");
    Matcher m = p.matcher(str);
    if (m.matches()) {
    return true;
    } else {
    return false;
    }
    }
    }