Skip to content
Snippets Groups Projects
Commit 26614b2a authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Gracefully handles case when client is ready before server.

Partially addresses #8
parent a8e36269
No related branches found
No related tags found
No related merge requests found
package edu.unl.cse.csce361.socket_chat; package edu.unl.cse.csce361.socket_chat;
import java.io.*; import java.io.*;
import java.net.InetAddress; import java.net.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.InputMismatchException; import java.util.InputMismatchException;
import java.util.Scanner; import java.util.Scanner;
import static java.lang.Thread.sleep;
public class Chat { public class Chat {
private static final int MAXIMUM_CONNECTION_ATTEMPTS = 10;
private Socket socket; private Socket socket;
private Scanner scanner; private Scanner scanner;
private boolean isHost; private boolean isHost;
public Chat() { public Chat() {
scanner = new Scanner(System.in); scanner = new Scanner(System.in);
try {
socket = connect(); socket = connect();
} catch (IOException ioException) {
System.err.println("Connection failed: " + ioException);
System.exit(1);
}
}
@SuppressWarnings("WeakerAccess")
public void communicate() {
try {
communicate(
new BufferedReader(new InputStreamReader(System.in)),
new BufferedReader(new InputStreamReader(socket.getInputStream())),
System.out,
new PrintStream(socket.getOutputStream()));
socket.close();
} catch (IOException ioException) {
System.err.println("Connection dropped: " + ioException);
System.exit(1);
}
}
@SuppressWarnings("SameParameterValue")
private void communicate(BufferedReader localInput,
BufferedReader remoteInput,
PrintStream localOutput,
PrintStream remoteOutput) {
System.out.println("Connection established. Host goes first.");
String message = "";
boolean myTurnToTalk = isHost;
try {
while (!message.equals("EXIT")) {
if (myTurnToTalk) {
message = localInput.readLine();
remoteOutput.println(encipher(message));
} else {
message = decipher(remoteInput.readLine());
localOutput.println(message);
}
myTurnToTalk = !myTurnToTalk;
}
} catch (IOException ioException) {
System.err.println("Connection dropped: " + ioException);
System.exit(1);
}
} }
private String encipher(String plaintext) { // THESE METHODS SET UP CONNECTION
// String ciphertext = ...;
// return ciphertext;
return plaintext;
}
private String decipher(String ciphertext) { private Socket connect() {
// String plaintext = ...;
// return plaintext;
return ciphertext;
}
private Socket connect() throws IOException {
System.out.print("Are you the chat host? [Y] "); System.out.print("Are you the chat host? [Y] ");
String answerString = scanner.nextLine().toUpperCase(); String answerString = scanner.nextLine().toUpperCase();
char answer = answerString.length() > 0 ? answerString.charAt(0) : 'Y'; char answer = answerString.length() > 0 ? answerString.charAt(0) : 'Y';
isHost = (answer != 'N'); isHost = (answer != 'N');
return isHost ? connectAsServer() : connectAsClient(); Socket socket = null;
try {
socket = isHost ? connectAsServer() : connectAsClient();
} catch (IOException ioException) {
System.err.println("Connection failed: " + ioException);
System.exit(1);
}
return socket;
} }
private Socket connectAsServer() throws IOException { private Socket connectAsServer() throws IOException {
...@@ -98,7 +51,28 @@ public class Chat { ...@@ -98,7 +51,28 @@ public class Chat {
String prompt = "Enter port host is opening at " + String prompt = "Enter port host is opening at " +
address[0] + "." + address[1] + "." + address[2] + "." + address[3]; address[0] + "." + address[1] + "." + address[2] + "." + address[3];
int port = getPort(prompt); int port = getPort(prompt);
return new Socket(InetAddress.getByAddress(address), port); Socket socket = null;
int attemptCount = 0;
do {
try {
sleep(1000*attemptCount++);
} catch (InterruptedException ignored) {
}
try {
socket = new Socket(InetAddress.getByAddress(address), port);
} catch (ConnectException ignored) {
System.out.println("Attempt " + attemptCount + ": Chat server is not yet ready at " +
address[0] + "." + address[1] + "." + address[2] + "." + address[3] + ":" + port);
if (attemptCount < MAXIMUM_CONNECTION_ATTEMPTS) {
System.out.println("Will attempt to connect again in " + attemptCount + " seconds");
socket = null;
} else {
System.err.println("Exceeded maximum number of connection attempts. Terminating.");
System.exit(1);
}
}
} while (socket == null);
return socket;
} }
private byte[] getRemoteHostAddress() { private byte[] getRemoteHostAddress() {
...@@ -159,6 +133,66 @@ public class Chat { ...@@ -159,6 +133,66 @@ public class Chat {
return port; return port;
} }
// THESE METHODS PERFORM CHAT AFTER CONNECTION IS SET UP
@SuppressWarnings("WeakerAccess")
public void communicate() {
try {
communicate(
new BufferedReader(new InputStreamReader(System.in)),
new BufferedReader(new InputStreamReader(socket.getInputStream())),
System.out,
new PrintStream(socket.getOutputStream()));
} catch (IOException ioException) {
System.err.println("Failed to set up input/output streams: " + ioException);
System.err.println("Terminating."); // I'm pretty sure this is recoverable if the client is waiting on the server
System.exit(1);
}
try {
socket.close();
} catch (IOException ioException) {
System.err.println("Error while closing socket: " + ioException);
// We're terminating anyway, note the error and continue normal termination
}
}
@SuppressWarnings("SameParameterValue")
private void communicate(BufferedReader localInput,
BufferedReader remoteInput,
PrintStream localOutput,
PrintStream remoteOutput) {
System.out.println("Connection established. Host goes first.");
String message = "";
boolean myTurnToTalk = isHost;
try {
while (!message.equals("EXIT")) {
if (myTurnToTalk) {
message = localInput.readLine();
remoteOutput.println(encipher(message));
} else {
message = decipher(remoteInput.readLine());
localOutput.println(message);
}
myTurnToTalk = !myTurnToTalk;
}
} catch (IOException ioException) {
System.err.println("Connection dropped: " + ioException);
System.exit(1);
}
}
private String encipher(String plaintext) {
// String ciphertext = ...;
// return ciphertext;
return plaintext;
}
private String decipher(String ciphertext) {
// String plaintext = ...;
// return plaintext;
return ciphertext;
}
public static void main(String[] args) { public static void main(String[] args) {
Chat chat = new Chat(); Chat chat = new Chat();
chat.communicate(); chat.communicate();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment