本人大概思路是 服务端 为每个用户单独分配一个接受消息的线程(当接到后将信息群发给所有连接的客户端), 再主线程上一直是等待接受下一个客户端的连接。
可就有个问题就是 当第一个客户端跟我连接成功后, 第2个再连的时候它会不会把之前的那个连接覆盖掉 因为端口毕竟只一个 急等 !!!!!!!
可就有个问题就是 当第一个客户端跟我连接成功后, 第2个再连的时候它会不会把之前的那个连接覆盖掉 因为端口毕竟只一个 急等 !!!!!!!
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;public class ChatServer extends Frame{
TextArea ta=new TextArea(20,80);//消息接收显示框
TextField tf=new TextField(60);//消息编写框
Button b=new Button(" 发 送 ");//发送消息按钮
Button start=new Button("启动服务");
ServerSocket server=null;
TextField portInput=new TextField("4444",2);
List userList=new List(21);
Button refreshUser=new Button(" 刷 新 用 户 列 表 ");
//Vector users=new Vector();
Hashtable hash=new Hashtable();
public ChatServer() {
super("聊天室服务器端");
ta.setBackground(new Color(1,60,160));
ta.setForeground(Color.white);
ta.setEditable(false);
//this.add(ta,BorderLayout.NORTH);
Panel p=new Panel(new FlowLayout(FlowLayout.LEFT));
p.add(new Label("Port"));
p.add(portInput);
p.add(start);
p.add(tf);
p.add(b); Panel pleft=new Panel(new BorderLayout());
pleft.add(ta,BorderLayout.NORTH);
pleft.add(p,BorderLayout.CENTER);
Panel pright=new Panel(new BorderLayout());
userList.setBackground(new Color(1,60,60));
userList.setForeground(Color.white); Panel pb=new Panel();
pb.add(refreshUser); pright.add(pb,BorderLayout.CENTER);
pright.add(userList,BorderLayout.NORTH);
//this.add(p,BorderLayout.CENTER);
this.add(pleft,BorderLayout.CENTER);
this.add(pright,BorderLayout.EAST);
this.setResizable(false);//不能调节窗口大小
MyActionListener lis=new MyActionListener();
this.addWindowListener(lis);
start.addActionListener(lis);
b.addActionListener(lis);
refreshUser.addActionListener(lis);
this.pack();
this.show();
}
public static void main(String[] args) {
ChatServer s = new ChatServer();
}
public void showUserList(){
userList.clear();
Collection col=hash.keySet();
Iterator it=col.iterator();
int i=0;
while(it.hasNext()){
String name=(String)it.next();
userList.add(name);
i++;
}
this.setTitle("聊天室服务器端-当前在线"+i+"位用户");
}
//广播消息
public void broadCast(String msg) { Collection col=hash.values();
Iterator it=col.iterator();
while(it.hasNext()){
try {
Socket c = (Socket) it.next();
OutputStream os = c.getOutputStream();
PrintStream ps = new PrintStream(os);
ps.println(msg);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
//内部类,做事件处理
class MyActionListener extends WindowAdapter implements ActionListener{
Service service = new Service();
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if(cmd.equals("启动服务")){
String tmp=null;
try {
if(server!=null&&!server.isClosed())
server.close();
server = new ServerSocket(Integer.parseInt(portInput.getText()));
service.start();
tmp="[系统消息]:服务器启动成功\n";
} catch (Exception ex) {
tmp="[系统消息]:服务器启动失败\n";
//ex.printStackTrace();
}
ta.setText(tmp);
}
if(cmd.equals(" 发 送 ")){
broadCast("[版主]:"+tf.getText());
ta.append("[版主]:"+tf.getText()+"\n");
}
if(cmd.equals(" 刷 新 用 户 列 表 "))
showUserList();
}
public void windowClosing(WindowEvent e){
System.exit(0);//关闭窗口,退出程序
}
}
//接受连接客户端
class Service extends Thread {
public void run() {
while (true) {
try {
Socket client = server.accept();
ServiceUnit unit=new ServiceUnit(client);
unit.start(); Thread.sleep(100);
} catch (Exception ex) {
//ex.printStackTrace();
break;
}
}
}
}
//接受客户端聊天信息
class ServiceUnit extends Thread{
Socket client = null;
InputStream is = null;
BufferedReader br = null;
String msg = null;
String returnMsg=null;
int index=0;
String name=null;
public ServiceUnit(Socket c) {
client=c;
}
public void run() {
//users.add(client);
while (true) {
try {
is = client.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
msg = null; while ((msg = br.readLine()) != null) {
index++;
if (index == 1) {
name = msg+"-"+client.getInetAddress().getHostAddress();
ta.append("[" + name + "]进入聊天室\n");
returnMsg = "[版主]:欢迎" + name + "进入聊天室";
//把登陆的用户和信息封装到一个hashtable(K,V)里
hash.put(name,client);
showUserList();
} else {
ta.append("[" + name + "]:" + msg + "\n");
returnMsg = "[" + name + "]:" + msg;
}
broadCast(returnMsg);
}
Thread.sleep(100);
} catch (Exception ex) {
//ex.printStackTrace();
break;
}
}
hash.remove(name);
broadCast("[" + name + "]走了");
ta.append("[" + name + "]走了\n");
showUserList();
}
}
}
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;public class ChatClient extends Frame{
TextArea ta=new TextArea(10,40);//消息接收显示框
TextField tf=new TextField(20);//消息编写框
TextField ipInput=new TextField("localhost",10);//IP输入框
TextField portInput=new TextField("4444",2);//输入端口
TextField nameInput=new TextField("user",5);//输入端口
Button conn=new Button("登录");
Button b=new Button("发送");//发送消息按钮
Socket client=null;
public ChatClient() {
super("聊天室客户端");
ta.setBackground(new Color(1,60,60));
ta.setForeground(Color.white);
ta.setEditable(false);
this.add(ta,BorderLayout.NORTH);
Panel p=new Panel();
p.add(new Label("IP"));
p.add(ipInput);
p.add(new Label("Port"));
p.add(portInput);
p.add(new Label("Name"));
p.add(nameInput);
p.add(conn);
p.add(tf);
p.add(b);
this.add(p,BorderLayout.CENTER);
this.setResizable(false);//不能调节窗口大小
MyActionListener lis=new MyActionListener();
this.addWindowListener(lis);
conn.addActionListener(lis);//给登录按钮添加事件处理器
b.addActionListener(lis);
this.pack();
this.show();
}
public static void main(String[] args) {
ChatClient cc = new ChatClient();
}
//内部类,做事件处理
class MyActionListener extends WindowAdapter implements ActionListener{
public void actionPerformed(ActionEvent e){
String cmd=e.getActionCommand();
if(cmd.equals("登录")){
String tmp=null;
try {
//创建到指定服务器的socket连接
client = new Socket(ipInput.getText(),Integer.parseInt(portInput.getText()));
tmp="[系统消息]:连接成功\n";
ReadMsg reader=new ReadMsg();
reader.start();
} catch (Exception ex) {
tmp="[系统消息]:连接失败\n";
}
ta.setText(tmp);//显示登录成功或失败信息
}
if(cmd.equals("发送")){
OutputStream os =null;
PrintStream ps =null;
try {
os = client.getOutputStream();
ps = new PrintStream(os);
ps.println(tf.getText());
} catch (Exception ex1) {
//ex1.printStackTrace();
ta.append("[系统消息]:发送失败\n");
}
}
}
public void windowClosing(WindowEvent e){
System.exit(0);//关闭窗口,退出程序
}
} //内部类,负责接收从服务器上转发回的消息
class ReadMsg extends Thread{
public void run(){
InputStream is =null;
BufferedReader br=null;
String msg = null;
OutputStream os = null;
PrintStream ps = null;
try {
is = client.getInputStream();
br = new BufferedReader(new InputStreamReader(is)); //客户端连接成功后,首先发送昵称过去
os = client.getOutputStream();
ps = new PrintStream(os);
ps.println(nameInput.getText());
} catch (Exception ex1) {
//ex1.printStackTrace();
}
while(true){
try {
while ((msg = br.readLine()) != null) {
ta.append(msg + "\n");
}
} catch (Exception ex) {
//ex.printStackTrace();
}
}
}
}
}