代码太长,放不下,我将分两此分别贴出,这个代码主要是实现像QQ一样的简单的通讯功能。
这是第一部分代码
package jxtatest;
import net.jxta.peergroup.PeerGroup;
import net.jxta.peergroup.PeerGroupID;
import net.jxta.peergroup.NetPeerGroupFactory;
import net.jxta.exception.PeerGroupException;
import net.jxta.protocol.ModuleClassAdvertisement;
import net.jxta.protocol.ModuleSpecAdvertisement;
import net.jxta.protocol.ModuleImplAdvertisement;
import net.jxta.protocol.PeerGroupAdvertisement;
import net.jxta.protocol.PipeAdvertisement;
//import net.jxta.protocol.DiscoveryResponseMsg;
import net.jxta.document.AdvertisementFactory;
//import net.jxta.document.StructuredTextDocument;
//import net.jxta.document.StructuredDocument;
//import net.jxta.document.StructuredDocumentFactory;
import net.jxta.document.MimeMediaType;
import net.jxta.document.Advertisement;
import net.jxta.document.TextDocument;
import net.jxta.discovery.DiscoveryService;
//import net.jxta.discovery.DiscoveryListener;
import net.jxta.pipe.PipeService;
import net.jxta.pipe.InputPipe;
import net.jxta.pipe.OutputPipe;
import net.jxta.pipe.PipeMsgListener;
import net.jxta.pipe.PipeMsgEvent;
import net.jxta.id.IDFactory;
import net.jxta.platform.ModuleClassID;
//import net.jxta.platform.ModuleSpecID;
import net.jxta.endpoint.Message;
import net.jxta.endpoint.MessageElement;
import net.jxta.endpoint.StringMessageElement;
import net.jxta.endpoint.TextDocumentMessageElement;
import java.net.URL;
import java.util.Enumeration;
import java.util.Vector;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
//import javax.swing.event.*;
import javax.swing.table.*;
/**
 * 
 *
 */
public class MyChatGroup implements PipeMsgListener, ActionListener{
private PeerGroup netGP = null;//默认组
private PeerGroup myGroup = null;//自己创建的组
private DiscoveryService discoverySvc = null;
private PipeService pipeSvc = null;
private PipeAdvertisement pipeAdv = null;
private PipeAdvertisement pipePrivateAdv = null;
    private InputPipe inPipe = null;
private OutputPipe outPipe = null;
private String name = "MainChatRoom";
private long findGroupTimeOut = 3 * 1000;
private long findGroupTryTimes = 3;
private long findPipeTimeOut = 3 * 1000;
private long findPipeTryTimes = 3;
private long createPipeTimeOut = 6 * 1000;
private int findPipeCount = 200;
private Vector<Vector<Object>> pipes = new Vector<Vector<Object>>();
private Vector<String> pipeId = new Vector<String>();
private Vector<Vector<Object>> pipesPrivate = new Vector<Vector<Object>>();
private Vector<String> list = new Vector<String>();
private Vector<String> pipePrivateId = new Vector<String>();

private JButton jbSend = new JButton("发送");
private JButton jbRefresh = new JButton("刷新");
private JButton jbPrivateChat = new JButton("私聊");
private JTextArea jtaHistoryContent = new JTextArea();
private JTextArea jtaPrivateContent = new JTextArea();
private JTextField jtfContent = new JTextField();
private JTable jlTable = null;

private PipeMsgListener privateMsgListener =null;
private String advPrivateFileName = "privatepipe.adv";

static String groupURL =
              "jxta:uuid-04B8173E42A445F0AF6BBB486CEA53D102";

public MyChatGroup(){
jlTable = new JTable(new DefaultTableModel(){  //创建Table的默认模型。
                 public int getRowCount(){//设置Table行数,list的大小作为Table的行数。
                  return list.size();
                 }
                 
                 public int getColumnCount(){ //返回Table中的列数,Table列数为1
                  return 1;
                 }
                 
                 public Object getValueAt(int row, int col){ //返回 row 和 column 处单元格的属性值
                  return list.get(row);
                 }
                 
                 public boolean isCellEditable(int row, int col){
                  return false;    //设置Table不能被编辑
                 }
                 
                 public String getColumnName(int col){   //返回列名称
                  return "在线列表";
                 }
               });
jbSend.addActionListener(this);//为发送按钮注册监听器
jbRefresh.addActionListener(this);
jbPrivateChat.addActionListener(this);
jtaHistoryContent.setEditable(false);
jtaHistoryContent.setLineWrap(true);//获取文本区的换行策略。如果设置为 true,则当行的长度大于所
                                      //分配的宽度时,将换行。如果设置为 false,则始终不换行。 
jtaPrivateContent.setEditable(false);
privateMsgListener = new PipeMsgListener(){
 public void pipeMsgEvent(PipeMsgEvent pme){
             privateMessage(pme);
      }
};
}

public static void main(String[] args) throws Exception{
MyChatGroup tj = new MyChatGroup();
tj.startJxta();
tj.showFrame();
}

private void startJxta(){
try{//创建默认组netGP
netGP = (new NetPeerGroupFactory()).getInterface();
}catch(Exception e){
System.out.println(e.getMessage());
System.exit(0);
}

try{//加入自己创建的组MyGroup
joinMyGroup();//调用joinMyGroup()方法
}catch(Exception e){
e.printStackTrace();
System.out.println("Can't join or create myGroup.");
System.exit(0);
}
}

解决方案 »

  1.   

    第二部分代码如下,是接着第一部分的
    /** 寻找本地组 */
    private boolean findLocalGroup(DiscoveryService dstmp){
    Enumeration en = null;//记录发现的广告

    try{
    //根据下面joinMyGroup()中传递过来的默认组netGP的服务(dstmp),在本地中查找名为MyChatGroup的对等组。
                en = dstmp.getLocalAdvertisements(DiscoveryService.GROUP, "Name", "MyChatGroup");
            }catch(IOException ioe){
             ioe.printStackTrace();
             return false;
            }
            if(en==null) return false;//没有找到名为MyChatGroup的对等组。
            if(!en.hasMoreElements()) return false;//如果没有下一个元素,返回FALSe
            
            try{//若找到名为MyChatGroup的对等组,则加入该组。
             myGroup = netGP.newGroup((PeerGroupAdvertisement)en.nextElement());
            }catch(PeerGroupException pge){
             pge.printStackTrace();
             return false;
            }
    return true;//找到了名为MyChatGroup的对等组,或创建成功,返回TRUE
    }

    private void showFrame(){
    JFrame jf = new JFrame();
    JPanel jpBottom = new JPanel(new BorderLayout());
    JPanel jpRight = new JPanel(new BorderLayout());
    JPanel jpCenter = new JPanel(new BorderLayout());
    JScrollPane jsp = new JScrollPane(jtaPrivateContent);//JScrollPane为滚动面板

    jpCenter.setBounds(10, 10, 400, 300);//设置jpCenter的距JFrame边界的距离和jpCenter的大小,即距JFrame左边界10个单位,距JFrame上边界10个单位,大小取长400个单位,宽300个单位。
    jpRight.setBounds(420, 10, 150, 340);
    jpBottom.setBounds(10, 320, 400, 30);
    jsp.setBounds(10, 350, 560, 200);
    jsp.setBorder(BorderFactory.createTitledBorder("私聊记录"));

    jpCenter.add(new JScrollPane(jtaHistoryContent, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER);
    jpBottom.add(jtfContent, BorderLayout.CENTER);
    jpBottom.add(jbSend, BorderLayout.EAST);
    JPanel jpRightBottom = new JPanel(new BorderLayout());
         jpRightBottom.add(jbRefresh,BorderLayout.WEST);
         jpRightBottom.add(jbPrivateChat,BorderLayout.EAST);
    jpRight.add(jpRightBottom, BorderLayout.SOUTH);
    jpRight.add(new JScrollPane(jlTable), BorderLayout.CENTER);
    jf.getContentPane().setLayout(null);
    jf.getContentPane().add(jpCenter);
    jf.getContentPane().add(jpBottom);
    jf.getContentPane().add(jpRight);
    jf.getContentPane().add(jsp);
    jf.setSize(580,610);
    jf.setTitle("聊天室 - " + myGroup.getPeerName());
    jf.setLocation(200,200);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.getRootPane().setDefaultButton(jbSend);
    jtfContent.requestFocus(true);
    jf.setVisible(true);
    }

    /** 寻找本地通告 */
    private boolean findLocalPipe(){
    Enumeration en = null;
    try{                               //查找名称为MyChatGroup:PipeAdv:MainChatRoom的广告。
                en = discoverySvc.getLocalAdvertisements(DiscoveryService.ADV, "Name", "MyChatGroup:PipeAdv:"+name);
            }catch(IOException ioe){
             ioe.printStackTrace();
             return false;
            }
            if(en==null) return false;
            if(!en.hasMoreElements()) return false;
            
            System.out.println("Find a exist pipeadvertisement.");
    pipeAdv = (PipeAdvertisement)en.nextElement(); // 在集合中提取一个对等组通告元素
            
    return true;
    }

    /** 加入组,没有找到则建立同时发布通道公告 */
    private void joinMyGroup() throws Exception{
            // find exist group
    DiscoveryService dstmp = netGP.getDiscoveryService();//获得默认组的发现服务

    long tryGroupCount = 1;//尝试加入组的次数
    //调用findLocalGroup()方法
    while(!findLocalGroup(dstmp) && tryGroupCount++<=findGroupTryTimes)
    {
    //在远程查找名为MyChatGroup的对等组,1为获得最大的通告数量。
    dstmp.getRemoteAdvertisements(null, DiscoveryService.GROUP, "Name", "MyChatGroup", 1);
        Thread.sleep(findGroupTimeOut);//线程暂停三秒钟,等待查找结果。
    }

    if(myGroup==null){//myGroup没有找到,则创建它
    //得到在netGP组中的所有ModuleImplAdvertisement广告
        ModuleImplAdvertisement mia = netGP.getAllPurposePeerGroupImplAdvertisement();
        myGroup = netGP.newGroup((PeerGroupID)IDFactory.fromURL(new URL("urn", "", groupURL)), mia, "MyChatGroup", "A test chat jxta group.");
        }
        
    discoverySvc = myGroup.getDiscoveryService();//得到myGroup的发现服务
    pipeSvc = myGroup.getPipeService();//得到myGroup的管道服务

    long tryPipeCount = 1;
    //调用findLocalPipe()方法寻找广告管道名称为MyChatGroup:PipeAdv:MainChatRoom的广告
    while(!findLocalPipe() && tryPipeCount++<=findPipeTryTimes){
    discoverySvc.getRemoteAdvertisements(null, DiscoveryService.ADV, 
                                         "Name", "MyChatGroup:PipeAdv:"+name,
                                         1
                                        );
    Thread.sleep(findPipeTimeOut);
    }

    if(pipeAdv==null){//若管道广告为空,则创建一个
    System.out.println("Create a new pipeadvertisement.");
    pipeAdv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(
    PipeAdvertisement.getAdvertisementType());
    pipeAdv.setName("MyChatGroup:PipeAdv:"+name);//设置管道广告的名称为MyChatGroup:PipeAdv:MainChatRoom
    pipeAdv.setPipeID(IDFactory.newPipeID(myGroup.getPeerGroupID()));
    pipeAdv.setType(PipeService.PropagateType);//设置广告类型
    //发布广告
    discoverySvc.publish(pipeAdv, PeerGroup.DEFAULT_LIFETIME, PeerGroup.DEFAULT_EXPIRATION);
    discoverySvc.remotePublish(pipeAdv, DiscoveryService.ADV);
    }

    // 私自的通道
    try{//读取privatepipe.adv文件的内容
    FileInputStream fis = new FileInputStream(advPrivateFileName);
    pipePrivateAdv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(
                                new MimeMediaType("text/xml"), fis);
    }catch(IOException fe){
    System.out.println("Create a new private pipeadvertisement.");
    //创建一个privatepipe.adv文件并写入数据,即设置创建一个privatepipe.adv的各种属性。
    FileOutputStream fos = new FileOutputStream(advPrivateFileName);
    pipePrivateAdv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(
    PipeAdvertisement.getAdvertisementType());
    pipePrivateAdv.setName("MyChatGroup:PipePrivateAdv:"+name);//设置广告名称
        pipePrivateAdv.setPipeID(IDFactory.newPipeID(myGroup.getPeerGroupID()));//广告ID
        pipePrivateAdv.setType(PipeService.UnicastType);//广告类型
        pipePrivateAdv.setDescription(myGroup.getPeerName());//设置广告描述
        pipePrivateAdv.getDocument(new MimeMediaType("text/xml")).sendToStream(fos);//将广告的设置为XML的形式写入到文件中
        fos.flush();
        fos.close();
    }
    //发布私自通道广告
    discoverySvc.publish(pipePrivateAdv, PeerGroup.DEFAULT_LIFETIME, PeerGroup.DEFAULT_EXPIRATION);
    discoverySvc.remotePublish(pipePrivateAdv, DiscoveryService.ADV);
        //根据管道服务和私自通道广告创建私自输入管道。并实现输入管道的监听
        InputPipe inPrivatePipe = pipeSvc.createInputPipe(pipePrivateAdv, privateMsgListener);
        
    inPipe = pipeSvc.createInputPipe(pipeAdv, this);//创建输入管道
            
            System.out.println(myGroup.getPeerName());
            // 建立输出通道
            refreshOnline();
    }

    // 私聊时发来的信息处理
    private void privateMessage(PipeMsgEvent pme){
    Message msg = pme.getMessage();
    /* 因为私聊时,信息里携带了对方的通告,所以可以这样获得。但暂时不这样
    try{
       StructuredDocument sd = StructuredDocumentFactory.newStructuredDocument(
       new MimeMediaType("text/xml"), msg.getMessageElement("PipeAdv").getStream());
       System.out.println(sd);
    }catch(IOException ioe){
    ioe.printStackTrace();
    }
    */
    MessageElement userName = null;
    MessageElement sendContent = null;
    try{
       userName = msg.getMessageElement("UserName");
       if (userName == null)return;
       sendContent = msg.getMessageElement("SendContent");
       jtaPrivateContent.append("[[  " + userName + "  ]]\n" + sendContent + "\n");
       jtaPrivateContent.setSelectionStart(jtaHistoryContent.getText().length());
       //JTextComponent类是JTextArea和JTextField的基类,setSelectionStart()方法是JTextComponent类
       //的一个方法,作用是从文本组件中提取被选中的文本内容。getText()也是JTextComponent类的一个方法,其作用
       //是从文本组件中提取所有文本内容。
    }catch(Exception e){
    e.printStackTrace();
    }
    }

    // 刷新列表
    private void refreshList(){ // 存在同步问题,多线程会执行此方法
        Enumeration en = null;
        try{
        en = discoverySvc.getLocalAdvertisements(DiscoveryService.ADV, 
                                                     "Name", 
                                                     "MyChatGroup:PipePrivateAdv:"+name);
    }catch(IOException de){
    de.printStackTrace();
    }
    if(en==null || !en.hasMoreElements()) return ;
    Advertisement adv = null;
    PipeAdvertisement pa = null;
    PipeAdvertisement padv = null;
    Vector<Object> pipeInfo = null;

    int length = 0; while(en.hasMoreElements()){
    try{
       adv = (Advertisement)en.nextElement();
       if (!adv.getAdvType().equals(PipeAdvertisement.getAdvertisementType())){
       continue;
       }
                   pa = (PipeAdvertisement)adv;
                   
                   
                   if(pipePrivateId.contains(pa.getPipeID().toString())){ // 是否已经存在该ID
                      System.out.println("已存在");
                      continue;
                   }
                   
       padv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(
           PipeAdvertisement.getAdvertisementType());
           padv.setPipeID(IDFactory.fromURL(
                               pa.getPipeID().getURL()
                              ) );
       padv.setType(PipeService.UnicastType);
       try{
             outPipe = pipeSvc.createOutputPipe(padv, createPipeTimeOut);
           }catch(Exception ope){
             continue;
           }
                   
                   if(pipePrivateId.contains(pa.getPipeID().toString())){ // 是否已经存在该ID
                      System.out.println("已存在");
                      continue;
                   }else{
                      pipePrivateId.add(pa.getPipeID().toString());
                   }
                   
       pipeInfo = new Vector<Object>();
       pipeInfo.add(pa.getDescription());
       pipeInfo.add(pa.getPipeID().toString());
       pipeInfo.add(outPipe);
       pipesPrivate.add(pipeInfo);
       list.add(pa.getDescription());
    }catch(Exception e){
    e.printStackTrace();
    }
    }
    ((DefaultTableModel)jlTable.getModel()).fireTableDataChanged();
    }
      

  2.   

    第三部分代码,是接着第二部分的private void refreshOnline(){
    Runnable tGroup = new Runnable(){
      public void run(){
       while(true){
          discoveryGroup();
          discoverySvc.getRemoteAdvertisements(null, DiscoveryService.ADV, 
                                         "Name", "MyChatGroup:PipeAdv:"+name,
                                         findPipeCount
                                        );
           try{Thread.currentThread().sleep(10 * 60 * 1000);}catch(Exception e){}
        }
      }
    };

    new Thread(tGroup).start();

    Runnable tList = new Runnable(){
      public void run(){
       while(true){
        refreshList();
                 discoverySvc.getRemoteAdvertisements(null, DiscoveryService.ADV, 
                                         "Name", "MyChatGroup:PipePrivateAdv:"+name,
                                         findPipeCount
                                        );
             try{Thread.currentThread().sleep(10 * 1000);}catch(Exception e){}
        }
      }
    };

    new Thread(tList).start();
    }

    private ModuleSpecAdvertisement doAdertisement(){
    ModuleClassAdvertisement mca = (ModuleClassAdvertisement)AdvertisementFactory.newAdvertisement(
    ModuleClassAdvertisement.getAdvertisementType());

    ModuleClassID mcid = IDFactory.newModuleClassID();
    mca.setModuleClassID(mcid);
    mca.setName("ccc");
    mca.setDescription("");
    try{
    discoverySvc.publish(mca);
    discoverySvc.remotePublish(mca, DiscoveryService.ADV);
    }catch(Exception e){
    e.printStackTrace();
    }

    ModuleSpecAdvertisement msa = (ModuleSpecAdvertisement)AdvertisementFactory.newAdvertisement(
    ModuleSpecAdvertisement.getAdvertisementType());
    msa.setModuleSpecID(IDFactory.newModuleSpecID(mcid));
    msa.setName("iiiiiiiiii");
    msa.setDescription("lllllllllll");
    return msa;
    }

    public void discoveryGroup(){
    Enumeration en = null;
    try{
    en = discoverySvc.getLocalAdvertisements(DiscoveryService.ADV, 
                                             "Name", 
                                             "MyChatGroup:PipeAdv:"+name);
    }catch(IOException ie){
    ie.printStackTrace();
    }
    if(en==null || !en.hasMoreElements()) return ;
    Advertisement adv = null;
    PipeAdvertisement pa = null;
    PipeAdvertisement padv = null;
    Vector<Object> pipeInfo = null;

    while(en.hasMoreElements()){
    try{
       adv = (Advertisement)en.nextElement();
       if (!adv.getAdvType().equals(PipeAdvertisement.getAdvertisementType())){
       continue;
       }
                   pa = (PipeAdvertisement)adv;
                   
                   if(pipeId.contains(pa.getPipeID().toString())){//pipeId.contains()方法检查pipeId是否包含getPipeID字符串
                      continue;
                   }else{
                      pipeId.add(pa.getPipeID().toString());//如不包含,则将广告pa的ID字符串加入pipeId中。
                   }
                
       padv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(
           PipeAdvertisement.getAdvertisementType());
           padv.setPipeID(IDFactory.fromURL(
                               pa.getPipeID().getURL()
                              ) );
       padv.setType(PipeService.PropagateType);
       outPipe = pipeSvc.createOutputPipe(padv, createPipeTimeOut);//根据管道服务和padv创建输出管道
       
       pipeInfo = new Vector<Object>();//pipeInfo收集pipe广告的名称、ID、输出管道等
       pipeInfo.add(pa.getName());
       pipeInfo.add(pa.getPipeID().toString());
       pipeInfo.add(outPipe);
       pipes.add(pipeInfo);//最后将收集到的输出管道信息传添加到pipe中
    }catch(Exception e){
    e.printStackTrace();
    }
    }
    }
    //公聊时发来的消息处理。
    public void pipeMsgEvent(PipeMsgEvent pme){
    MessageElement userName = null;
    MessageElement sendContent = null;
    try{
       Message msg = pme.getMessage();
       userName = msg.getMessageElement("UserName");
       if (userName == null)return;
       sendContent = msg.getMessageElement("SendContent");
       jtaHistoryContent.append("[[  " + userName + "  ]]\n" + sendContent + "\n");
       jtaHistoryContent.setSelectionStart(jtaHistoryContent.getText().length());
      
    }catch(Exception e){
       System.out.println(e.getMessage());
       e.printStackTrace();
    }
    }
    //getActionCommand()方法的用法:比如说按纽的事件,同一个JFrame里可能有多个按钮的事件,为了避免冲突,给每个按钮
    //设置不同的ActionCommand,在监听时间的时候,用这个做条件区分事件,以做不同的响应,getActionCommand()返回的是按钮上的标签。
    public void actionPerformed(ActionEvent ae){
    if(ae.getActionCommand().equals("发送")){//如果对名为"发送"的按钮进行任何操作,则会对事件作出如下响应。
    if(jtfContent.getText().trim().equals("")) return;
    int count = sendToAll();
    if(count > 0) jtfContent.setText("");
    jtfContent.requestFocus(true);
    }else if(ae.getActionCommand().equals("刷新")){//对在线列表进行刷新。
    pipesPrivate.clear();
        pipePrivateId.clear();
        list.clear();
    refreshList(); 
    }else if(ae.getActionCommand().equals("私聊")){
    int index = jlTable.getSelectedRow();
    if(index==-1) return;
    OutputPipe op = (OutputPipe)pipesPrivate.get(index).get(2);
    String to = list.get(index).toString();
    privateChat(op, to);
    }

    }

    private void privateChat(OutputPipe op, String to){
    String oneText = "";
    oneText = JOptionPane.showInputDialog("发送给 - "+to, "");
    if(oneText==null || oneText.equals(""))return;
    jtaPrivateContent.append("[[  " + "发送给-" + to + "  ]]\n" + oneText + "\n");
    jtaPrivateContent.setSelectionStart(jtaHistoryContent.getText().length());
    Message msg = new Message();
    StringMessageElement smeUsername = new StringMessageElement("UserName", myGroup.getPeerName(), null);
    StringMessageElement smeContent = new StringMessageElement("SendContent", oneText, null);
    TextDocumentMessageElement tdme = new TextDocumentMessageElement("PipeAdv", (TextDocument)pipePrivateAdv.getDocument(new MimeMediaType("text/xml")), null);
    msg.addMessageElement(smeUsername);
    msg.addMessageElement(smeContent);
    msg.addMessageElement(tdme);
    try{
       op.send(msg);
    }catch(IOException ioe){
    ioe.printStackTrace();
    }
    }

    private int sendToAll(){
    Enumeration<Vector<Object>> en = pipes.elements();
    Message msg = new Message();
    StringMessageElement smeUsername = new StringMessageElement("UserName", myGroup.getPeerName(), null);
    StringMessageElement smeContent = new StringMessageElement("SendContent", jtfContent.getText(), null);
    msg.addMessageElement(smeUsername);
    msg.addMessageElement(smeContent);
    while(en.hasMoreElements()){
    outPipe = (OutputPipe)en.nextElement().get(2);//不懂这句是什么意思
    try{
       outPipe.send(msg);
    }catch(Exception e){
    }
    }
    return pipes.size();
    }

    }
      

  3.   

    以上就是全部代码,主要是在默认组netPG组中创建自己的组myGroup,然后就是查找该组的广告,没有找到,则创建该广告,然后就是寻找pipeadvertisement,里面有我自己的注释,有很多地方也不太明白,哪位好心人能详细的告诉我其中的过程吗?加我QQ也可以448922106(请注明来历);或发邮件也行,[email protected]
      

  4.   

    5楼加我QQ好吗?或者把你QQ告诉我,我加你
    有太多不明白的,在这里说不清楚。我有很多问题
      

  5.   

    上面代码为什么找到myGroup组后,马上就去查找pipe呢?而不去找peer呢?难道pipe就代表着peer吗?找到一个pipe是不是就意味着找到了一个peer呢?