2014-02-18 2 views
0

Я пытаюсь создать простое приложение для чата Client-Server с клиентом. Я уже несколько дней нахожусь в Интернете, ища ответы на вопрос о проблеме, с которой я сейчас сталкиваюсь. Я пробовал все предложения и «решения», но я все еще не могу заставить его работать должным образом.Входные потоки java сокета

Проблема с потоками. Если я закрываю выходной поток клиента после отправки строки на сервер, Сервер успешно считывает строку. Но тогда сервер не смог отправить ответ, потому что сокет был закрыт. Если я не закрываю выходной поток клиента, сервер не сможет прочитать данные, отправленные клиентом. Я пробовал использовать мой код, но безрезультатно.

Вот мой код клиента: Код

import java.io.*; 
import java.net.*; 
import java.net.Socket; 

public class Client { 

public static BufferedReader bf; 
public static PrintWriter pw; 
public static Socket s; 
public static ClientLogin login = new ClientLogin(); 
public String me; 

public static boolean connect(String ip, int port){ 
    try { 
     s = new Socket(ip, port); 
     pw = new PrintWriter(s.getOutputStream(), true); 
     bf = new BufferedReader(new InputStreamReader(s.getInputStream())); 
     new ServerListener().start(); 

    }catch (ConnectException ce){ 
     return false; 
    } catch (UnknownHostException ex) { 
     return false; 
    } catch (IOException ex) { 
     return false; 
    } 
    return true; 
} 

public void send(String msg){ 
    try{ 
     if(msg.length()>0){ 
      pw.write(msg); 
      System.out.println("client message sent.. " + msg); 
     } 
    }catch(Exception e){ 
     System.out.println("Error in client sender: " + e); 
    } 
} 
} 

class ServerListener extends Thread{ 

@Override 
public void run(){ 

    String res = ""; 
    String input; 
    try{ 
     System.out.println("client listening...."); 
     input = Client.bf.readLine(); 
     System.out.println(input); 

     if(input.startsWith("LOGIN")){ 
      ClientLogin cl = new ClientLogin(); 
      cl.login(input); 
     }else{ 
      ClientLogin.errorLabel.setText(input); 
     } 

    }catch(Exception e){ 
     System.out.println("Error in Client listener: " + e); e.printStackTrace(); 
    } 

} 

} 

Сервер:

package server; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.InetAddress; 
import java.net.Socket; 
import java.net.ServerSocket; 
import java.net.SocketException; 
import java.util.LinkedList; 

public class ChatServer { 
    public static final LinkedList<Socket> sockets = new LinkedList<>(); 
    private static Dbdriver db; 
    private static int users; 
    static clientThread cl = new clientThread(); 
    public static InetAddress ia; 

public ChatServer(){ 
    db = new Dbdriver(); //database connection 
    db.getClass(); 
    try{ 
     users = db.countUsers(); 
    }catch(Exception e){ e.printStackTrace(); } 
} 

//START SERVER 
public static void startServer(){ 
    clientThread s = new clientThread(); 
    s.start(); 
} 

public static void stopServer(){ 
    try { 
     synchronized(ChatServer.sockets){ 
      for(Socket ss:sockets){ 
       if(ss.isConnected()){ 
        MessengerEngine.pw.close(); 
        ss.close(); 
       } 
      } 
      sockets.clear(); 
     } 
     cl.theServer.close(); 
    } catch (IOException ex) {ex.printStackTrace(); } 
} 

} 

class clientThread extends Thread { 

public static ServerSocket theServer; 

@Override 
public void run() { 
    int port = 8888; 
    try{ 
     theServer = new ServerSocket(port); 

     while(true){ 
      MessengerEngine engine = new MessengerEngine(theServer.accept()); 
      engine.start();   
     } 
    }catch(SocketException se){ 
    }catch(Exception e){ 
    } 
} 
} 

class MessengerEngine extends Thread{ 

public static Dbdriver theDriver; 
private Socket theSocket; 
    private BufferedReader bf; 
    private PrintWriter pw; 

    public String ipadd; 

public MessengerEngine(Socket s){ 
    theSocket = s; 
    synchronized(ChatServer.sockets){ 
     ChatServer.sockets.add(theSocket); 
    } 

try{ 
     bf = new BufferedReader(new InputStreamReader(theSocket.getInputStream())); 
     pw = new PrintWriter(theSocket.getOutputStream(), true); 
     ipadd = s.getInetAddress().getHostAddress(); 
     AdminServer.serverLog.setText(AdminServer.serverLog.getText() + ipadd +" has connected." +"\n"); 
}catch(Exception e){ 
     System.out.println("Socket.accept error"); 
} 
} 

@Override 
public void run(){ 

    String res = ""; //server response 

     try{ 
      String input = bf.readLine(); 
      System.out.println("String from client: " + input); 
      String[] inputs= input.split("-"); 

      if(input.startsWith("LOGIN")){ //LOGIN - "LOGIN-name-pass-ip" 
       Dbdriver db = new Dbdriver(); 
       res = db.userLogin(inputs[1], inputs[2], inputs[3]); 
       System.out.println("Client logging in sent: " + inputs[1] + ", " + inputs[2] +", " + inputs[3]); 
       send(res); 
      } 
     }catch(IOException e){ 
      e.printStackTrace(); 
     } 
} 

public void send(String msg){ 
    System.out.println("Server trying to send: "+ msg); 
    pw.write(msg); 
    System.out.println("server sent message.."); 
} 
} 

Все данные клиента являются из текстовых полей (имя пользователя, пароль). Я хотел, чтобы сервер проверял вход клиента, проверяя его в базе данных. Сборка из текстовых полей и проверка входа в систему работают отлично. Моя единственная проблема - поток ввода клиента. Я думаю. Помогите ученику программирования noob? Пожалуйста.

выброшенное исключение на сервере:

java.net.SocketException: Connection reset 
at java.net.SocketInputStream.read(SocketInputStream.java:196) 
at java.net.SocketInputStream.read(SocketInputStream.java:122) 
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283) 
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325) 
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177) 
at java.io.InputStreamReader.read(InputStreamReader.java:184) 
at java.io.BufferedReader.fill(BufferedReader.java:154) 
at java.io.BufferedReader.readLine(BufferedReader.java:317) 
at java.io.BufferedReader.readLine(BufferedReader.java:382) 
at server.MessengerEngine.run(ChatServer.java:102) 

ChatServer.java:102 >> Строка ввода = bf.readLine();

+0

Вам не нужно создавать новый DataOutputStream только для его закрытия. Но вы должны проверить результат каждого readLine() для null, и если так закрыть сокет и выйти из потока. – EJP

+0

Возможный дубликат [Java-сокета клиента с использованием writeBytes] (http://stackoverflow.com/questions/9341898/java-client-socket-using-writebytes) –

+0

@EJP отметил сэр. Я уверен, что отправленные данные не являются нулевыми. – andreianna

ответ

-1

Вы не должны закрывать потоки, пока ваше сообщение не будет завершено. Это всегда приведет к закрытию сокета. Что вам нужно сделать, так это использовать dos.flush() после записи чего-то в поток вывода данных, чтобы сервер получал информацию и закрывал доски только после того, как вы завершили свое сообщение.

+0

Вот где я запутался на самом деле. Я попытался выполнить flush() после записи в выходной поток, но затем сервер не считывает данные. Он просто ждет. :(Я принимаю какой-то смысл? :( – andreianna

+0

вы используете метод readLine, который устарел. Если вы имеете дело с простым текстом, вы должны использовать читателя/писателя, например, заменяя dos на устройство печати и din буферизированным считывателем поможет – Sanjeev

+0

О, я сделаю это сейчас :) Спасибо! – andreianna

Смежные вопросы