Java开发网 Java开发网
注册 | 登录 | 帮助 | 搜索 | 排行榜 | 发帖统计  

您没有登录

» Java开发网 » Java SE 综合讨论区  

按打印兼容模式打印这个话题 打印话题    把这个话题寄给朋友 寄给朋友    该主题的所有更新都将Email到你的邮箱 订阅主题
flat modethreaded modego to previous topicgo to next topicgo to back
作者 谁能帮我分析一下这个代码?感谢
nishishuisw





发贴: 2
积分: 0
于 2009-08-17 11:39 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
/*
* MyChatGroup.java
*
* @auther: Liu Jingchao
* @version: 1.0
* @Copyright: 2006-2008
* @date: 2006.12.28
*
*/

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);
    }
  }
  
  /** 寻找本地组 */
  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);
    
    jpCenter.setBounds(10, 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);
     jpRightBottom.add(jbPrivateChat);
    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{ //查找名称为MyChatGroupTongueipeAdv:MainChatRoom的广告。
en = discoverySvc.getLocalAdvertisements(DiscoveryService.ADV, "Name", "MyChatGroupTongueipeAdv:"+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()方法寻找广告管道名称为MyChatGroupTongueipeAdv:MainChatRoom的广告
    while(!findLocalPipe() && tryPipeCount++<=findPipeTryTimes){
      discoverySvc.getRemoteAdvertisements(null, DiscoveryService.ADV,
       "Name", "MyChatGroupTongueipeAdv:"+name,
       1
       );
      Thread.sleep(findPipeTimeOut);
    }
    
    if(pipeAdv==null){//若管道广告为空,则创建一个
      System.out.println("Create a new pipeadvertisement.");
      pipeAdv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(
        PipeAdvertisement.getAdvertisementType());
      pipeAdv.setName("MyChatGroupTongueipeAdv:"+name);//设置管道广告的名称为MyChatGroupTongueipeAdv: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){
      //创建一个privatepipe.adv文件并写入数据,即设置创建一个privatepipe.adv的各种属性。
      FileOutputStream fos = new FileOutputStream(advPrivateFileName);
      pipePrivateAdv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(
        PipeAdvertisement.getAdvertisementType());
      pipePrivateAdv.setName("MyChatGroupTongueipePrivateAdv:"+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",
       "MyChatGroupTongueipePrivateAdv:"+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();
  }
  
  private void refreshOnline(){
    Runnable tGroup = new Runnable(){
       public void run(){
         while(true){
          discoveryGroup();
          discoverySvc.getRemoteAdvertisements(null, DiscoveryService.ADV,
       "Name", "MyChatGroupTongueipeAdv:"+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", "MyChatGroupTongueipePrivateAdv:"+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",
       "MyChatGroupTongueipeAdv:"+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())){
   continue;  
}else{
   pipeId.add(pa.getPipeID().toString());
}

       padv = (PipeAdvertisement)AdvertisementFactory.newAdvertisement(
       PipeAdvertisement.getAdvertisementType());
     padv.setPipeID(IDFactory.fromURL(
       pa.getPipeID().getURL()
       ) );
       padv.setType(PipeService.PropagateType);
       outPipe = pipeSvc.createOutputPipe(padv, createPipeTimeOut);
      
       pipeInfo = new Vector<Object>();
       pipeInfo.add(pa.getName());
       pipeInfo.add(pa.getPipeID().toString());
       pipeInfo.add(outPipe);
       pipes.add(pipeInfo);
      }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();
    }
  }
  
  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();
  }
  
}




关于 异常 。。。。 谢谢指教

话题树型展开
人气 标题 作者 字数 发贴时间
9964 谁能帮我分析一下这个代码?感谢 nishishuisw 21231 2009-08-17 11:39
7885 Re:谁能帮我分析一下这个代码?感谢 nishishuisw 21 2009-08-18 09:45
7684 Re:谁能帮我分析一下这个代码?感谢 xtuali 6 2009-08-28 19:16
7914 Re:谁能帮我分析一下这个代码?感谢 binghebook 13 2009-08-30 00:07
8283 Re:谁能帮我分析一下这个代码?感谢 JiafanZhou 160 2009-09-03 21:21

flat modethreaded modego to previous topicgo to next topicgo to back
  已读帖子
  新的帖子
  被删除的帖子
Jump to the top of page

   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923