Witam.
Chciałbym napisać prosty komunikator sieciowy. Używam połączeń blokujących. Sytuacja wygląda tak: klient przesyła serwerowi wiadomość a ten odpowiada (międzyczasie klient czeka)
Jeżeli klient chciałby dopisać jakąś wiadomość musi czekać aż serwer odpowie, w przeciwnym wypadku jest zablokowany. Wypadałoby oczekiwać w nowym wątku na odbieranie wiadomości.
A jak zrobić to metodą nieblokującą?
Kolejna sprawa to wykrywanie rozłączenia połączenia.
Jak prawidłowo się rozłączyć z serwerem (lub na odwrót), żeby to wykrył. Są metody w socet (teoretycznie) umożliwiające sprawdzenie (is connected itd.). Jednak u mnie nie działają.
Jak sprawdzić połączenia, strumienie. Jak przy zamknięciu klienta serwer ma odebrać tą informację (szczególnie w przypadku awarii klienta, lub niespowadziewanego rozłączenia.
Napisałem taki kodzik. Serwer jest wielowątkowy.
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
private ArrayList threadList;
public int nr;
public Server() {
this.nr = 0;
this.threadList = new ArrayList(0);
try {
ServerSocket serverSocket = new ServerSocket(9090);
while (true) {
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
this.nr++;
System.out.println("::: CONNECT: "+this.nr);
ThreadServer thread= new ThreadServer(socket, this, this.nr, is, os);
thread.start();
this.threadList.add(thread);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
for (int i = 0; i < threadList.size(); i++) {
ThreadSpecial thread = (ThreadSpecial) threadList.get(i);
System.out.println("::: Server work: "+thread.isAlive());
thread.close();
}
} catch(Exception e) {
}
}
}
public static void main(String[] args) {
new Server();
}
}
Wątek serwera
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ThreadServer extends Thread {
public Server server;
public Socket socket;
public InputStream is;
public OutputStream os;
public int nr;
public ThreadServer(Socket socket, Server server, int nr, InputStream is, OutputStream os) {
this.server = server;
this.socket = socket;
this.is = is;
this.os = os;
this.nr = nr;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadServer.class.getName()).log(Level.SEVERE, null, ex);
}
synchronized(this) {
try {
//InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String number = br.readLine();
System.out.println("... "+this.nr+" Wiadomość od klienta: "+number);
String returnMessage;
try {
int numberInIntFormat = Integer.parseInt(number);
int returnValue = numberInIntFormat*2;
returnMessage = String.valueOf(returnValue) + "\n";
} catch(NumberFormatException e) {
returnMessage = "Wprowadź prawidłową liczbę\n";
}
//OutputStream os = this.socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage+" mada faka");
System.out.println(">>> "+this.nr+" Do klienta: "+returnMessage);//returnMessage);
bw.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void closeBude() {
try {
System.out.println("BUDA");
this.socket.close();
} catch (IOException ex) {
Logger.getLogger(ThreadServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Klient
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Client {
private static Socket socket;
public Client() throws IOException {
try {
this.socket = new Socket("localhost", 9090);
System.out.println("Klient...");
while(true) {
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
Scanner scanner = new Scanner(System.in);
String number = scanner.nextLine();
if ("123".equals(number)) {
bw.close();
osw.close();
os.close();
break;
}
//String number = "2";
System.out.println("Input: "+socket.isInputShutdown());
System.out.println("Output: "+socket.isInputShutdown());
String sendMessage = number + "\n";
bw.write(sendMessage);
bw.flush();
System.out.println("[>]Wiadomość dla serwera : "+sendMessage);
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("[<]Wiadomość od serwera : " +message);
}
socket.shutdownInput();
socket.shutdownOutput();
Close();
} catch (Exception exception) {
System.out.println("!!! Błąd kodu");
socket.shutdownInput();
socket.shutdownOutput();
Close();
exception.printStackTrace();
} finally {
try {
if (socket.isConnected()) {
// socket.shutdownInput();
// socket.shutdownOutput();
socket.close();
}
} catch(Exception e) {
System.out.println("!!! Błąd zamykania gniazda");
e.printStackTrace();
}
}
}
public void Close() {
try {
socket.close();
} catch (IOException ex) {
System.out.println("!!! Błąd zamykania gniazda in Close");
// Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String args[]) {
try {
new Client();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}