📄 chatserver.java
字号:
import java.net.*;
import java.io.*;
import java.util.*;
/***************************************************************************
*
* Created by: Christian Ricci
* Started: March 17, 2000
* See also: chatadmin.java, chatapplet.java
*
* My chatserver program is designed to be used with a chat applet.
* However, there is no reason a person with a telnet client, connecting
* to the configured port couldn't utilize this application.
*
* There are three classes in this .java file: chatserver, broadcaster and
* listener.
*
***************************************************************************/
/***************************************************************************
*
* - chatserver, parent class. Listens for a connection on the comm
* port, passed in the argument list. An incoming connection causes
* this application to spawn a listener and broadcaster thread. There
* can be many simultaneous instances of this application running at
* any given time.
*
***************************************************************************/
public class ChatServer {
/***************************************************************************
* method: swrite -- rudimentary communications for the chatserver class
***************************************************************************/
public static void swrite(Socket sock, String str) throws Exception {
OutputStream outStream = sock.getOutputStream();
outStream.write(str.getBytes());
outStream.flush();
}
/***************************************************************************
* method: main
***************************************************************************/
public static void main(String args[]) throws Exception {
//
// Communications
//
Listener listenHandle = null;
Broadcaster broadHandle = null;
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(in);
ServerSocket server = new ServerSocket(Integer.parseInt(args[0]));
InputStream inStream;
BufferedReader inReader;
Socket sock;
//
// tmpVars and output strings
//
int counter = -1;
long tmpKey;
String name, systemOut;
System.out.println("Chat Server Running");
while (true) {
//
// Get, open new connection
//
sock = server.accept();
inReader = new BufferedReader(
new InputStreamReader(
sock.getInputStream()));
//
// Get name of participant
//
swrite(sock, "Name? ");
name = inReader.readLine();
tmpKey = (new Date()).getTime();
//
// Either start threads or add connections
//
if (counter == -1) {
broadHandle =
new Broadcaster(sock, in, tmpKey, name);
listenHandle =
new Listener(sock, out, tmpKey, name, broadHandle);
Thread t1 = new Thread(listenHandle);
Thread t2 = new Thread(broadHandle);
t1.start();
t2.start();
} else {
listenHandle.addSock(sock, tmpKey, name);
broadHandle.addSock(sock, tmpKey, name);
}
//
// Get current number of connections
//
counter = listenHandle.numSocks();
systemOut = "Added User : " + name + " (" + counter + ")";
System.out.println(systemOut);
}
}
}
/***************************************************************************
*
* - Broadcaster, output thread. Spawned by chatserver. Keeps a hash-
* table of the outputstreams associated with this each connection.
* A PipedInputStream passes communications to this thread class
* (spawned as a thread) from the Listener thread. When commun-
* ications passes thru this pipe, it enumerates thru the hashtable,
* sending the message and user name to each connection.
*
***************************************************************************/
class Broadcaster implements Runnable {
//
// Global vars
//
Hashtable sockHash = new Hashtable();
InputStream in;
private Socket sock;
private PrintWriter ostr;
/***************************************************************************
* method: constructor -- call addSock, setup InputStream
***************************************************************************/
public Broadcaster(Socket sock, InputStream in, long i, String name)
throws IOException {
this.in = in;
addSock(sock, i, name);
}
/***************************************************************************
* method: bCast -- Performs actual output (to a PrintWriter, see note).
***************************************************************************/
private void bCast(String s) throws IOException {
PrintWriter os;
for (Enumeration e = sockHash.elements() ; e.hasMoreElements() ;) {
os = (PrintWriter)e.nextElement();
os.println(s);
os.flush();
}
}
/***************************************************************************
* method: addSock -- Adds a new connection to the hashtable, bCast user.
***************************************************************************/
public void addSock(Socket sock, long i, String name)
throws IOException {
ostr = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
sockHash.put(Long.toString(i), ostr);
try {
bCast(name + " has joined.");
}
catch (Exception e) {
e.printStackTrace();
}
}
/***************************************************************************
* method: delSock -- Removes a connection in the hashtable.
***************************************************************************/
public void delSock(Object hKey) throws IOException {
sockHash.remove(hKey);
}
/***************************************************************************
* method: run -- Main thread activity, loopty
***************************************************************************/
public void run() {
BufferedReader istr = new BufferedReader(new InputStreamReader(in));
try {
while (true) {
bCast(istr.readLine());
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
/***************************************************************************
*
* - Listener, input thread. Like the Broadcaster thread, the Listener
* thread maintains a hashtable for each of the current connections.
* It enumerates thru the connections, checking for incoming messages
* and passes them through a PipedOutputStream to the Broadcaster
* thread.
*
***************************************************************************/
class Listener implements Runnable {
//
// Global vars
//
Hashtable sockHash = new Hashtable();
Hashtable nameHash = new Hashtable();
OutputStream out;
Broadcaster broadHandle;
private Socket sock;
private BufferedReader istr;
/***************************************************************************
* method: constructor -- call addSock, setup connection to Broadcaster
***************************************************************************/
public Listener(Socket sock, OutputStream out,
long i, String name, Broadcaster broadHandle) throws IOException {
this.broadHandle = broadHandle;
this.out = out;
addSock(sock, i, name);
}
/***************************************************************************
* method: addSock -- Adds a new connection to the hashtable.
***************************************************************************/
public void addSock(Socket sock, long i, String name) throws IOException {
istr = new BufferedReader(new InputStreamReader(sock.getInputStream()));
sockHash.put(Long.toString(i), istr);
nameHash.put(Long.toString(i), name);
}
/***************************************************************************
* method: numSocks -- Returns number of known connections.
***************************************************************************/
public int numSocks() {
return sockHash.size();
}
/***************************************************************************
* method: delSock -- Removes a connection in the hashtable. Output
* disconnect.
***************************************************************************/
public void delSock(Object hKey) throws IOException {
String systemOut;
String tmpName = (String)nameHash.get(hKey);
String tmpStr = tmpName + " has left.\n";
//
// Connection over to broadcaster thread
//
broadHandle.delSock(hKey);
//
// Close socket
//
BufferedReader tmpBfr = (BufferedReader)sockHash.get(hKey);
tmpBfr.close();
//
// Clean out hashtable entries
//
sockHash.remove(hKey);
nameHash.remove(hKey);
//
// Broadcast departure
//
out.write(tmpStr.getBytes());
systemOut = "Removed User : " + tmpName + " (" + nameHash.size() + ")";
System.out.println(systemOut);
}
/***************************************************************************
* method: run -- Main thread activity, loopty
***************************************************************************/
public void run() {
String tmpStr, tmpName, tmpInput;
String exitStr = new String("exit");
Object tmpKey;
BufferedReader tmpBfr;
try {
while (true) {
//
// Loop thru hash table looking for input that is ready to be
// posted.
//
for (Enumeration e = sockHash.keys() ; e.hasMoreElements() ;) {
tmpKey = e.nextElement();
tmpBfr = (BufferedReader)sockHash.get(tmpKey);
if (tmpBfr.ready()) {
tmpInput = tmpBfr.readLine();
if (tmpInput.compareToIgnoreCase(exitStr) == 0) {
delSock(tmpKey);
} else if (tmpInput != "") {
tmpName = (String)nameHash.get(tmpKey);
tmpStr = tmpName + " : " + tmpInput + "\n";
out.write(tmpStr.getBytes());
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -