我做了这么一个基于Socket的聊天室:
客户端:建立一个Socket,然后(1)将个人信息以对象的形式发给服务器,(2)接收从服务器生成的ID,(3)再接收从服务器发来的在线用户列表.
接下来进入接收消息循环,当接收到一个消息对象时,显示在GUI上,当接收到一个用户列表时,更新GUI上的用户列表显示....服务器:建立一个ServerSocket,开始监听.每当接到一个请求时,生成一个ID,并用此ID与Socket构造一个客户服务线程.(1)接收客户发来的个人信息(2)向客户端发ID,(3)向所有关客户发更新以后的在线用户列表.感觉如此就可以了.但现在的问题是:
第二个用户上线时,第一个用户会接收到一个更新后的用户列表,但是这个用户列表仍然只有一条数据.第二个用户接收到两条.
而第三个用户上线时,第一个用户仍然接收只有一条数据的列表,第二个用户接收到只有两条数据的列表.第三个用户3条.
第四个用户上线时,第一个用户是:1条,第二个用户:2条,第三个用户:3条.第四个用户:4条.我把服务器端的输出和客户端的接收都打印出来了.
显示是:服务器发了正确的数据,但客户端接收到的不正确.但自己的代码查了下找不出问题.所以来求助高人.因为代码比较长,所以没有贴出来.
有兴趣的可以留个邮箱,我把代码打包发给他.谢谢
客户端:建立一个Socket,然后(1)将个人信息以对象的形式发给服务器,(2)接收从服务器生成的ID,(3)再接收从服务器发来的在线用户列表.
接下来进入接收消息循环,当接收到一个消息对象时,显示在GUI上,当接收到一个用户列表时,更新GUI上的用户列表显示....服务器:建立一个ServerSocket,开始监听.每当接到一个请求时,生成一个ID,并用此ID与Socket构造一个客户服务线程.(1)接收客户发来的个人信息(2)向客户端发ID,(3)向所有关客户发更新以后的在线用户列表.感觉如此就可以了.但现在的问题是:
第二个用户上线时,第一个用户会接收到一个更新后的用户列表,但是这个用户列表仍然只有一条数据.第二个用户接收到两条.
而第三个用户上线时,第一个用户仍然接收只有一条数据的列表,第二个用户接收到只有两条数据的列表.第三个用户3条.
第四个用户上线时,第一个用户是:1条,第二个用户:2条,第三个用户:3条.第四个用户:4条.我把服务器端的输出和客户端的接收都打印出来了.
显示是:服务器发了正确的数据,但客户端接收到的不正确.但自己的代码查了下找不出问题.所以来求助高人.因为代码比较长,所以没有贴出来.
有兴趣的可以留个邮箱,我把代码打包发给他.谢谢
我看看
[email protected]
谁敢抢版主的饭碗?
至于出现LZ那样的情况,我觉得应该用个键值对的集合去保存客户端连接上来的套接字,要想往某客户端发消息,只要拿到对应的套接字就行,不会出现这样的情况,我也只是用C#做过聊天软件,相信JAVA差不多的,原理是一样的,LZ也可以联系我的QQ
然后用户列表是用的Vector.上线一个用户时,马上将其加入到vector,然后再调用服务器上的方法sendtoall(而不是每个任务线程中的方法)把这个vector发到每个用户上.
主要是说服务器里面维护一个Vector,保存着在线用户列表,每上线一个用户后就把这个加到Vector里面,然后再用for循环遍历这个Vector里面的用户,将Vector自身发到每一个用户.客户端主要是用ObjectInputStream()封装了一个Socket.
用Switch处理接到的类,如果读出来的是消息,就显示出来.如果是一个Vector,就把它当用户列表看待,直接更新本地的在线用户列表就可以了.
但就是出问题:
第一个用户上线时,会接到一个列表,只有它自己.
第二个用户上线时,接到一个列表,有它自己和第一个用户,而第一个用户此时接到的列表只有第一个用户
第三个用户上线时,接到列表中有它自己,第二个用户和第三个用户,而第二个用户接到的列表中只有第二个用户和第一个用户,第一个用户接到的列表只有第一个用户.
....如此下去.
但是问题在于我在服务器端将发送的消息打印出来了,是对每个用户都发了同一个列表(包含正确的当前在线用户信息).
而客户端接收到数据后,首先将其打印出来,显示的是如上所说的错误数据.
//Server.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
public class Server {
Vector<String> v=new Vector<String>();
Vector<Task> tasklist=new Vector<Task>();
ServerSocket server;
static int count=0;
Server()throws Exception{
server=new ServerSocket(9999);
}
public static void main(String[] args)throws Exception {
Server s=new Server();
s.listen();
}
public void listen()throws Exception{
while(true){
Socket tmp=server.accept();
count++;
Task tmptask=new Task(tmp);
addUser(tmptask,"user"+count);
Thread s=new Thread(tmptask);
s.start();
}
}
public synchronized void addUser(Task t,String u){
this.tasklist.add(t);
this.v.add(u);
}
public synchronized void removeUser(Task t,String u){
this.tasklist.remove(t);
this.v.remove(u);
}
public void sendUserToAll()throws IOException {
Task tmptask;
System.out.println("#######begin send to all######");
for(int i=0;i<tasklist.size();i++){
tmptask=tasklist.get(i);
tmptask.oos.writeObject(v);
System.out.println("send v to the port:"+tmptask.socket.getPort()+" ,the v's data is :");
for(int j=0;j<v.size();j++){
String s=v.get(i);
System.out.println("******"+s);
}
}
System.out.println("#######end send to all######");
}
class Task implements Runnable{
Task(Socket s)throws Exception{
this.socket=s;
ois=new ObjectInputStream(s.getInputStream());
oos=new ObjectOutputStream(s.getOutputStream());
}
public Socket socket;
public ObjectInputStream ois;
public ObjectOutputStream oos;
public void run(){
try{
sendUserToAll();
}catch(IOException e){
e.printStackTrace();
}
}
}
}//******************
//Client.java
import java.net.Socket;
import java.util.Vector;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Client {
Socket s;
ObjectInputStream ois;
ObjectOutputStream oos;
Client()throws Exception{
s=new Socket("127.0.0.1",9999);
oos=new ObjectOutputStream(s.getOutputStream());
ois=new ObjectInputStream(s.getInputStream());
}
public void work()throws Exception {
while(true){
Vector v=(Vector)ois.readObject();
System.out.println("received a vector ,this is the data:");
for(int i=0;i<v.size();i++){
System.out.println("******"+(String)(v.get(i)));
}
}
}
public static void main(String[] args)throws Exception{
Client c=new Client();
c.work();
}
}
运行结果如下:
运行Client1: java Client
received a vector ,this is the data:
******user1
received a vector ,this is the data:
******user1再打开一个新的CMD,运行Client2: java Client
received a vector ,this is the data:
******user1
******user2
为什么收到的不是同样的数据
服务器端输出:
#######begin send to all######
send v to the port:2563 ,the v's data is :
******user1
#######end send to all#############begin send to all######
send v to the port:2563 ,the v's data is :
******user1
******user1
send v to the port:2564 ,the v's data is :
******user2
******user2
#######end send to all######
1.笔误一处:
System.out.println("send v to the port:"+tmptask.socket.getPort()+" ,the v's data is :");
for(int j=0;j <v.size();j++){
String s=v.get(i);
System.out.println("******"+s); 应该是:
String s=v.get(j); 2.第二个用户上线时,接到一个列表,有它自己和第一个用户,而第一个用户此时接到的列表只有第一个用户,以此类推:
本人以为是
Vector v=(Vector)ois.readObject();
的问题。
用这种对象传递包括子元素的Vector很难说会有什么结果。估计是和序列化有关。建议使用更底层的通讯,例如字节流。简单修改样例如下:Server:
public void sendUserToAll()throws IOException {
Task tmptask;
System.out.println("#######begin send to all######");
for(int i=0;i <tasklist.size();i++){
tmptask=tasklist.get(i);
//tmptask.oos.writeObject(v);
System.out.println("send v to the port:"+tmptask.socket.getPort()+" ,the v's data is :");
for(int j=0;j <v.size();j++){
tmptask.oos.writeObject((String)v.get(j));
String s = v.get(j);
System.out.println("******"+s);
} Client:
while(true){
String v=(Vector)ois.readObject();
System.out.println("received a vector ,this is the data:" + v);
}
Client:
while(true){
String v=(String)ois.readObject();
System.out.println("received a vector ,this is the data:" + v);
}
他改的是:在服务器端的发送数据的语句前加一句重构oos: tmptask.oos=new ObjectOutputStream(tmptask.socket);
然后对应的客户端接收数据前也加一句重构ois:ois=new ObjectInputStream(socket)这样就可以得到正常运行的结果了.但是却不知道是什么原因.