2014-05-13 148 views
1

我通过TCP sockat创建简单的聊天应用程序,但程序冻结时,当我尝试将数据发送到服务器登录,当我尝试调试客户端代码时, Dataoutputstream.write Server代码通过TCP套接字的DataOutputStream死锁

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.ArrayList; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

/* 
* To change this license header, choose License Headers in Project Properties. 
* To change this template file, choose Tools | Templates 
* and open the template in the editor. 
*/ 

/** 
* 
* @author HADDAD 
*/ 
public class Server { 
    final static int LOGIN=0,LOGOUT=1,BCAST=2,MCAST=3,SERVER=4; 
    private DataInputStream in; 
    private DataOutputStream out; 
    private Socket client; 
    private ServerSocket serverSocket; 
    private ArrayList<connection> conlist=new ArrayList<>(); 
    private boolean running; 
    private byte[] bytes=new byte[1000]; 
    private String msg; 
    private String[] msgs; 
    private int tag; 
    private static ServerGui serverGui=new ServerGui(); 
    public void runServer() 
    { 
     serverGui.jTextArea1.append("CHAT SERVER STARTED"); 
     running=true; 
     while(running) 
     { 
     try { 
      serverSocket =new ServerSocket(1676); 
      client =serverSocket.accept(); 
      in=new DataInputStream(client.getInputStream()); 
      // out=new DataOutputStream(client.getOutputStream()); 
      in.read(bytes); 
      msg=new String(bytes); 
      msgs=msg.split("-"); 
      tag=check(msgs); 
      switch(tag) 
        { 
        case LOGIN: 
        { 
         if(login(msgs[1], msgs[2], client)){} 
         else { System.out.println("login failed"); 
         serverGui.jTextArea1.append("login failed"); 
         } 
         break; 
        } 
        case LOGOUT: 
        { 
         if(logout(msgs[1])){} 
         else System.out.println("you are not logged in"); 
         break; 
        } 
        case SERVER: 
          recivemsg(msgs[1], msgs[0]); 
         break; 
        case MCAST: 
        { 
         multiCast(msgs); 
        } 
        case BCAST: 
        { 
         broadCast(msgs); 
        } 

        } 

     } catch (IOException ex) { 
      Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
     } 


     } 
    } 
    public int check(String[] data) 
    { 
     return Integer.parseInt(data[data.length-1]); 

    } 
    public boolean login(String usr,String pass,Socket s) throws IOException 
    { 
     connection con=new connection(s, usr); 
     if(1==1){ 

     conlist.add(con); 
     writeMsgFromserver(con,true); 
     return true;} 
     else{ 
      writeMsgFromserver(con, false); 
      return false; 
     } 
    } 
    public boolean logout(String usr) 
    { 
     for(connection c:conlist) 
     { 
      if(c.getUsername().equals(usr)) 
      { 
       conlist.remove(c); 
       return true; 
      } 
      else return false; 
     } 
     return false; 
    } 
    public void recivemsg(String usr,String msg) 
    { 
     System.out.println(usr+":"+msg); 
    } 
    public void multiCast(String[] msgs) throws IOException 
    { 
     Socket s; 
     DataOutputStream dos; 
     if(conlist.isEmpty()) 
     { 
      serverGui.jTextArea1.append(System.lineSeparator()); 
      serverGui.jTextArea1.append("there is no other users"); 
      System.out.println("there is no other users"); 
     } 
     else 
      for(connection c:conlist) 
      { 
       s=c.getSocket(); 
       dos=new DataOutputStream(s.getOutputStream()); 
       dos.write(Format(msgs).getBytes()); 

      } 
    } 
    public void writeMsgFromserver(connection c,boolean b) throws IOException 
    { 
     if(b==true){ 
     String m="accept"+"-"+"Server"+"-"+"empty"+"-"+"empty"+"-"+SERVER; 
     Socket s=c.getSocket(); 
     DataOutputStream dos=new DataOutputStream(s.getOutputStream()); 
     dos.write(m.getBytes()); 
     serverGui.jTextArea1.append(System.lineSeparator()); 
     serverGui.jTextArea1.append("Server:"+c.getUsername()+" logged in"); 
     } 
     else 
     { 
      String m="refuse"+"-"+"Server"+"-"+"empty"+"-"+"empty"+"-"+SERVER; 
     Socket s=c.getSocket(); 
     DataOutputStream dos=new DataOutputStream(s.getOutputStream()); 
     dos.write(m.getBytes()); 
     serverGui.jTextArea1.append(System.lineSeparator()); 
     serverGui.jTextArea1.append("Server:"+c.getUsername()+" registeration failed"); 
     } 


    } 
    public void broadCast(String[] msgs) throws IOException 
    { 
     Socket rcvrsocket; 
     DataOutputStream dos; 
     for(connection c:conlist) 
     { 
      if(c.getUsername().equals(msgs[1])) 
      { 
       rcvrsocket=c.getSocket(); 
       dos=new DataOutputStream(rcvrsocket.getOutputStream()); 
       dos.write(Format(msgs).getBytes()); 
       return ; 
      } 

     } 
     System.out.println("user:"+msgs[1]+"Not found!"); 
     serverGui.jTextArea1.append(System.lineSeparator()); 
     serverGui.jTextArea1.append("user:"+msgs[1]+"Not found!"); 
    } 
    public String Format(String[] m) 
    { 
     StringBuilder builder=new StringBuilder(); 
     for (int i=0;i<m.length;i++) 
     { 
      builder.append(m[i]); 
      if(i!=m.length-1) 
      builder.append('-'); 
     } 
     return builder.toString(); 
    } 
    public static void main(String[] args){ 
     Server s=new Server(); 

     serverGui.main(args); 
     s.runServer(); 
    } 
} 

客户端代码

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.Socket; 

/* 
* To change this license header, choose License Headers in Project Properties. 
* To change this template file, choose Tools | Templates 
* and open the template in the editor. 
*/ 

/** 
* 
* @author HADDAD 
*/ 
public class client { 
    private String usrname; 
    private String pass; 
    private int port; 
    private Socket socket; 
    private DataInputStream dis; 
    private DataOutputStream dos; 
    private boolean loggedin=false; 
    private byte[] bytes; 
    private ClientGui cg; 

    public boolean isLoggedin() { 
     return loggedin; 
    } 

    public void setLoggedin(boolean loggedin) { 
     this.loggedin = loggedin; 
    } 

    public client(String usrname, String pass, int port,ClientGui cg) { 
     bytes=new byte[1000]; 
     this.usrname = usrname; 
     this.pass = pass; 
     this.port = port; 
     this.cg=cg; 

    } 
    public void start() throws IOException{ 
      socket =new Socket("localhost", port); 
     dis=new DataInputStream(socket.getInputStream()); 
     dos=new DataOutputStream(socket.getOutputStream()); 
     sendloginmsg(); 
     dis.read(bytes); 
     String m=new String(bytes); 
     String msgs[]=recive(m); 
     if(msgs[1].equals("accept")) 
     { 
      cg.jTextArea1.append(System.lineSeparator()); 
      cg.jTextArea1.append("logain successed"); 
     } 
     else 
     { 
      cg.jTextArea1.append(System.lineSeparator()); 
      cg.jTextArea1.append("logain failed check your username or password"); 
      return; 
     } 
     while(true) 
     { 
     dis.read(bytes); 
     m=new String(bytes); 
     msgs=recive(m); 
      writeToGui(msgs); 
     } 
    } 
    public void sendMsg(String msg) throws IOException 
    { 
     dos.write(msg.getBytes()); 
     dos.flush(); 
    } 
    public String[] recive(String msg) 
    { 
     String[] msgs=msg.split("-"); 
     String[] a={msgs[0],msgs[1],msgs[msgs.length-1]}; 
     return a; 
    } 
    public void writeToGui(String[] mm) 
    { 
     switch(Integer.parseInt(mm[mm.length-1])) 
      { 
      case Server.SERVER: 
      { 
       cg.jTextArea1.append(System.lineSeparator()); 
      cg.jTextArea1.append("Server:"+mm[0]); 

      break; 
      } 
      case Server.MCAST : 
      { 
        cg.jTextArea1.append(System.lineSeparator()); 
      cg.jTextArea1.append(mm[1]+":"+mm[0]); 
      break; 
      } 
      case Server.BCAST: 
      { 
        cg.jTextArea1.append(System.lineSeparator()); 
      cg.jTextArea1.append(mm[1]+":"+mm[0]); 
      break; 
      } 
      } 

    } 
    public void sendloginmsg() throws IOException 
    { 
     String tag=String.valueOf(Server.LOGIN); 
       String[] m={"Hello!",usrname,pass,"Server",tag}; 
       sendMsg(Format(m)); 
    } 
    public String Format(String[] m) 
    { 
     StringBuilder builder=new StringBuilder(); 
     for (int i=0;i<m.length;i++) 
     { 
      builder.append(m[i]); 
      if(i!=m.length-1) 
      builder.append('-'); 
     } 
     return builder.toString(); 
    } 
} 

连接代码

import java.net.Socket; 

/* 
* To change this license header, choose License Headers in Project Properties. 
* To change this template file, choose Tools | Templates 
* and open the template in the editor. 
*/ 

/** 
* 
* @author HADDAD 
*/ 
public class connection { 
    private Socket socket; 
    private String username; 

    public connection(Socket socket, String username) { 
     this.socket = socket; 
     this.username = username; 
    } 

    public Socket getSocket() { 
     return socket; 
    } 

    public String getUsername() { 
     return username; 
    } 

} 

和死锁时,我打电话sendMsg()方法

+0

尝试调试发生.. – Juanpe

+0

我尝试了很多次,当我到达dos里面的sendMsg方法它冻结与noo异常 – Tony

+0

所以它与您的服务器的问题,如果没有例外意味着什么都没有出错,只是nothig正在发生,采取更好看在你的服务器代码 – Juanpe

回答

1

如果你到DataOutputStream类块写操作,这通常意味着另一端不读发生。

我建议向客户端添加一个单独的线程,该线程除了将DataInputStream的另一端读取到服务器之外,直到连接关闭。这种读取器线程可以安排与SwingUtils.invokeLater()事件循环事件

注:这意味着你的start()应该从一个新的线程被调用,所有更新的GUI应通过一个invokeLater()

+0

我在java.awt.EventQueue.invokeLater中创建了新的runnable – Tony

+0

我调用了gui中的start方法,但是我得到了相同的结果 – Tony

+0

@Tony invokeLater将它添加到事件队列中,start()将运行代码您从中调用它的线程。无论哪种方式,你正在使用唯一的事件线程来阻止读取,这意味着它不会做任何事情(如更新屏幕)您需要启动一个新的'Thread'来运行您的Runnable。 –