📄 chatserver.java
字号:
package at.ac.uni_linz.tk.vchat;
import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.text.*;
/**
* Main class for the server side's functionality. Starts a listener on the
* defined port, opens socket connections as needed and handles UserEvents.
*
* @author Arno Huetter
* (C)opyright by the Institute for Computer Science, Telecooperation Department, University of Linz
*/
public class ChatServer implements Runnable {
private static final String STORAGE_FOLDER = "users/";
private static final String IMAGE_FOLDER = "images/";
private static final String ROOM_FOLDER = "rooms/";
private static final String ROOM_FILENAME = "rooms";
private static final String KEY = "Admin";
private static final String BANNED_IP_FILENAME = "banned_ip";
public static final int LOGLEVEL0 = 0;
public static final int LOGLEVEL1 = 1;
public static final int LOGLEVEL2 = 2;
public static final int LOGLEVEL3 = 3;
public static final int DEFAULT_LOGLEVEL = LOGLEVEL1;
public static final int STANDARD_LOGLEVEL = LOGLEVEL1;
public static final int DELAY = 10000;
private ServerSocket listener;
private Vector connectionVector, bannedIPs;
private Thread serverThread;
private IntegerHashtable onlineTable, roomTable;
private String key, storageFolder, imageFolder, roomFolder, roomFilename;
private int logLevel;
private Random rand = new Random();
/**
* Starts the ChatServer.
*
* @param args[] command line arguments - the first argument is the server
* key
*/
public static void main(String args[]) {
int port;
try {
port = (args.length >= 1 && new Integer(args[0]).intValue() > 2048) ? new Integer(args[0]).intValue() : ChatRepository.DEFAULT_PORT;
}
catch (NumberFormatException excpt) {
port = ChatRepository.DEFAULT_PORT;
}
if (args.length >= 1 && (args[0].indexOf("?") != -1 || args[0].toLowerCase().indexOf("help") != -1)) {
System.out.println("Visual Chat Server");
System.out.println("Usage: java chat.ChatServer [ port [ serverkey [ storagefolder [ imagefolder [ roomfolder [ roomfilename [ loglevel ] ] ] ] ] ] ]");
System.out.println("Hint: Store banned ip-addresses in a file named \"banned_ip\"");
}
else {
new ChatServer(port, (args.length >= 2) ? args[1] : KEY, (args.length >= 3) ? args[2] : STORAGE_FOLDER, (args.length >= 4) ? args[3] : IMAGE_FOLDER, (args.length >= 5) ? args[4] : ROOM_FOLDER, (args.length >= 6) ? args[5] : ROOM_FILENAME, (args.length >= 7) ? ChatUtil.getInt(args[6]) : DEFAULT_LOGLEVEL);
}
}
/**
* Constructs the ChatServer.
*
* @param portParam the port the server is running on
* @param keyParam the server key
* @param storageFolderParam the foldername for storing user-files
* @param imageFolderParam the foldername for retrieving images
* @param roomFolderParam the foldername for storing user-files
* @param roomFileNameParam the foldername for retrieving images
* @param logLevelParam the logLevel
*/
public ChatServer(int portParam, String keyParam, String storageFolderParam, String imageFolderParam, String roomFolderParam, String roomFilenameParam, int logLevelParam) {
Object loadedObject;
Room room;
key = keyParam;
storageFolder = storageFolderParam + (storageFolderParam.endsWith("/") ? "" : "/");
imageFolder = imageFolderParam + (imageFolderParam.endsWith("/") ? "" : "/");
roomFolder = roomFolderParam + (roomFolderParam.endsWith("/") ? "" : "/");
roomFilename = roomFilenameParam;
logLevel = logLevelParam;
try {
new File(storageFolder).mkdirs();
new File(imageFolder).mkdirs();
new File(roomFolder).mkdirs();
listener = new ServerSocket(portParam);
connectionVector = new Vector();
onlineTable = new IntegerHashtable();
if (!exists(ChatRepository.ADMIN)) {
saveUser(new User(ChatRepository.ADMIN, keyParam));
log("Created admin user...");
}
if (new File(roomFolder + roomFilename).exists()) {
try {
roomTable = (IntegerHashtable)load(roomFolder + roomFilename);
}
catch (Exception excpt) {
log(excpt.toString());
createStandardRooms();
}
}
else {
createStandardRooms();
}
try {
roomTable = (IntegerHashtable)load(roomFolder + roomFilename);
}
catch (Exception excpt) {
log(excpt.toString());
createStandardRooms();
}
bannedIPs = new Vector();
try {
String content = new String();
StringTokenizer tokenizer;
char ch;
BufferedInputStream is = new BufferedInputStream(new FileInputStream(new File(BANNED_IP_FILENAME)));
while ((ch = (char)is.read()) != (char)-1) {
content += ch;
}
is.close();
tokenizer = new StringTokenizer(content, System.getProperty("line.separator"));
while(tokenizer.hasMoreTokens()) {
bannedIPs.addElement(tokenizer.nextToken().trim());
}
}
catch (Exception excpt) {
log(excpt.toString());
}
log("Listening on port " + portParam + "...");
log("Storage folder is " + storageFolder + "...");
log("Image folder is " + imageFolder + "...");
log("Room folder is " + roomFolder + "...");
log("Room filename is " + roomFilename + "...");
log("Log level is " + logLevel + "...");
log("Nr of banned ip-addresses read from " + BANNED_IP_FILENAME + ": " + bannedIPs.size());
serverThread = new Thread(this);
serverThread.start();
log("ChatServer up and running...");
}
catch (IOException excpt) {
log("IOException while starting ChatServer: " + excpt);
}
}
/**
* Runs a thread that listenes on the defined port to new socket connections.
* Starts a new thread for each Connection.
*/
public void run() {
Connection connection;
while (true) {
try {
connection = new Connection(this, listener.accept());
connection.start();
connectionVector.addElement(connection);
log("Opened connection to " + connection.getSocket().getInetAddress());
}
catch (IOException excpt) {
log("IOException while opening a new connection: " + excpt);
}
}
}
/**
* Handles incoming UserEvents or UserLoginRequests.
*
* @param object the UserEvent or UserLoginRequest
* @param connection the Connection that received the UserEvent
*/
public synchronized void handleUserEvent(Object object, Connection connection) {
ExistingUserLoginRequest existingUserLogin;
NewUserLoginRequest newUserLogin;
UserUpdateEvent userUpdate;
User user;
Room room;
Connection suspendedConnection;
String userName;
room = null;
if (object instanceof UserLoginRequest) {
if (bannedIPs.contains(connection.getIPAddress())) {
((UserLoginRequest)object).status = UserLoginRequest.DENIED;
((UserLoginRequest)object).statusString = "IP-Address has been banned";
log("Login for new user " + ((UserLoginRequest)object).user.getName() + " denied: Banned IP-Address");
send(object, connection);
}
else {
if (object instanceof ExistingUserLoginRequest) {
existingUserLogin = (ExistingUserLoginRequest)object;
log("Login for user " + existingUserLogin.user.getName() + " received");
if (!exists(existingUserLogin.user.getName()) || !correctPassword(existingUserLogin.user.getName(), existingUserLogin.user.getPassword())) {
existingUserLogin.status = UserLoginRequest.DENIED;
if (!exists(existingUserLogin.user.getName())) {
existingUserLogin.statusString = "User does not exist";
log("Login for user " + existingUserLogin.user.getName() + " denied: User does not exist");
}
else if (!correctPassword(existingUserLogin.user.getName(), existingUserLogin.user.getPassword())) {
existingUserLogin.statusString = "Wrong password";
log("Login for user " + existingUserLogin.user.getName() + " denied: Wrong password");
}
send(existingUserLogin, connection);
}
else {
log("Login for user " + existingUserLogin.user.getName() + " accepted");
existingUserLogin.status = UserLoginRequest.ACCEPTED;
existingUserLogin.statusString = "Everything ok";
existingUserLogin.user = loadUser(existingUserLogin.user.getName());
existingUserLogin.user.setPosition(getAvailablePosition(existingUserLogin.user.getRoom()));
if (isOnline(existingUserLogin.user.getName())) {
closeConnection(getConnection(getOnlineUserId(existingUserLogin.user.getName())));
}
handleAcceptedUserLoginRequest(existingUserLogin, connection);
}
}
else if (object instanceof NewUserLoginRequest) {
newUserLogin = (NewUserLoginRequest)object;
log("Login for user " + newUserLogin.user.getName() + " received");
if (exists(newUserLogin.user.getName())) {
newUserLogin.status = UserLoginRequest.DENIED;
newUserLogin.statusString = "User exists already";
log("Login for new user " + newUserLogin.user.getName() + " denied: Already existing");
send(newUserLogin, connection);
}
else {
newUserLogin.status = UserLoginRequest.ACCEPTED;
newUserLogin.statusString = "Everything ok";
log("Login for new user " + newUserLogin.user.getName() + " accepted");
newUserLogin.user.setPosition(getAvailablePosition(newUserLogin.user.getRoom()));
saveUser(newUserLogin.user);
handleAcceptedUserLoginRequest(newUserLogin, connection);
}
}
}
}
else if (object instanceof UserUpdateEvent) {
userUpdate = (UserUpdateEvent)object;
log("Update for user " + userUpdate.user.getName() + " received");
new UserUpdateThread(userUpdate, this, connection).start();
}
else if (object instanceof RoomEvent) {
RoomEvent roomEvent;
Enumeration userEnum;
if (object instanceof RoomUpdateEvent || object instanceof RoomCreateEvent) {
log("Handling room creation / update...");
if (object instanceof RoomUpdateEvent) {
roomEvent = (RoomUpdateEvent)object;
room = ((RoomUpdateEvent)object).room;
}
else {
roomEvent = (RoomCreateEvent)object;
room = ((RoomCreateEvent)object).room;
room.setId(getNextAvailableRoomId());
room.removeAllUsers();
if (roomExists(room.getName())) {
int i;
for (i = 1; roomExists(room.getName() + i); i++);
room.setName(room.getName() + i);
}
}
addRoom(room);
broadcast(roomEvent);
userEnum = onlineTable.elements();
while(userEnum.hasMoreElements()) {
user = (User)userEnum.nextElement();
if (user.getRoom() == room.getId() && !room.hasAccess(user.getName())) {
user.setRoom(0);
user.setPosition(getAvailablePosition(0));
addOnlineUser(user);
broadcast(new UserRoomEvent(user.getId(), user.getRoom(), user.getPosition()));
}
}
}
else if (object instanceof RoomRemoveEvent) {
room = getRoom(((RoomRemoveEvent)object).roomId);
if (room != null) {
removeRoom(room.getId());
broadcast(object);
}
}
saveRooms();
}
else if (object instanceof UserEvent) {
boolean broadcastExcluding;
broadcastExcluding = true;
user = getOnlineUser(((UserEvent)object).userId);
if (user != null) {
if (object instanceof UserPositionEvent) {
if (!collides(user.getRoom(), ((UserPositionEvent)object).userPosition, user.getId()))
user.setPosition(((UserPositionEvent)object).userPosition);
else {
((UserPositionEvent)object).userPosition = user.getPosition();
broadcastExcluding = false;
}
}
else if (object instanceof UserHeadingEvent)
user.setHeading(((UserHeadingEvent)object).userHeading);
else if (object instanceof UserMessageEvent) {
user.setMessage(((UserMessageEvent)object).userMessage);
log("User " + user.getName() + " says " + user.getMessage());
}
else if (object instanceof UserMoodEvent)
user.setMood(((UserMoodEvent)object).userMood);
else if (object instanceof UserRoomEvent) {
room = getRoom(((UserRoomEvent)object).roomId);
if (room != null) {
getRoom(room.getId()).removeUser(user.getName());
user.setRoom(room.getId());
room.addUser(user.getName());
user.setPosition(getAvailablePosition(room.getId()));
((UserRoomEvent)object).position = user.getPosition();
}
broadcastExcluding = false;
}
if (object instanceof UserLogoutEvent)
closeConnection(connection);
else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -