聊天室的公聊已经弄出来了`
但是私聊却无从下手`
用服务器端存取每个建立连接的客户只能得到对方的IP` 和连接的端口号` 存这些信息是用集合的HaspMap来存么?
公聊和私聊貌似可以通过在聊天信息前面加字符来区分`
但是我要选择和哪个用户进行私聊`该怎么和那个用户建立连接呢`
在服务器端也只能得到另一个用户的IP`和端口号`
我是自己一台机器实验`  IP都相同` 端口号不同`
在swing里面`  都是自定义的名字`
和某人聊天不可能就要输对方的IP` 和他与服务器连接的端口号吧`
私聊的具体思路是怎样的呢` 求解答`

解决方案 »

  1.   

    很简单。。
    知道飞鸽传书吗?既然你能在服务器得到所有建立连接的hasMap,那这个map发送并显示在客户端不就好了,客户端通过选择相应的用户,将信息和对话用户的特征发送到服务器,然后由服务器转发,结束。
      

  2.   

    公聊时 for 循环下0--254   ,私聊 ip
      

  3.   

    以前学习的时候看过一个聊天系统的例子,是个教学用案例,效率上不敢说多么好,他的思路大概是这样的:
    他是用线程来完成的,私聊时单独给这两个用户开一个线程。
    当用户A想与用户B私聊时,用户A在页面上点击B选择私聊,服务器接收到A的请求信息,里面包含所需要的信息。
    然后服务器向用户B发送一个信息,用户B接收到信息后反馈回服务器一个确认信息
    如果同意私聊,则服务器为A和B单独建立一个线程,在其中完成私聊的工作。不过我看的是J2EE版的,页面端貌似用的AJAX反转来接受服务器发给B用户的请求信息。但你要用swing写的话,可以写一个监听器来监听服务器的请求信息。
      

  4.   

    很简单啊  你都会公聊了  把服务器端存socket的map发给客户端,可以再客户端上添加个JList 让客户端自己选者和谁私聊 弄个私聊选者框 If选了 按发送的的时候就多发个socket给客户端 客户端就知道你和谁私聊了  
      

  5.   

    代码有点长,自己慢慢研究吧
    package com.myqq.frame;
    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.border.BevelBorder;
    import javax.swing.text.*;
    import com.myqq.MyQQ;
    import com.myqq.dao.Dao;
    import com.myqq.system.Resource;
    import com.myqq.userList.ChatTree;
    import com.myqq.userList.User;
    public class TelFrame extends JFrame {
    private Dao dao;
    private User user;
    private JTextPane receiveText = new JTextPane();
    private JScrollPane scrollPane = new JScrollPane();
    private JTextPane sendText = new JTextPane();
    private JScrollPane scrollPane_1 = new JScrollPane();
    private JSplitPane splitPane = new JSplitPane();
    private JButton sendButton = new JButton();
    private final JButton messageButton = new JButton();
    private JPanel panel = new JPanel();
    private final static Map<String, TelFrame> instance = new HashMap<String, TelFrame>();
    private final JCheckBox messageMode = new JCheckBox();
    private JToolBar toolBar = new JToolBar();
    private JToggleButton toolFontButton = new JToggleButton();
    private JButton toolFaceButton = new JButton();
    private JButton button = new JButton();
    private JButton button_3 = new JButton();
    private final JButton button_1 = new JButton();
    private final JPanel panel_5 = new JPanel();
    private JPanel panel_2 = new JPanel();
    private JPanel panel_1 = new JPanel();
    private JLabel label = new JLabel();
    private final JScrollPane scrollPane_2 = new JScrollPane();
    private final JLabel label_1 = new JLabel();
    private JPanel panel_3 = new JPanel();
    private byte[] buf;
    private DatagramSocket ss;
    private String ip;
    private DatagramPacket dp;
    private TelFrame frame;
    private ChatTree tree;
    private int rightPanelWidth = 148;
    public static synchronized TelFrame getInstance(DatagramSocket ssArg,
    DatagramPacket dp, ChatTree treeArg) {
    String tmpIp = dp.getAddress().getHostAddress();//获取用户地址
    if (!instance.containsKey(tmpIp)) { //判断集合中是否存在该用户的窗体
    TelFrame frame = new TelFrame(ssArg, dp, treeArg);//创建新窗体
    instance.put(tmpIp, frame); //更新窗体集合
    frame.receiveInfo(treeArg); //添加接受的信息
    if (!frame.isVisible()) { //如果窗体用于隐藏状态
    frame.setVisible(true);
    }
    frame.setState(JFrame.NORMAL);
    frame.toFront();
    return frame;
    } else { //如果集合中包含该用户的窗体
    TelFrame frame = instance.get(tmpIp); //从集合中获取窗体实例
    frame.setBufs(dp.getData());
    frame.receiveInfo(treeArg); //接受信息
    if (!frame.isVisible()) {
    frame.setVisible(true); //显示窗体
    }
    frame.setState(JFrame.NORMAL);
    frame.toFront();
    return frame;
    }
    } public TelFrame(DatagramSocket ssArg, DatagramPacket dpArg,
    final ChatTree treeArg) {
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    this.tree = treeArg;//获取用户列表对象
    ip = dpArg.getAddress().getHostAddress();//获取用户IP
    dao = Dao.getDao();//初始化Dao实例
    user = dao.getUser(ip);//获取用户对象
    frame = this; //获取窗体
    ss = ssArg;//获取数据服务对象
    dp = dpArg;//获取数据报
    buf = dp.getData();//获取数据报中的数据
    try {
    setBounds(200, 100, 521, 424);//设置窗体的大小、位置
    getContentPane().add(splitPane);//添加分割面板
    splitPane.setDividerSize(2);//设置面板分隔线大小
    splitPane.setResizeWeight(0.8);//定义面板竖向分割
    splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
    splitPane.setLeftComponent(scrollPane);
    scrollPane.setViewportView(getReceiveText());
    receiveText.setFont(new Font("宋体", Font.PLAIN, 12));
    receiveText.setInheritsPopupMenu(true);
    receiveText.setVerifyInputWhenFocusTarget(false);
    receiveText.setDragEnabled(true);
    receiveText.setMargin(new Insets(0, 0, 0, 0));
    receiveText.setEditable(false);
    getReceiveText().addComponentListener(new ComponentAdapter() {
    public void componentResized(final ComponentEvent e) {
    scrollPane.getVerticalScrollBar().setValue(
    getReceiveText().getHeight());
    }
    });
    getReceiveText().setDoubleBuffered(true); splitPane.setRightComponent(panel_2);
    panel_2.setLayout(new BorderLayout()); final FlowLayout flowLayout = new FlowLayout();
    flowLayout.setHgap(4);
    flowLayout.setAlignment(FlowLayout.LEFT);
    flowLayout.setVgap(0);
    panel_2.add(panel, BorderLayout.SOUTH);
    final FlowLayout flowLayout_1 = new FlowLayout();
    flowLayout_1.setVgap(3);
    flowLayout_1.setHgap(20);
    panel.setLayout(flowLayout_1); panel.add(sendButton);
    sendButton.setMargin(new Insets(0, 14, 0, 14));
    sendButton.addActionListener(new sendActionListener());
    sendButton.setText("发送"); panel.add(messageButton);
    messageButton.setMargin(new Insets(0, 14, 0, 14));
    messageButton.addActionListener(new MessageButtonActionListener());
    messageButton.setText("信史"); panel_2.add(panel_5, BorderLayout.NORTH);
    panel_5.setLayout(new BorderLayout());

    toolbarActionListener toolListener = new toolbarActionListener();
    panel_5.add(toolBar);
    toolBar.setBorder(new BevelBorder(BevelBorder.RAISED));
    toolBar.setFloatable(false);
    toolBar.add(toolFontButton);
    toolFontButton.addActionListener(toolListener);
    toolFontButton.setFocusPainted(false);
    toolFontButton.setMargin(new Insets(0, 0, 0, 0));
    ImageIcon toolbarFontIcon = new ImageIcon(
    MyQQ.class.getResource("/image/telFrameImage/toolbarImage/ToolbarFont.png"));
    toolFontButton.setIcon(toolbarFontIcon);
    toolFontButton.setToolTipText("设置字体颜色和格式");
    toolBar.add(toolFaceButton);
    toolFaceButton.addActionListener(toolListener);
    toolFaceButton.setToolTipText("选择表情");
    toolFaceButton.setFocusPainted(false);
    toolFaceButton.setMargin(new Insets(0, 0, 0, 0)); ImageIcon toolbarFaceIcon = new ImageIcon(
    MyQQ.class.getResource("/image/telFrameImage/toolbarImage/ToolbarFace.png"));
    toolFaceButton.setIcon(toolbarFaceIcon);
    toolBar.add(button);

    button.addActionListener(toolListener);
    button.setToolTipText("发送文件");
    button.setFocusPainted(false);
    button.setMargin(new Insets(0, 0, 0, 0));
    ImageIcon toolbarPictureIcon = new ImageIcon(
    MyQQ.class
    .getResource("/image/telFrameImage/toolbarImage/ToolbarPicture.png"));
    button.setIcon(toolbarPictureIcon);
    toolBar.add(button_3);
    button_3.addActionListener(toolListener);
    button_3.setToolTipText("选择聊天场景");
    button_3.setFocusPainted(false);
    button_3.setMargin(new Insets(0, 0, 0, 0));
    ImageIcon toolbarSceneIcon = new ImageIcon(
    MyQQ.class.getResource("/image/telFrameImage/toolbarImage/ToolbarScene.png"));
    button_3.setIcon(toolbarSceneIcon);
    System.currentTimeMillis();
    toolBar.add(messageMode);
    messageMode.setText("消息模式");
    panel_5.add(button_1, BorderLayout.EAST);
    button_1.addActionListener(new Button_1ActionListener());
    button_1.setMargin(new Insets(0, 0, 0, 0));
    button_1.setText("<");
    panel_2.add(panel_1);
    panel_1.setLayout(new BorderLayout());
    panel_1.add(scrollPane_1);
    scrollPane_1
    .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    sendText.setInheritsPopupMenu(true);
    sendText.addKeyListener(new SendTextKeyListener());
    sendText.setVerifyInputWhenFocusTarget(false);
    sendText.setFont(new Font("宋体", Font.PLAIN, 12));
    sendText.setMargin(new Insets(0, 0, 0, 0));
    sendText.setDragEnabled(true);
    sendText.requestFocus();
    scrollPane_1.setViewportView(getSendText()); addWindowListener(new TelFrameClosing(tree));//添加窗体事件监听器
    add(panel_3, BorderLayout.EAST);
    panel_3.setLayout(new BorderLayout());
    panel_3.add(scrollPane_2);
    scrollPane_2
    .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
    scrollPane_2.setViewportView(label);
    label.setIconTextGap(-1);
    String imgPath = MyQQ.class
    .getResource("/image/telFrameImage/telUserInfo.png")
    + "";
    label.setText("<html><body background='" + imgPath
    + "'><table width='" + rightPanelWidth
    + "'><tr><td>用户名:<br>&nbsp;&nbsp;" + user.getName()
    + "</td></tr><tr><td>主机名:<br>&nbsp;&nbsp;" + user.getHost()
    + "</td></tr>" + "<tr><td>IP地址:<br>&nbsp;&nbsp;" + user.getIp()
    + "</td></tr><tr><td colspan='2' height="
    + this.getHeight() * 2
    + "></td></tr></table></body></html>");//设置窗体右下的用户信息 panel_3.add(label_1, BorderLayout.NORTH);
    label_1.setIcon(new ImageIcon(MyQQ.class
    .getResource("/image/telFrameImage/telUserImage.png")));//设置窗体右边的用户图像
    } catch (Exception e) {
    e.printStackTrace();
    }
    setVisible(true); //显示窗体
    setTitle("与好友" + user + "聊天交流中");
    }
      

  6.   

    private void receiveInfo(final ChatTree tree) {// 接收信息
    if (buf.length > 0) {
    String rText = new String(buf).replace("" + (char) 0, "");
    String hostAddress = dp.getAddress().getHostAddress();
    String info = dao.getUser(hostAddress).getName();
    info = info + "  (" + new Date().toLocaleString() + ")";
    appendReceiveText(info, Color.BLUE);
    appendReceiveText(rText + "\n", null);
    }
    } class sendActionListener implements ActionListener {
    public void actionPerformed(final ActionEvent e) {
    String sendInfo = getSendInfo(); //获取信息发送文本
    if (sendInfo == null)
    return;
    insertUserInfoToReceiveText(tree); //插入用户信息
    appendReceiveText(sendInfo + "\n", null); //追加发送信息
    byte[] tmpBuf = sendInfo.getBytes();
    DatagramPacket tdp = null; //数据报
    try {//使用数据报将消息使用1111端口发送到指定ip
    tdp = new DatagramPacket(tmpBuf, tmpBuf.length,
    new InetSocketAddress(ip, 1111));
    ss.send(tdp);
    } catch (SocketException e2) {
    e2.printStackTrace();
    } catch (IOException e1) {
    e1.printStackTrace();
    JOptionPane.showMessageDialog(TelFrame.this, e1
    .getMessage());
    }
    sendText.setText(null);
    sendText.requestFocus();
    if (messageMode.isSelected())
    setState(ICONIFIED);
    }
    } class toolbarActionListener implements ActionListener {
    public void actionPerformed(final ActionEvent e) {
    JOptionPane.showMessageDialog(TelFrame.this, "功能隐藏");
    }
    } private final class TelFrameClosing extends WindowAdapter {
    private final JTree tree; private TelFrameClosing(JTree tree) {
    this.tree = tree;
    } public void windowClosing(final WindowEvent e) {
    tree.setSelectionPath(null);
    TelFrame.this.setState(ICONIFIED);
    TelFrame.this.dispose();
    }
    } private class MessageButtonActionListener implements ActionListener {// 信史按钮
    public void actionPerformed(final ActionEvent e) {
    try {
    Document doc = sendText.getDocument();
    String sendInfo = doc.getText(0, doc.getLength());
    if (sendInfo.equals("") || sendInfo == null) {
    JOptionPane.showMessageDialog(TelFrame.this, "不能发送空信息。");
    return;
    }
    insertUserInfoToReceiveText(tree);
    appendReceiveText(sendInfo, null);
    Resource.sendMessenger(user, sendInfo, frame);
    sendText.setText(null);
    sendText.requestFocus();
    } catch (BadLocationException e1) {
    e1.printStackTrace();
    }
    }
    }
    private class SendTextKeyListener extends KeyAdapter {
    public void keyPressed(KeyEvent e) {
    if (e.isControlDown() && e.getKeyCode() == 10)
    sendButton.doClick();
    else if (e.isShiftDown() && e.getKeyCode() == 10)
    messageButton.doClick();
    }
    }
    private class Button_1ActionListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
    panel_3.setVisible(!panel_3.isVisible());
    TelFrame.this.setVisible(true);
    }
    } public JButton getSendButton() {
    return sendButton;
    } public JTextPane getReceiveText() {
    return receiveText;
    } public void setBufs(byte[] bufs) {
    this.buf = bufs;
    } public String getSendInfo() {
    String sendInfo = "";
    Document doc = sendText.getDocument();
    try {
    sendInfo = doc.getText(0, doc.getLength());
    } catch (BadLocationException e) {
    e.printStackTrace();
    }
    if (sendInfo.equals("")) {
    JOptionPane.showMessageDialog(TelFrame.this, "不能发送空信息。");
    return null;
    }
    return sendInfo;
    } private void insertUserInfoToReceiveText(final ChatTree tree) {
    String info = null;
    try {
    String hostAddress = InetAddress.getLocalHost().getHostAddress();
    info = dao.getUser(hostAddress).getName();
    } catch (UnknownHostException e1) {
    e1.printStackTrace();
    }
    info = info + "  (" + new Date().toLocaleString() + ")";
    appendReceiveText(info, new Color(68, 184, 29));
    } public JTextPane getSendText() {
    return sendText;
    } public void appendReceiveText(String sendInfo, Color color) {
    Style style = receiveText.addStyle("title", null);
    if (color != null) {
    StyleConstants.setForeground(style, color);
    } else {
    StyleConstants.setForeground(style, Color.BLACK);
    }
    receiveText.setEditable(true);
    receiveText.setCaretPosition(receiveText.getDocument().getLength());
    receiveText.setCharacterAttributes(style, false);
    receiveText.replaceSelection(sendInfo + "\n");
    receiveText.setEditable(false);
    }
    }
      

  7.   

    刚刚好我写有,自己定义一个自己的CS协议不就行了http://download.csdn.net/source/1795293