对象流阻塞问题,帮帮忙

hui135 2010-08-19 04:02:12

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个小时了,郁闷!
...全文
239 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
hui135 2010-08-24
  • 打赏
  • 举报
回复
今天终于试出来了,哈哈哈哈哈哈哈哈!


最大的问题在于:
向流中写入对象时要用writeUnshared()这个方法

原因:

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


class Receiver implements Runnable {
ObjectInputStream read ;
public void run () throws .... {
read = new ObjectInputStream(socket.getInputStream());
while(true){
String message = ((String)read.readObject()).getMessage();

//收到消息
}
}
}

sunhui5415 2010-08-20
  • 打赏
  • 举报
回复
对象流,服务器和客户端同时用的时候,会出现这中情况,可以试试用其他流处理
pywepe 2010-08-20
  • 打赏
  • 举报
回复
[Quote=引用楼主 hui135 的回复:]
Java code

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 jav……
[/Quote]

lz是要做qq呢
humanity 2010-08-20
  • 打赏
  • 举报
回复
3. 让一个线程负责提取消息。
humanity 2010-08-20
  • 打赏
  • 举报
回复
1,队列,
2,生产者-消费者 场景。
read_act 2010-08-20
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 hui135 的回复:]
ls不要发些无聊的回复,没得意思,我是再问技术问题,不要捣乱哈!一边去圈圈叉叉!!!
……
[/Quote]

难道我说错了, 现在的人都怎么了, 没事喜欢装爷。。。作为初学者(我们都一样),还是先装儿子再装爷得好

接收消息问题

//伪代码

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){ //这种循环只有当客户端和服务器断开时才停止,没消息时一直阻塞
//收到消息并显示在对话框
}
}
}
hui135 2010-08-20
  • 打赏
  • 举报
回复
关键是客户端这边接受界面输入、发送消息、接受消息不是同一个线程,改如何解决?
hui135 2010-08-20
  • 打赏
  • 举报
回复
我的意思是ls没看懂。
举个例子:我现在有一个登录界面、一个好友列表界面、一个聊天窗口界面和一个接受网络消息的主程序。

当我要在登录界面输入用户名、密码后,就跳到好友列表界面,然后再选一个好友,就进入聊天窗口界面。
在聊天窗口中输入消息,发送到服务器。

说明白点就是如何对接主程序和界面。因为主程序肯定要不断的接受,而聊天消息的发送是随机时间发送的,
所以应该是不用的线程才可以,但是这两个线程之间肯定要相互传递数据。这个该如何解决呢?
hui135 2010-08-20
  • 打赏
  • 举报
回复
现在又有个问题:

我在做一个类似QQ的程序,客户端有个主程序要不断接受服务器发送的消息,而又有从几个客户端界面上得到些数据,如何将这些数据传递给客户端主程序呢?这几个界面都是其他的线程。是不是要实现多线程之间的消息传递啊?多线程之间又是如何传递消息的?
大家一般是如何解决这类问题呢?
hui135 2010-08-20
  • 打赏
  • 举报
回复
ls不要发些无聊的回复,没得意思,我是再问技术问题,不要捣乱哈!一边去圈圈叉叉!!!

昨天晚上我都把问题解决了。
1.客户端和服务器端的
dis = new ObjectInputStream(socket.getInputStream());
dos = new ObjectOutputStream(socket.getOutputStream());
顺序必须是相互颠倒的才可以,不然就会阻塞。

2.对象消息要实现序列化接口
read_act 2010-08-19
  • 打赏
  • 举报
回复
"爷的PC",8888 ;

爷你吗的, 不装B要死是吧
hui135 2010-08-19
  • 打赏
  • 举报
回复
感觉不是我想要的。
我的意思是要能通过网络传递对象,而且是那种比较复杂的对象,想我代码的Message中的一个属性还是一个对象。
google看了下是要对象序列化。但还是不是能明白。能帮忙把我这个代码给改造成传递对象的吗?
wzh0439 2010-08-19
  • 打赏
  • 举报
回复
感觉你的那个两个流应该是在那个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);
}

}

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧