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

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
# Project-specific
# none (for now)
# Mac file finder metadata
.DS_Store
# MS Office temporary file
~*
# Emacs backup file
*~
# Java files
*.class
javadoc/
# JetBrains (IntelliJ IDEA) files
.idea/
out/
bin/
*.iml
*.iws
*.ipr
# Eclipse files
bin/
.settings/
.classpath
.project
# Visual Studio / VS Code files
.vs*/
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Netbeans files
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
# Xcode files
*.xcodeproj/
xcuserdata/
.build/
# Maven
target/
# Miscellaneous
tmp/
*.tmp
*.bak
*.bk
*.swp
*.gcno
pom.xml 0 → 100644
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.unl.cse.csce361</groupId>
<artifactId>RelayServer</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- FOR PRODUCTION CODE -->
<!-- n/a -->
<!-- FOR TEST CODE -->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package edu.unl.cse.csce361.relay;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.Set;
import static java.lang.System.exit;
public class RelayServer {
public static void main(String[] args) {
if (args.length == 0 || args.length > 2) {
printUsage();
exit(1);
}
int portNumber = 0;
try {
portNumber = Integer.parseInt(args[0]);
} catch (NumberFormatException ignored) {
printUsage();
exit(1);
}
boolean alternatingClients = false;
if (args.length == 2 && args[1].equalsIgnoreCase("alternatingClients")) {
alternatingClients = true;
}
new RelayServer().run(portNumber, alternatingClients);
}
private static void printUsage() {
System.err.println("Usage: java edu.unl.cse.csce361.relay.RelayServer <portNumber> (alternatingClients)");
System.err.println(" Where <portNumber> is the required network port the relay server will listen to,");
System.err.println(" and `alternatingClients` is the optional argument to prompt one client to be \"first.\"");
}
private Set<ClientHandler> clients;
public RelayServer() {
clients = new HashSet<>();
}
public void run(int portNumber, boolean alternatingClients) {
try {
ServerSocket serverSocket = new ServerSocket(portNumber);
// int counter = 0;
//noinspection InfiniteLoopStatement
while (true) {
Socket clientSocket = serverSocket.accept();
// System.out.print("Connection #" + ++counter);
ClientHandler clientHandler = new ClientHandler(clientSocket, clients);
clients.forEach(client -> client.addRelaySink(clientHandler));
// System.out.println(" connected to " + clients.size() + " others.");
clients.add(clientHandler);
clientHandler.start();
if (alternatingClients && clients.size() == 1) {
clientHandler.sendMessage("You are the first client.");
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
private class ClientHandler extends Thread {
private final BufferedReader in;
private final PrintStream out;
private final Set<ClientHandler> relaySinks;
public ClientHandler(Socket clientSocket, Set<ClientHandler> otherClients) throws IOException {
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintStream(clientSocket.getOutputStream());
relaySinks = new HashSet<>(otherClients);
}
@SuppressWarnings("UnusedReturnValue")
public boolean addRelaySink(ClientHandler otherClient) {
return relaySinks.add(otherClient);
}
@SuppressWarnings("UnusedReturnValue")
public boolean removeRelaySink(ClientHandler otherClient) {
return relaySinks.remove(otherClient);
}
public void sendMessage(String message) {
out.println(message);
}
@SuppressWarnings("unused")
public void sendObject(Object object) {
out.print(object);
}
public void run() {
// System.out.println("Thread started.");
Scanner scanner = new Scanner(in);
boolean running = true;
while (running) {
try {
String message = scanner.nextLine();
relaySinks.forEach(sink -> sink.sendMessage(message));
} catch (NoSuchElementException exception) {
// the client dropped, remove this handler from the other handlers and terminate
relaySinks.forEach((sink -> sink.sendMessage("Remote client dropped.")));
relaySinks.forEach(sink -> sink.removeRelaySink(this));
clients.remove(this); // accessing outer class
running = false;
}
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment