package tcp;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.Hashtable;
public class ChatServer1 {
private ServerSocket ss;
private Socket s;
private DataInputStream dis;
private DataOutputStream dos;
private TextArea ta;// 文本域
private TextField tf;// 文本框
// 把每个用户的名称及他的内容以键-值的方式存储在Hashtable中
private Hashtable<String, DataOutputStream> userTable = new Hashtable<String, DataOutputStream>();
public static void main(String args[]) {
ChatServer1 ts = new ChatServer1();
ts.createUI();// 创建界面
ts.connect();// 创建连接并启动线程
}
// 创建界面
public void createUI() {
Frame f = new Frame("服务端");
ta = new TextArea();
ta.setEditable(false);
tf = new TextField();
Button send = new Button("发送");
// 面板
Panel p = new Panel();
// 面板设置布局管理器
p.setLayout(new BorderLayout());
p.add(tf, "Center");
p.add(send, "East");
f.add(ta, "Center");
f.add(p, "South");
MyServerListener1 listener = new MyServerListener1(this);
send.addActionListener(listener);// 按钮注册事件监听器
tf.addActionListener(listener);// 文本框注册事件监听器,按enter同步文本框内容到文本域
f.setSize(400, 400);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
transmitMessage("服务端已经关闭");//关闭服务端之前,先关闭各客户端
ChatServer1.this.close();// 关闭所有流
System.exit(0);
}
});
}
// 显示单个用户的行为给其他用户看
public void transmitMessage(String msg) {
Collection<DataOutputStream> doses = userTable.values();// 返回此映射中包含的值的
// Collection
// 视图。
DataOutputStream dos;
for (DataOutputStream o : doses) {
dos = o;
try {
dos.writeUTF(msg);
} catch (Exception e) {
}
}
}
// 创建连接,启动服务端,并启动线程
public void connect() {
String name;
try {
ss = new ServerSocket(8888);
while (true) {
s = ss.accept();
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream());
name = dis.readUTF();// 每当一个用户连接的时候都会输入自己的用户名
userTable.put(name, dos);
// 启动线程
MyServerReader1 reader = new MyServerReader1(name, dis,
userTable, this);
reader.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 统一关闭流操作
public void close() {
try {
dis.close();
dos.close();
s.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 一些get方法
public Hashtable<String, DataOutputStream> getUserTable() {
return userTable;
}
public void setUserTable(Hashtable<String, DataOutputStream> userTable) {
this.userTable = userTable;
}
public DataInputStream getDataInputStream() {
return dis;
}
public DataOutputStream getDataOutputStream() {
return dos;
}
public TextArea getTextArea() {
return ta;
}
public TextField getTextField() {
return tf;
}
}
// ***************************************************************************
// 创建事件监听类......用于处理自己写信息的操作
class MyServerListener1 implements ActionListener {
private ChatServer1 server;
private Hashtable<String, DataOutputStream> userTable;
public MyServerListener1(ChatServer1 server) {
this.server = server;
this.userTable = server.getUserTable();
}
public void actionPerformed(ActionEvent e) {
// 返回此映射中包含的值 Collection 视图,获取在线人数。
Collection<DataOutputStream> doses = userTable.values();
TextField tf = server.getTextField();
String info = tf.getText();
// 将给定文本追加到文本区的当前文本。
server.getTextArea().append(
"俺是服务端: " + info + "\t" + "在线人数" + doses.size() + "人" + "\n");
transmitMessage1(info, "服务端");
/*
* if (info.equals("bye")) { server.close();// 关闭所有的流操作
* System.exit(0);// 然后退出程序 }
*/
tf.setText("");
tf.requestFocus();// 请求此 Component 获取输入焦点
}
// 显示服务端的行为给其他用户看
public void transmitMessage1(String msg, String name) {
Collection<DataOutputStream> doses = userTable.values();// 返回此映射中包含的值的
// Collection
// 视图。
DataOutputStream dos;
for (DataOutputStream o : doses) {
dos = o;
try {
dos.writeUTF(name + ":" + msg);
} catch (Exception e) {
}
}
}
}
// **************************************************************************************
// 线程类......用于读取信息的操作
class MyServerReader1 extends Thread {
private ChatServer1 server;
private String name;
private DataInputStream dis;
private Hashtable<String, DataOutputStream> userTable;
public MyServerReader1(String name, DataInputStream dis,
Hashtable<String, DataOutputStream> userTable, ChatServer1 server) {
this.server = server;
this.name = name;
this.dis = dis;
this.userTable = userTable;
}
public void run() {
// 返回此映射中包含的值 Collection 视图。
Collection<DataOutputStream> doses = userTable.values();
String info;
DataInputStream dis = server.getDataInputStream();
TextArea ta = server.getTextArea();
try {
transmitMessage("--上线了!!!--", name);
ta.append(name + ":上线了!!" + "\t" + "在线人数" + doses.size() + "人"
+ "\n");
while (true) {
info = dis.readUTF();
if (info.equals("bye")) {
DataOutputStream dos = (DataOutputStream) (userTable
.get(name));
Thread.sleep(1000);
dos.close();// 要退出用户的必须关闭流的操作
dis.close();
userTable.remove(name);// 并把用退出用户从在线用户列表中移除
transmitMessage("--下线!!!--", name);
ta.append(name + ":下线了!!" + "\t" + "在线人数" + doses.size()
+ "人" + "\n");
break;
} else if (info.length() > 0) {
transmitMessage(info, name);
ta.append(name + ":" + info + "\t" + "在线人数" + doses.size()
+ "人" + "\n");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 显示单个用户的行为给其他用户看
public void transmitMessage(String msg, String name) {
Collection<DataOutputStream> doses = userTable.values();// 返回此映射中包含的值的
// Collection
// 视图。
DataOutputStream dos;
for (DataOutputStream o : doses) {
dos = o;
try {
dos.writeUTF(name + ":" + msg);
} catch (Exception e) {
}
}
}
}