2012-05-09 175 views
0

我使用线程为客户端提供服务,但是当我删除命令handler.out.flush(在Server类上)时,线程挂起。我试过在谷歌搜索,但仍然没有帮助。我认为问题在于通信套接字,但我仍然没有找到正确的解决方案。服务器线程挂起

我想做一个简单的登录和注册功能,所以我使用了2类,ServerMysqlConnServer类通过套接字从客户端接收传入数据(用户配置文件 - 用户名,密码等)。收到后,数据将被发送到MysqlConn班。 MysqlConn类的功能是检查数据并访问我的sql数据库以匹配它们。如果数据和数据库匹配,那么登录过程就是succsses。

由客户端发送的数据的格式是:

"login."+"name."+ "password." +"\n"; 

以下是Server类的内容:

public class Server {  

public static void main(String[] args)throws IOException, InstantiationException, 
IllegalAccessException { 

    ServerSocket servsocket = null; 
    Socket sock = null;   

    try { 
     servsocket = new ServerSocket(28000); 
     while(true){ 
     sock = servsocket.accept(); 
     System.out.println(servsocket.isBound()); 

     ChatThread thread = new ChatThread(sock); 
     String portnum = Integer.toString(sock.getPort()); 
     thread.run(portnum);     
     } 
    } catch (IOException ioe) { 

    } 
    finally{ 
      try { 
       servsocket.close(); 
       } catch (IOException ioe) { 

       } 
      }  
    } 
    } 

class ChatThread extends Thread{ 
    static Vector<ChatThread> chatthread = new Vector<ChatThread>(10); 

    private BufferedReader in; 
    private PrintWriter out;   

    public ChatThread (Socket socket) throws IOException { 

     in = new BufferedReader(
       new InputStreamReader(socket.getInputStream())); 
     out = new PrintWriter(
       new OutputStreamWriter(socket.getOutputStream())); } 

    public void run(String portnum){ 
     String line; 
     synchronized(chatthread) { 
     chatthread.addElement(this); } 
     try { 
     line = in.readLine()+portnum; 
     String[] teksmasuk = line.split("\\."); 

     for(int i = 0; i < chatthread.size(); i++) { 
       synchronized(chatthread) { 
       ChatThread handler = 
       (ChatThread)chatthread.elementAt(i); 
       handler.out.println(line + "\r"); 
       handler.out.flush(); 
       if 
    (teksmasuk[0].contentEquals("reg")||teksmasuk[0].contentEquals("login") 

    ||teksmasuk[0].contentEquals("logout")) { 
        if(teksmasuk[0].contentEquals("reg")){ 
         } 
        else 
    if(teksmasuk[0].contentEquals("login")){ 
         } 

       MysqlConn sqlcon = new MysqlConn(); 
       String hasil = sqlcon.register(line); 


       }     
       else{   

       } 
       } 

       }   
     } catch(IOException ioe) { 

     ioe.printStackTrace(); 
     } catch (InstantiationException e) { 

      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 

      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 

      e.printStackTrace(); 
     } 
     finally { 
      synchronized(chatthread) { 
      chatthread.removeElement(this); 
      } 
     } 
}            
}  

MysqlConn类:

public class MysqlConn{ 
String dbn = "chat_db"; 
String URL = "jdbc:mysql://localhost/"+dbn ; 
String usr = "root"; 
String pwd = ""; 
private String result; 
boolean checkname = false; 
boolean checkemail  = false; 
boolean checkpass = false; 
private Connection con = null; 
private String dbnama; 
private String dbpass; 

public String register(String line) throws InstantiationException, 
IllegalAccessException, IOException, ClassNotFoundException{ 

     String[] messagein = 
line.split("\\."); 

     MysqlConn regs = new MysqlConn(); 
     regs.login(messagein); 
     return result;    
    } 

    public void login (String[] messagein) throws InstantiationException, 
    IllegalAccessException{ 
    if(messagein[0].contentEquals("login")) { 
     try { 
      Class.forName("com.mysql.jdbc.Driver").newInstance(); 
      con = DriverManager.getConnection(URL,usr,pwd); 
      Statement statement = 
    con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); 
      ResultSet rslset = statement.executeQuery("select * from user"); 
      int rs = statement.executeUpdate("update user set port="+ 
    "'"+messagein[3] +"'" + "where nama = " 
        + "'" + messagein[1] + "'" + "and password = " + "'" 
    +messagein[2] +"'"); 

      MysqlConn regs = new MysqlConn(); 
      regs.check_status_login(messagein); 

      } catch (ClassNotFoundException e) { 
       System.out.println("Error #1:" + e.getMessage()); 
       System.exit(0); 
      } catch(SQLException e){ 
       System.out.println("Error #2:" + e.getMessage()); 
       System.exit(0); 
      } 
     } 
    } 

    public void check_status_login (String[] messagein) throws InstantiationException, 
    IllegalAccessException, ClassNotFoundException{ 
    try { 
     Class.forName("com.mysql.jdbc.Driver").newInstance(); 
     con = DriverManager.getConnection(URL,usr,pwd); 
     Statement statement = 
    con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); 
     ResultSet rslset = statement.executeQuery("select * from user");    

     while(rslset.next()) { 
      String dbname = rslset.getString("nama"); 
      String dbpass = rslset.getString("password");     
      if((messagein[1].contentEquals(dbnama))){ 

       + messagein[1]+ "\r" + "Password from database: "+dbpass + "\r" + 
       "Password from client: "+ messagein[2]+ "\n"); 
       checknama = true; 
      } 
      else if (messagein[2].contentEquals(dbpass)){ 
        checkpass = true; 
      } 
    } 
     } catch (SQLException e1) { 
     + e1); 
    } 
    if (!checknama){ 
     hasil = "gagal"; 
    } 
    else if (!checkpass) 
    { 
     hasil = "gagal"; 
    } 
    else { 
     hasil = "login sukses";} 
    } 
    } 
+1

呼叫ChatThread.start(前到底会发生)实际启动线程。调用run是一个不会启动线程的常规方法。 – LazyCubicleMonkey

+0

我已经取代它(** thread.run(portnum); **到** thread.start(); **)但仍然错误 –

+1

这里有太多的代码供我们解析和帮助。我会确保你正在记录_all_异常,并使用调试器或'println'消息来找出你被卡住的地方。然后,您可以将您的代码修剪到实际的问题位置。 – Gray

回答

0

化java docs明确地说,你是构造函数使用PrintWriter不会导致自动冲洗。这意味着你需要调用flush来手工发送数据到printwriter。或者你可以做

out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()) , true); 

启用自动冲洗。我通常宁愿手动进行冲洗流。

至于你关于你的问题“申请卡”,则需要提供更多的信息,比如有多少客户端连接,什么,而不是运行系统挂起