红色字体报错EOFException,错误如下:
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2571)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1315)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at com.way.chat.server.InputThread.readMessage(InputThread.java:71)
at com.way.chat.server.InputThread.run(InputThread.java:50)
服务端代码:package com.way.chat.server;import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;import com.way.chat.common.bean.TextMessage;
import com.way.chat.common.bean.User;
import com.way.chat.common.tran.bean.TranObject;
import com.way.chat.common.tran.bean.TranObjectType;
import com.way.chat.common.util.MyDate;
import com.way.chat.dao.UserDao;
import com.way.chat.dao.impl.UserDaoFactory;/**
 * 读消息线程和处理方法
 * 
 * 
 */
public class InputThread extends Thread {
private Socket socket;// socket对象
private OutputThread out;// 传递进来的写消息线程,因为我们要给用户回复消息啊
private OutputThreadMap map;// 写消息线程缓存器
private ObjectInputStream ois;// 对象输入流
private boolean isStart = true;// 是否循环读消息 public InputThread(Socket socket, OutputThread out, OutputThreadMap map) {
this.socket = socket;
this.out = out;
this.map = map;
try {
ois = new ObjectInputStream(socket.getInputStream());// 实例化对象输入流
} catch (IOException e) {
e.printStackTrace();
} } public void setStart(boolean isStart) {// 提供接口给外部关闭读消息线程
this.isStart = isStart;
} @Override
public void run() {
try {
while (isStart) {
// 读取消息
readMessage();
}
if (ois != null)
ois.close();
if (socket != null)
socket.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} } /**
 * 读消息以及处理消息,抛出异常
 * 
 * @throws IOException
 * @throws ClassNotFoundException
 */
public void readMessage() throws IOException, ClassNotFoundException {
Object readObject = ois.readObject();// 从流中读取对象
UserDao dao = UserDaoFactory.getInstance();// 通过dao模式管理后台
if (readObject != null && readObject instanceof TranObject) {
TranObject read_tranObject = (TranObject) readObject;// 转换成传输对象
switch (read_tranObject.getType()) {
case REGISTER:// 如果用户是注册
User registerUser = (User) read_tranObject.getObject();
int registerResult = dao.register(registerUser);
System.out.println(MyDate.getDateCN() + " 新用户注册:"
+ registerResult);
// 给用户回复消息
TranObject<User> register2TranObject = new TranObject<User>(
TranObjectType.REGISTER);
User register2user = new User();
register2user.setId(registerResult);
register2TranObject.setObject(register2user);
out.setMessage(register2TranObject);
break;
case LOGIN:
User loginUser = (User) read_tranObject.getObject();
ArrayList<User> list = dao.login(loginUser);
TranObject<ArrayList<User>> login2Object = new TranObject<ArrayList<User>>(
TranObjectType.LOGIN);
if (list != null) {// 如果登录成功
TranObject<User> onObject = new TranObject<User>(
TranObjectType.LOGIN);
User login2User = new User();
login2User.setId(loginUser.getId());
onObject.setObject(login2User);
for (OutputThread onOut : map.getAll()) {
onOut.setMessage(onObject);// 广播一下用户上线
}
map.add(loginUser.getId(), out);// 先广播,再把对应用户id的写线程存入map中,以便转发消息时调用
login2Object.setObject(list);// 把好友列表加入回复的对象中
} else {
login2Object.setObject(null);
}
out.setMessage(login2Object);// 同时把登录信息回复给用户 System.out.println(MyDate.getDateCN() + " 用户:"
+ loginUser.getId() + " 上线了");
break;
case LOGOUT:// 如果是退出,更新数据库在线状态,同时群发告诉所有在线用户
User logoutUser = (User) read_tranObject.getObject();
int offId = logoutUser.getId();
System.out
.println(MyDate.getDateCN() + " 用户:" + offId + " 下线了");
dao.logout(offId);
isStart = false;// 结束自己的读循环
map.remove(offId);// 从缓存的线程中移除
out.setMessage(null);// 先要设置一个空消息去唤醒写线程
out.setStart(false);// 再结束写线程循环 TranObject<User> offObject = new TranObject<User>(
TranObjectType.LOGOUT);
User logout2User = new User();
logout2User.setId(logoutUser.getId());
offObject.setObject(logout2User);
for (OutputThread offOut : map.getAll()) {// 广播用户下线消息
offOut.setMessage(offObject);
}
break;
case MESSAGE:// 如果是转发消息(可添加群发)
// 获取消息中要转发的对象id,然后获取缓存的该对象的写线程
int id2 = read_tranObject.getToUser();
OutputThread toOut = map.getById(id2);
if (toOut != null) {// 如果用户在线
toOut.setMessage(read_tranObject);
} else {// 如果为空,说明用户已经下线,回复用户
TextMessage text = new TextMessage();
text.setMessage("亲!对方不在线哦,您的消息将暂时保存在服务器");
TranObject<TextMessage> offText = new TranObject<TextMessage>(
TranObjectType.MESSAGE);
offText.setObject(text);
offText.setFromUser(0);
out.setMessage(offText);
}
break;
case REFRESH:
List<User> refreshList = dao.refresh(read_tranObject
.getFromUser());
TranObject<List<User>> refreshO = new TranObject<List<User>>(
TranObjectType.REFRESH);
refreshO.setObject(refreshList);
out.setMessage(refreshO);
break;
default:
break;
}
}
}
}求大神指点,急用!!!!我qq291950960,可以联系我详细说
红色为报错代码:显示为空指向客户端代码:
@Override
// 依据自己需求处理父类广播接收者收取到的消息
public void getMessage(TranObject msg) {
if (msg != null) {
// System.out.println("Login:" + msg);
switch (msg.getType()) {
case LOGIN:// LoginActivity只处理登录的消息

List<User> list = (List<User>) msg.getObject();
if (list.size() > 0) {
// 保存用户信息
SharePreferenceUtil util = new SharePreferenceUtil(
LoginActivity.this, Constants.SAVE_USER);
util.setId(mAccounts.getText().toString());
util.setPasswd(mPassword.getText().toString());
util.setEmail(list.get(0).getEmail());
util.setName(list.get(0).getName());
util.setImg(list.get(0).getImg()); UserDB db = new UserDB(LoginActivity.this);
db.addUser(list); Intent i = new Intent(LoginActivity.this,
FriendListActivity.class);
i.putExtra(Constants.MSGKEY, msg);
startActivity(i); if (mDialog.isShowing())
mDialog.dismiss();
finish();
Toast.makeText(getApplicationContext(), "登录成功", 0).show();
} else {
DialogFactory.ToastDialog(LoginActivity.this, "QQ登录",
"亲!您的帐号或密码错误哦");
if (mDialog.isShowing())
mDialog.dismiss();
}
break;
default:
break;
}
}
}
Androidsocket

解决方案 »

  1.   

    你的InputThread的socket是不是初始化有问题?贴一下socket初始化的代码。
      

  2.   

    public class InputThread extends Thread {
    private Socket socket;// socket对象
    private OutputThread out;// 传递进来的写消息线程,因为我们要给用户回复消息啊
    private OutputThreadMap map;// 写消息线程缓存器
    private ObjectInputStream ois;// 对象输入流
    private boolean isStart = true;// 是否循环读消息 public InputThread(Socket socket, OutputThread out, OutputThreadMap map) {
    this.socket = socket;
    this.out = out;
    this.map = map;
    try {
    ois = new ObjectInputStream(socket.getInputStream());// 实例化对象输入流
    } catch (IOException e) {
    e.printStackTrace();
    } }
      

  3.   

    InputThread中的构造方法。大神求带呀。可加qq291950960  
      

  4.   

    不是这一段代码,你在哪里创建的InputThread,把那段代码贴出来?
      

  5.   

    这是server端代码import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;import com.way.chat.common.util.Constants;
    import com.way.chat.common.util.MyDate;/**
     * 服务器,接受用户登录、离线、转发消息
     * 
     * 
     */
    public class Server {
    private ExecutorService executorService;// 线程池
    private ServerSocket serverSocket = null;
    private Socket socket = null;
    private boolean isStarted = true; public Server() {
    try {
    // 创建线程池,池中具有(cpu个数*50)条线程
    executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
    .availableProcessors() * 50);
    serverSocket = new ServerSocket(Constants.SERVER_PORT);
    } catch (IOException e) {
    e.printStackTrace();
    quit();
    }
    } public void start() {
    System.out.println(MyDate.getDateCN() + " 服务器已启动...");
    try {
    while (isStarted) {
    socket = serverSocket.accept();
    String ip = socket.getInetAddress().toString();
    System.out.println(MyDate.getDateCN() + " 用户:" + ip + " 已建立连接");
    // 为支持多用户并发访问,采用线程池管理每一个用户的连接请求
    if (socket.isConnected())
    executorService.execute(new SocketTask(socket));// 添加到线程池
    }
    if (socket != null)
    socket.close();
    if (serverSocket != null)
    serverSocket.close();
    } catch (IOException e) {
    e.printStackTrace();
    // isStarted = false;
    }
    } private final class SocketTask implements Runnable {
    private Socket socket = null;
    private InputThread in;
    private OutputThread out;
    private OutputThreadMap map; public SocketTask(Socket socket) {
    this.socket = socket;
    map = OutputThreadMap.getInstance();
    } @Override
    public void run() {
    out = new OutputThread(socket, map);
    // 先实例化写消息线程,(把对应用户的写线程存入map缓存器中)
    in = new InputThread(socket, out, map);// 再实例化读消息线程
    out.setStart(true);
    in.setStart(true);
    in.start();
    out.start();
    }
    } /**
     * 退出
     */
    public void quit() {
    try {
    this.isStarted = false;
    serverSocket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    } public static void main(String[] args) {
    new Server().start();
    }
    }
      

  6.   

    把“while (isStart) {
    // 读取消息
    readMessage();
    }”
    修改为:    while (isStart) {
        // 读取消息
        try
        {
           readMessage();
        }catch(EOFException e)//当发生该Exception的时候表明客户端的socket已经关闭了,但是你还在读,所以就会出错
        {
            break;//跳出循环
        }
       }