只贴出网络传输的部分。
程序功能:服务端点击开始,客户端label显示准备抢答, 客户端单击【抢答】,择抢答的这个用户结果显示在客户端和服务端上。现在可以实现服务端点击,客户端再点击,结果显示在服务端,但是显示不到客户端去。【还有如果客户端连续点击多次,会出现socket的阻塞】服务端:public class Answer extends javax.swing.JFrame {
    //声明必要的常量和变量  ready 单击开始计数,来判断是否已经被单击。 port  端口  userID 连接服务端的用户数
    //run 当单击某按钮就为true,便开始执行循环,s ,ss ,test,dis, dos能看出        //新建一个线程用于操作抢答操作
        new Thread(new newThread()).start();
    }
    
    private class newThread implements Runnable
    {
        public void run()
        {
            start();
        }
    }
    
   public void start(){
        System.out.println("Server Start!");
        try {
            //创建ServerSocket对象
            ss = new ServerSocket(port);
            started = true;
        } catch(BindException e){
            System.out.println("端口使用中....");
            System.out.println("请关掉相关程序并重新运行服务器!");
            System.exit(0);
        }catch (IOException e){
            e.printStackTrace();
        }
        try {
            while(started){
                
                //等待连接,如果连接了控制台打印一个客户已经连接
                s = ss.accept();
                System.out.println("A client connected!");
                
                //创建一个新的对象,并且添加到集合中
                Client c = new Client(s);
                clients.add(c);
                
                //一个客户端一个线程
                new Thread(c).start();
            }        
        }catch (IOException e){
            e.printStackTrace();
        }finally{
            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
   //内部类
 protected class Client implements Runnable{
        private int ID = 0;
        private Socket s = null;
        private DataInputStream dis = null;
        private DataOutputStream dos =null;
        private boolean bConnect= false;
        
        public Client(Socket s){
            this.s =s;
            
            //设置当前连接客户端的ID
            this.setID(userID++);
            clientNum++;
            
            //窗体上面显示链接的客户端数量
            jLabel4.setText(String.valueOf(userID-1));
            this.bConnect= true;
            try {
                dis = new DataInputStream(s.getInputStream());
                dos = new DataOutputStream(s.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        public void send(){
            for(int i=0;i<clients.size();i++){
                try {
                        if(conW == 1)
                        {
                            //传过去准备字符串,客户端判断,如果是准备就在label中显示抢答开始
                            clients.get(i).dos.writeUTF("准备");
                            conR = 1;
                        }
                        else
                            clients.get(i).dos.writeUTF("用户" + ID+":  ");
                    //输出测试用,
                    
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //定义了单击 【准备】 conW = 1 while循环里if为真,就执行这里,这里又初始化为0,让它可以正常的点击才会执行写到客户端
            conW = 0;
        }
        
        public void run() {
            try {
                while(bConnect){
                    //start是 【开始】按钮单击以后 = 1, 如果单击了准备并且单击了start,服务端开始计时,客户端显示【开始抢答】
                    if(conW == 1 && start ==1)
                    {
                        //调用上面的send方法
                        this.send();
                    }
                    //send方法中 conR赋值为1,这里便可以执行
                    if(conR == 1)
                    {
                        //读取对方是否点击,如果点击了,就会在当前label中显示结果
                        String str = dis.readUTF();
                        if(str.equals("抢")){
                        jLabel2.setFont(new Font("微软雅黑",Font.BOLD,30));
                        run = false;
                        num++;
                        jLabel2.setText(num+"号题  "+"选手" + getID() +"  " +"耗时间:" + time);
                        String ip = s.getInetAddress().getHostAddress();
                        int port = s.getPort();
                        jTable1.setValueAt("       " + ip+" : "+port, rows, 0);
                        jTable1.setValueAt("      " + num, rows, 1);
                        jTable1.setValueAt("       选手" + getID(), rows, 2);
                        jTable1.setValueAt("   耗时" + time, rows, 3);
                        
                        rows++;
                           }
                        //把结果发给客户端(现在只会把结果发送到抢答成功的客户端,所以这里有问题)
                        sendMessage();
                        
                        //如果点击了开始,就= 1,执行,执行完了 = 2,如果再点击就显示:结果已出。并且再单击准备 让ready为初值0
                        ready = 2;
                    }
                    }
                    //初始化读和开始按钮单击情况
                    conR = 0;
                    start = 0;
            }
//                e.printStackTrace();\
            catch (Exception e){
                e.printStackTrace();
            }finally{
                try {
                    clients.remove(this);
                    bConnect = false;
                    if(dis != null) dis.close();
                    if(dos != null) dos.close();
                    if(s != null) s.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }        public int getID() {
            return this.ID;
        }        public void setID(int ID) {
            this.ID = ID;
        }
    }
  //开始按钮的监听事件
    private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        start = 1;}
 private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        run = false;
        ready = 0;
        jLabel2.setText("");
        conW = 1;
        
        }
//这里是单独把抢答结果发送到客户端中,这里好像只能发送到 抢答成功的客户端上,
    //我想使用循环判断clients集合的大小,并且 clients.get(i).dos.writeUTF(); 这样,但是客户端接收有问题。
    //一定要发一次,收一次,所以容易阻塞,由于是新手,所以写了几个ServerSocket
    public void sendMessage()
    {
        try{
        ServerSocket ss = new ServerSocket(10086);
        Socket s = ss.accept();
        DataOutputStream dos = new DataOutputStream(s.getOutputStream());
        for(int i=0;i<clients.size();i++){
            clients.get(i).dos.writeUTF(jLabel2.getText());
        }
        dos.close();
        s.close();
        ss.close();
        
        }catch(Exception e1){System.out.println(e1.getMessage());}
        
    }客户端:private void connect(){
//创建socket对象和输入输出流省略
            new Thread(new RecvThread()).start();     private class RecvThread implements Runnable{
        String s = null;
        public void run() {
        
            while(bConnected){
                try {
                    //接收,如果服务端发送的准备过来,这边label就显示抢答开始
                    s = dis.readUTF();
                    System.out.println(s);
                    if(s.equals("准备"))
                    {
                        i = 1;
                        jButton1.setEnabled(true);
                        jLabel1.setForeground(new java.awt.Color(255, 0, 0));
                        jLabel1.setText("抢答开始!"); 
                    }
                    else{
                         jTextArea2.append(s+"\r\n");
                         jButton1.setEnabled(false);
                    }
                    
                    while(true)
                    {
                        //计时已经开始,循环开始,,如果我点击了抢,就发送消息到客户端
                        if(i == 1 && j == 1)
                        {
                            dos.writeUTF("抢");
                            dos.flush();
                            getMessage();
                            jButton1.setEnabled(false);
                            Thread.sleep(3000);
                            jButton1.setEnabled(true);
                            
                            j++;
                            
                            break;
                        }
                    }
                        
                        j = 0;
                        i = 0;
                }catch(EOFException e){
                    e.printStackTrace();
                }catch(SocketException e){
System.out.println("服务端退出了!");
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public void getMessage()
    {
        try{
        Socket s = new Socket("127.0.0.1",10086);
        DataInputStream dis = new DataInputStream(s.getInputStream());
        String str = dis.readUTF();
        jLabel1.setText("恭喜你,抢答成功!");
        jTextArea2.append(str+"\r\n");
        dis.close();
        s.close();
        }catch(Exception e1){System.out.println(e1.getMessage());}
    }

解决方案 »

  1.   

    就相当于一个聊天室,客户端发生一句话,然后显示在聊天室的窗口里,那个不是有顺序的吗?服务端已经确定了信息,直接转发给客户端就行了,也不用都收到在转发,一收到客户端来的信息,就可以转发给所有客户端了。包括他自己。
    还有如果客户端连续点击多次这个问题更好解决了,在actionperformed里面,获取到了单机事件后,响应,用个flag标记两次单机时间是多少。
    如果时间太近,无效按键,接着重置就可以了。