最好是带界面的。      急  有思路和想法的也可以说说想法

解决方案 »

  1.   

    下面是代码,你可以参照package client;import java.awt.Container;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    import java.net.UnknownHostException;import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JTextField;public class LoginFrame extends JFrame{
    private JTextField name;
    private JTextField ip;
    private JButton ok,cancle;

    public Socket socket;

    public LoginFrame()
    {
    super("登录框");
    this.setSize(400,80);
    this.setLocation(100,100);

    name = new JTextField("昵称");
    ip = new JTextField("127.0.0.1");
    ok = new JButton("登录");
    cancle = new JButton("取消");
    ok.addActionListener(new listenEvent());
    cancle.addActionListener(new listenEvent());

    addcomponettocontainer();
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);

    } public void addcomponettocontainer()
    {
    Container c = this.getContentPane();
    c.setLayout(null);

    name.setBounds(10,10,100,30);
    ip.setBounds(120,10,100,30);
    ok.setBounds(230,10,70,30);
    cancle.setBounds(310,10,70,30);

    c.add(name);
    c.add(ip);
    c.add(ok);
    c.add(cancle);

    this.setVisible(true);
    this.setResizable(false);
    }

    public class listenEvent implements ActionListener
    { public void actionPerformed(ActionEvent event) {
    // TODO Auto-generated method stub
    if(event.getSource()==ok)
    {
    String n = name.getText().trim();
    String i = ip.getText().trim();
    if("".equals(n)||"".equals(i))
    {
    JOptionPane.showMessageDialog(null,"昵称、IP不能够为空!","错误",JOptionPane.OK_OPTION);
    }
    else{login(n,i);}
    }
    if(event.getSource()==cancle)
    {
    name.setText("");
    ip.setText("");
    }
    }

    }

    public void login(String name,String ip)
    {

    try {
    socket = new Socket(ip,7777);
    DataOutputStream out = new DataOutputStream(socket.getOutputStream());
    out.writeUTF(name);
    out.flush();//强制输出缓存中的内容
    //out.close();
    new ClientFrame(name,socket);
    destroywindow();
    } catch (UnknownHostException e) {
    JOptionPane.showMessageDialog(null,"找不到主机地址(IP错误/网络故障)!","错误",JOptionPane.OK_OPTION);

    } catch (IOException e) {

    }
    }

    public void destroywindow()
    {
    this.dispose();
    }

    public static void main(String[] args)
    {
    new LoginFrame();
    }
    }
    package client;import java.awt.Color;
    import java.awt.Container;
    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.Socket;
    import java.util.Date;import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;public class ClientFrame extends JFrame{
    private JTextArea allmsg;
    private JTextField welcome,copyright,chatmsg;
    private JButton send;
    private JScrollPane js;
        private boolean isConnected = true;

    public DataOutputStream out;
    public DataInputStream in;

    public Socket s = null;

    String nic;  /*  -- 保存用户昵称 --*/


    /**
     * 初始化客户端资源
     * 1.获取从LoginFrame传递过来的参数
     * 2.初始化界面元素
     * 3.初始化通信所需要的资源 EG:输入/输出流(DataInputStream/DataOutputStream)
     * */
    public ClientFrame(String name,Socket socket)
    {
    this.setSize(310,660);
    this.setLocation(290,50);
            this.setTitle("聊天室客户端<"+name+">");/*  -- 指定窗口的标题 --*/
            
    this.s = socket;/*  -- 接收从LoginFrame中传递过来的Socket --*/

    this.nic = name+" 说: ";


    welcome = new JTextField(" < "+name+" >欢迎您来到聊天室 ",100);
    welcome.setBackground(Color.blue);
    welcome.setEnabled(false);

    copyright = new JTextField("             -----  all copyright @ TOP-king  -----");
    copyright.setEnabled(false);

    allmsg = new JTextArea();
    allmsg.setEditable(false);
    allmsg.append("                  系统消息: 欢迎登录在线聊天室 \n");

    js = new JScrollPane(allmsg);//为JTextArea添加滚动条

    chatmsg = new JTextField("在此输入聊天信息");
    chatmsg.addActionListener(new listen());

    send = new JButton("发送");
    send.addActionListener(new listen());/*  -- 添加事件监听器 --*/

    try {
    out = new DataOutputStream(s.getOutputStream());
    in = new DataInputStream(s.getInputStream());
    } catch (IOException e) {JOptionPane.showMessageDialog(null, "系统异常","错误",JOptionPane.OK_CANCEL_OPTION);}

    addcomponettocontainer(); /*  -- 当用户关闭窗口时进行相关的处理 eg:Socket Data(Input/Output)Stream 的关闭--*/
    this.addWindowListener(new WindowAdapter(){
    public void windowClosing(WindowEvent we)
    {
    sendmsg("quit&logout");/*  -- 向服务器端发送关闭信息 --*/
    isConnected = false;
    destory();/*  -- 销毁窗口资源 --*/
    }
    });

    new Thread(new linread()).start();/*  -- 启动读取信息线程 --*/

    }

    public void addcomponettocontainer()
    {
    Container c = this.getContentPane();
    c.setLayout(null);

    welcome.setBounds(75,10,150,20);
    js.setBounds(10,50,280,500);
    chatmsg.setBounds(10,560,180,30);
    send.setBounds(220,560,70,30);
    copyright.setBounds(10,600,280,20);

    c.add(welcome);
    c.add(js);
    c.add(chatmsg);
    c.add(send);
    c.add(copyright);

    this.setVisible(true);
    this.setResizable(false);
    }

    class listen implements ActionListener
    { public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub
    if(e.getSource()==send||e.getSource()==chatmsg)
    {
       String msg = chatmsg.getText().trim();
       if("".equals(msg))
       {
       JOptionPane.showMessageDialog(null,"发送信息不能为空!","错误",JOptionPane.OK_OPTION);
       }
       else
       {sendmsg((new Date()).toLocaleString()+"\n"+nic+msg+"\n");chatmsg.setText("");}
    }
    }
    }

    /*  -- 向服务器端发送信息 --*/
    public void sendmsg(String m)
    {
     System.out.println("ClientFrame.sendmsg" + isConnected);
    if(isConnected)//如果socket的输出流没关闭
    {
    try {
    out.writeUTF(m);
    } catch (IOException e) {
    JOptionPane.showMessageDialog(null,"发送信息失败!(系统异常)","错误",JOptionPane.OK_OPTION);
    }
    }
    else
    {
    JOptionPane.showMessageDialog(null,"发送信息失败!(服务器关闭/网络故障)","错误",JOptionPane.OK_OPTION);
    }
    } /*  -- 读取信息线程 --*/
    class linread implements Runnable
    {
    public void run()
    {
    read();
    }

    public void read()
    {     System.out.println("ClientFrame.read:   " + isConnected);
    while(isConnected)
    {
    try {
    String msg = in.readUTF();
    System.out.println("ClientFrame.read:   " + isConnected);
    if("SYSTEM_CLOSED".equals(msg))
    {
    JOptionPane.showMessageDialog(null,"读取消息失败(服务器关闭/网络故障)!","错误",JOptionPane.OK_OPTION);
    isConnected = false;
    }
    else
      allmsg.append(msg+"\n");
    } catch (IOException e) {
    }
    }//end while
    JOptionPane.showMessageDialog(null,"读取消息失败(服务器关闭/网络故障)!","错误",JOptionPane.OK_OPTION);
    }//end read()
    }

    public void destory()
    {
    try {
    this.out.close();
    this.in.close();
    this.s.close();
    } catch (IOException e) {
    }
    this.dispose();
    }
    }
      

  2.   

    下面是服务端代码
    package server;import java.awt.Container;
    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.ArrayList;
    import java.util.Date;import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;public class ServerFrame extends JFrame { private JTextArea allmsg;
    private JTextField currnum, totalnum, copyright, chatmsg;
    private JButton send;
    private JScrollPane js;
    int num1, num2, port;/* -- num1:当前在线人数 num2:总上线人数 port:服务端口号 -- */ private ServerSocket ss; ArrayList lists;// 存放所有在线用户 public ServerFrame() {
    super("聊天室服务器端");
    this.setSize(310, 660);
    this.setLocation(200, 50); lists = new ArrayList(); num1 = num2 = 0;
    port = 7777; currnum = new JTextField(" 当前在线人数: " + num1);
    currnum.setEnabled(false); totalnum = new JTextField(" 上线总人数: " + num2);
    totalnum.setEnabled(false); copyright = new JTextField(
    "             -----  all copyright @ TOP-king  -----");
    copyright.setEnabled(false); allmsg = new JTextArea();
    allmsg
    .append("                   --------------- 系统消息 --------------\n");
    allmsg.setEditable(false);
    allmsg.setLineWrap(true); // 允许自动换行 js = new JScrollPane(allmsg);// 为JTextArea添加滚动条 chatmsg = new JTextField("在此输入系统信息");
    chatmsg.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) {
    String str = chatmsg.getText().trim();
    if (!"".equals(str)) {
    sendmsg((new Date()).toLocaleString() + " -- 系统消息: " + str);
    chatmsg.setText("");
    } else
    JOptionPane.showMessageDialog(null, "消息不能为空", "错误",
    JOptionPane.OK_OPTION);
    chatmsg.setText("");/* -- 发送信息后,将输入栏中的信息清空 -- */
    }
    }); send = new JButton("发送");
    send.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) {
    String str = chatmsg.getText().trim();
    if (!"".equals(str)) {
    sendmsg((new Date()).toLocaleString() + " -- 系统消息: " + str);
    chatmsg.setText("");
    } else
    JOptionPane.showMessageDialog(null, "消息不能为空", "错误",
    JOptionPane.OK_OPTION);
    chatmsg.setText("");/* -- 发送信息后,将输入栏中的信息清空 -- */
    }
    }); addcomponettocontainer();
    this.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent we) {
    sendmsg("SYSTEM_CLOSED");/* -- 向客户端发送服务器关闭信息 -- */
    destory();
    }
    });
    start(); /* -- 启动连接服务 -- */ } public void addcomponettocontainer() {
    Container c = this.getContentPane();
    c.setLayout(null); currnum.setBounds(20, 15, 130, 20);
    totalnum.setBounds(155, 15, 125, 20);
    js.setBounds(10, 50, 280, 500);
    chatmsg.setBounds(10, 560, 180, 30);
    send.setBounds(220, 560, 70, 30);
    copyright.setBounds(10, 600, 280, 20); c.add(currnum);
    c.add(totalnum);
    c.add(js);
    c.add(chatmsg);
    c.add(send);
    c.add(copyright); this.setVisible(true);
    this.setResizable(false);
    } /**
     * start()方法监听客户的连接 并且保存客户端的相关信息EG:用户昵称、用户所使用的Socket
     * 用户连接到服务器成功之后,将其保存到用户列表中,并为该用户启动一个线程用于通信
     */
    public void start() {
    boolean isStarted = false;/* -- 用于标记服务器是否已经正常启动 -- */
    try {
    this.ss = new ServerSocket(port);
    isStarted = true;
    this.allmsg.append((new Date()).toLocaleString()
    + "    服务器启动 @ 端口: " + port + "\n");
    while (isStarted) {
    Socket client = this.ss.accept(); /* -- 监听客户端的连接 -- */
    DataInputStream in = new DataInputStream(client
    .getInputStream());
    String name = in.readUTF();
    user u = new user();
    u.name = name;
    u.socket = client;
    lists.add(u); // 将该用户加到列表中去
    num1++;
    num2++;
    currnum.setText(" 当前在线人数: " + num1);
    totalnum.setText(" 上线总人数: " + num2);
    this.allmsg.append((new Date()).toLocaleString() + " : "
    + u.name + " 登录 \n");
    new Thread(new ClientThread(u)).start();/* -- 为该用户启动一个通信线程 -- */
    } } catch (IOException e) {
    System.out.println("服务器已经启动......");
    System.exit(0);
    }
    } /**
     * 通信线程主要功能包括: 1.监听客户端输入的信息 2.将接收到的信息转发给其他用户
     */
    class ClientThread implements Runnable {
    user user = null;
    boolean isConnected = true;
    DataInputStream dis = null;
    DataOutputStream dos = null; public ClientThread(user u) {
    this.user = u;
    try {
    this.dis = new DataInputStream(this.user.socket
    .getInputStream());
    this.dos = new DataOutputStream(this.user.socket
    .getOutputStream());
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    } public void run() {
    readmsg();
    } /* -- 读取客户的聊天信息 -- */
    public void readmsg() {
    while (isConnected) {
    try {
    String msg = dis.readUTF();
    if ("quit&logout".equals(msg))// 当用户关闭客户端窗口时,发送quit字符串
    // 表示用户已经退出
    {
    num1--;
    try {
    this.dis.close();
    this.dos.close();
    this.user.socket.close();
    this.isConnected = false;
    } catch (IOException ioe) {
    ioe.printStackTrace();
    } finally {
    this.isConnected = false;
    if (dis != null)
    this.dis.close();
    if (dos != null)
    this.dos.close();
    if (this.user.socket != null)
    this.user.socket.close();
    }
    lists.remove(this.user);// 从列表中删除该用户
    currnum.setText(" 当前在线人数: " + num1);
    allmsg.append((new Date()).toLocaleString() + "  : "
    + this.user.name + "  退出\n");
    } else
    sendmsg(msg);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    } } /* -- 将信息进行转发 -- */
    public void sendmsg(String msg) {
    user us = new user();
    DataOutputStream os = null;
    if (lists.size() > 0) {
    for (int i = 0; i < lists.size(); i++) {
    us = (user) lists.get(i);
    try {
    os = new DataOutputStream(us.socket.getOutputStream());
    os.writeUTF(msg);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    } else
    JOptionPane.showMessageDialog(null, "当前无用户在线。发送消息失败", "失败",
    JOptionPane.OK_OPTION);
    } public void destory() {
    try {
    this.ss.close();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    this.dispose();
    } public static void main(String[] args) {
    new ServerFrame();
    }}
    package server;import java.net.*;public class user {  String name;
     Socket socket;
    }