import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;import qq.domain.Messages;
import qq.domain.User;public class ServerChat implements Runnable{
private static final String DATABASE_PATH = ""; private ServerSocket ss = null;
private boolean isStarted = false; private static ArrayList<User> users = new ArrayList<User>(); private ArrayList<Client> clients = new ArrayList<Client>();

@Override
public void run() {
this.startServer();
System.out.println("服务器停止了!!!!!!!!!!!!!");
}

public void startServer(){
System.out.println("服务器启动了!!!!!!!!!!!!!!");
try {
ss = new ServerSocket(8888);
this.isStarted = true;
//users = new DBUser().getUsersFromDB();

} catch (IOException e) {
e.printStackTrace();
}
while(isStarted) {
try {
Socket socket = ss.accept();
System.out.println("有个客户端连接上来了");
Client client = new Client(socket);
System.out.println("服务器端启动一个Client对话");
new Thread(client).start(); clients.add(client);
} catch (IOException e) {
e.printStackTrace();
}
}

}
public static void main(String[] args) {
ServerChat server = new ServerChat();
server.startServer();
}

class Client implements Runnable{
private Socket socket = null;
private boolean isConnection = false;
private InputStream input = null;
private OutputStream output = null;
private ObjectInputStream dis = null;
private ObjectOutputStream dos = null;
private Messages message = null;


public Client(Socket socket) {
this.socket = socket;
isConnection = true;
try {
input = this.socket.getInputStream();
output = this.socket.getOutputStream();

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

public void send(Messages message) {
try {
dos.writeObject(message);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public void run() {

try {
//这里阻塞了,如何解决
dis = new ObjectInputStream(input);
dos = new ObjectOutputStream(output);

while(isConnection) {
try {
System.out.println("服务器,将要读一次消息");
message = (Messages) dis.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}


System.out.println("服务器端收到:" +message.getMessage());
this.send(message);
}
} catch (IOException e) {
System.out.println("客户端连接已经中断");
} finally {
try {
if(dis != null) {
dis.close();
}
if(dos != null) {
dos.close();
}
if(socket != null){
socket.close();
}

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

}import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;import qq.domain.Messages;public class ClientChat { private Socket socket = null;
private ObjectInputStream dis = null;
private ObjectOutputStream dos = null;
private Messages message = null;

private boolean isConnection = false;

public ClientChat() {

}

public void connect() {

try {
this.socket = new Socket("爷的PC",8888);
dis = new ObjectInputStream(socket.getInputStream());
dos = new ObjectOutputStream(socket.getOutputStream());
isConnection = true;

new Thread(new receiveThread()).start();
} catch (IOException e) {
e.printStackTrace();
}
}

public void disConnect() {
try {
if(dis != null) {
dis.close();
}
if(dos != null) {
dos.close();
}
if(socket != null) {
socket.close();
}

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

public void send() {
Scanner scan = new Scanner(System.in);
String messageString = null;

try {
while(isConnection) {
messageString = scan.next();
message.setMessage(messageString);
dos.writeObject(message);

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

}

private class receiveThread implements Runnable {
private Messages receiveMessage = null;
@Override
public void run() {
try {
while(isConnection) {
try {
receiveMessage = (Messages) dis.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("客户端收到:"+message.getMessage());
}

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

}
public static void main(String[] args) {
ClientChat client = new ClientChat();
client.connect();
client.send();
}

}public class Messages {
private User fromUser = null;
private User toUser = null;
private String message = null;
private Image image = null;
private Icon icon = null;

public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Image getImage() {
return image;
}
public void setImage(Image image) {
this.image = image;
}
public Icon getIcon() {
return icon;
}
public void setIcon(Icon icon) {
this.icon = icon;
}
public User getFromUser() {
return fromUser;
}
public void setFromUser(User fromUser) {
this.fromUser = fromUser;
}
public User getToUser() {
return toUser;
}
public void setToUser(User toUser) {
this.toUser = toUser;
}


}程序走到下面这里就阻塞了,如何解决呢?
dis = new ObjectInputStream(input);
dos = new ObjectOutputStream(output);是因为ObjectInputStream和ObjectOutputStream只能通过文件流,不能通过网络流吗?
如果可以通过网络流传递对象,我的这个程序如何改才可以呢?
麻烦大家帮帮忙哈?都搞了2个小时了,郁闷!

解决方案 »

  1.   

    感觉你的那个两个流应该是在那个receiveThread 里面声明的我前段时间写过一个可以给你参考一下protected class Worker {
            protected Socket socket = null;
            protected DataInputStream dataIn;
            protected DataOutputStream dataOut;
            protected boolean closed = false;        public Worker(Socket socket) {
                this.socket = socket;            try {                socket.setTcpNoDelay(true);
                    socket.setKeepAlive(false);
                }
                catch (SocketException e) {
                    logger.error("Failed to set Socket properties: " + e.getMessage(), e);
                }        }
            public void dispose() {
                closed = true;
                try {
                    if (socket != null && !socket.isClosed()) {
                        if (logger.isDebugEnabled()) {
                            // some dirty workaround for IBM JSSE's SSL implementation,
                            // which closes sockets asynchronously by that point.
                            final SocketAddress socketAddress = socket.getLocalSocketAddress();
                            if (socketAddress == null) {
                                logger.debug("Listener has already been closed by other process.");
                            } else {
                                logger.debug("Closing listener: " + socketAddress);
                            }
                        }
                        socket.close();
                    }
                }
                catch (IOException e) {
                    logger.warn("Socket close failed with: " + e);
                }
            }        /**
             * Accept requests from a given TCP port
             */
            public void run() {
                try {
                    dataIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
                    dataOut = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));                while (!socket.isClosed()) {
                        try {                        Object readMsg = protocol.read(dataIn);
                            if (readMsg == null) {
                                break;
                            }
                                                             
                            Object result = processData(readMsg);
                            if (result != null) {
                                protocol.write(dataOut, (byte[])result);                        }
                            //protocol.write(dataOut,  (byte[])readMsg);
                            //dataOut.write((byte[])readMsg);                        dataOut.flush();                    }
                        catch (SocketTimeoutException e) {
                            if (!socket.getKeepAlive()) {
                                break;
                            }
                        }
                    }
                }
                catch (Exception e) {
                    handleException(e);
                }
                finally {
                    dispose();
                }
            }        protected Object processData(Object data) throws Exception {
                return d.doSend((byte[])data);
            }    }
      

  2.   

    感觉不是我想要的。
    我的意思是要能通过网络传递对象,而且是那种比较复杂的对象,想我代码的Message中的一个属性还是一个对象。
    google看了下是要对象序列化。但还是不是能明白。能帮忙把我这个代码给改造成传递对象的吗?
      

  3.   

    "爷的PC",8888   ;爷你吗的, 不装B要死是吧 
      

  4.   

    ls不要发些无聊的回复,没得意思,我是再问技术问题,不要捣乱哈!一边去圈圈叉叉!!!昨天晚上我都把问题解决了。
    1.客户端和服务器端的
    dis = new ObjectInputStream(socket.getInputStream());
    dos = new ObjectOutputStream(socket.getOutputStream());
    顺序必须是相互颠倒的才可以,不然就会阻塞。2.对象消息要实现序列化接口
      

  5.   


    难道我说错了,  现在的人都怎么了, 没事喜欢装爷作为初学者(我们都一样),还是先装儿子再装爷得好接收消息问题//伪代码class Receiver implements Runnable {
    BufferedReader read ;= 
    public void run () throws .... {
              read = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    String message = null;
    while((message=read.readLine())!=null){ //这种循环只有当客户端和服务器断开时才停止,没消息时一直阻塞
    //收到消息并显示在对话框
    }
    }
    }
      

  6.   

    看错了,要对象流是吧
    class Receiver implements Runnable {
        ObjectInputStream read ;
        public void run () throws .... {
            read = new ObjectInputStream(socket.getInputStream());
            while(true){         
               String message = ((String)read.readObject()).getMessage();
               
               //收到消息     
            }
        }
    }
      

  7.   

    今天终于试出来了,哈哈哈哈哈哈哈哈!
    最大的问题在于:
    向流中写入对象时要用writeUnshared()这个方法原因:将“未共享”对象写入 ObjectOutputStream。此方法等同于 writeObject,不同点在于它总是将给定对象作为流中唯一的新对象进行写入(相对于指向以前序列化实例的 back 引用而言)。尤其是: 
    通过 writeUnshared 写入的对象总是作为新出现对象(未曾将对象写入流中)被序列化,不管该对象以前是否已经被写入过。 
    如果使用 writeObject 写入以前通过 writeUnshared 写入的对象,则可将以前的 writeUnshared 操作视为写入一个单独对象。换句话说,ObjectOutputStream 永远不会生成通过调用 writeUnshared 写入的对象数据的 back 引用。 
    虽然通过 writeUnshared 写入对象本身不能保证反序列化对象时对象引用的唯一性,但它允许在流中多次定义单个对象,因此接收方对 readUnshared 的多个调用不会引发冲突。注意,上述规则仅应用于通过 writeUnshared 写入的基层对象,而不能应用于要序列化的对象图形中的任何可变迁方式引用的子对象。 
    重写此方法的 ObjectOutputStream 子类只能在处理 "enableSubclassImplementation" SerializablePermission 的安全上下文中构造;在不具有此权限的情况下,任何实例化这种子类的尝试都将导致抛出 SecurityException。