解决方案 »

  1.   

    读写也要放到线程里面,如果读到新的数据 就发广播 或者 用Handler 发送给主线程。
      

  2.   

    package socket.text;import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.lang.ref.WeakReference;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.nio.charset.Charset;
    import java.util.HashMap;
    import java.util.Map.Entry;import network.ConfigConst;import android.os.Handler;public class MessengerFactory implements Messenger, Runnable{

    private static Messenger instance;
    public static Messenger getInstance(){
    if(null==instance){
    instance = new MessengerFactory();
    instance.registProcesser(new MsgHandler());
    instance.setAddress(new InetSocketAddress(ConfigConst.SERVER_ADDRESS, 1234));
    instance.setCharset(Charset.forName("UTF-8"));
    instance.setDelimiter("~!OOXX!~");
    }
    return instance;
    }
    private InetSocketAddress address; private char[] buffer = new char[10240];

    private Charset charset; private String delimiter;

    private HashMap<Msg, Handler> msgCache = new HashMap<Msg, Handler>();

    private BufferedReader reader;
    private Socket socket;
    private SocketHandler socketHandler;
    private int status = Messenger.STATUS_DISCONNECTED;
    private StringBuilder stringBuilder = new StringBuilder();
    private BufferedWriter writer;
    private MessengerFactory(){
    }
    @Override
    public int getStatus() {
    return status;
    }
    @Override
    public void initSocket() {
    Thread thread = new Thread(this);
    thread.setName(getClass().getSimpleName());
    thread.setDaemon(true);
    status = STATUS_CONNECTING;
    thread.start();
    }
    /**
     * 分包,解码
     * @throws IOException
     */
    private void processInputStream() throws IOException {
    try{
    while(true){
    int n = reader.read(buffer);
    String s = new String(buffer, 0, n);
    stringBuilder.append(s);
    while(stringBuilder.toString().contains(delimiter)){
    int end = stringBuilder.indexOf(delimiter);
    String msg = stringBuilder.substring(0, end);
    stringBuilder.delete(0, end+delimiter.length());
    socketHandler.messageReceived(new Msg(msg), this);
    }
    }
    }catch(Exception e){
    e.printStackTrace();
    }
    stringBuilder = new StringBuilder();
    status = STATUS_DISCONNECTED;
    socket.close();
    socketHandler.socketClosed(this);
    System.out.println("Messenger Thread deaded");

    }
    @Override
    public void registMessageListener(Handler handler) {
    socketHandler.registMessageListener(new WeakReference<Handler>(handler));
    }
    @Override
    public void registProcesser(SocketHandler handler) {
    socketHandler = handler;
    }
    @Override
    public void registStatusListener(Handler handler) {
    socketHandler.registStatusListener(new WeakReference<Handler>(handler));
    }
    @Override
    public void run() {
    try {
    socket = new Socket(address.getHostName(), address.getPort());
    // socket.setKeepAlive(true);
    // socket.setSoTimeout(30000);
    socketHandler.socketConnected(MessengerFactory.this);
    status = STATUS_CONNECTED;
    reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), charset));
    writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), charset));
    sendCachedMsg();
    processInputStream();
    } catch (IOException e) {
    status = STATUS_DISCONNECTED;
    socketHandler.socketClosed(MessengerFactory.this);
    }
    }
    private void sendCachedMsg() {
    for(Entry<Msg, Handler> entry : msgCache.entrySet()){
    sendMessage(entry.getKey(), entry.getValue());
    }
    msgCache.clear();
    }
    @Override
    public void sendMessage(Msg msg) {
    sendMessage(msg, null);
    } @Override
    public void sendMessage(Msg msg, Handler h) {
    if(status==STATUS_CONNECTED){
    try {
    writer.write(msg.getStr());
    writer.write(delimiter);
    writer.flush();
    socketHandler.messageSent(msg, new WeakReference<Handler>(h));
    } catch (IOException e) {
    try {
    status = STATUS_DISCONNECTED;
    socket.close();
    socketHandler.socketClosed(this);
    } catch (IOException e1) {
    e1.printStackTrace();
    }
    }
    }else{
    System.out.println("put msg to cache");
    msgCache.put(msg, null);
    }

    } @Override
    public void setAddress(InetSocketAddress isa) {
    address = isa;
    } public void setCharset(Charset c){
    charset = c;
    }
    public void setDelimiter(String str){
    delimiter = str;
    }}