Я пытаюсь создать простое приложение для чата 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();
Вам не нужно создавать новый DataOutputStream только для его закрытия. Но вы должны проверить результат каждого readLine() для null, и если так закрыть сокет и выйти из потока. – EJP
Возможный дубликат [Java-сокета клиента с использованием writeBytes] (http://stackoverflow.com/questions/9341898/java-client-socket-using-writebytes) –
@EJP отметил сэр. Я уверен, что отправленные данные не являются нулевыми. – andreianna