我做了一个聊天程序,做了三个界面,一个是登陆界面,一个注册界面和聊天界面。假如登陆成功就打开聊天界面。当我把登陆类的socket传给聊天类QQCose后,我想用这个以建立好的通道发送其它数据时服务器却没有反应。比如说在QQCose中有一个Exit_button的关闭按钮,当我按下按钮时会向服务器发送一些客户的信息给服务器,然后由服务器将客户数据交给数据库类,执行相应的操作。我将客户数据发向服务器时,服务器一点反应都没有,确切的说服务器一步都没执行。我感觉是我的思路出问题了,我并没有使用建立好的socket通道,而是继续让服务器在侦听客户端,服务器不会侦听已经建立好的socket通道。我不知道这个想法是否正确。请高手给我点意见,谢谢!!!

解决方案 »

  1.   

    1.你是否将你的命令flush。
    建议你把核心代码贴出来参考一下
      

  2.   

    //此类为服务器启动类
    package com.java.server;
    import java.io.*;
    import java.net.*;import com.java.client.ClientSocket;public class ServerDemo {
    private ServerSocket ss = null;
    Node client = new Node();
    public ServerDemo(int port){
    try{
    ss =  new ServerSocket(port);
    }
    catch(Exception e){e.printStackTrace();}
    }
    private void Start(){//服务器侦听
    while(true){
    try{
    client.socket = ss.accept();
    new Thread(new ConnectionDemo(client.socket)).start();
    }
    catch(Exception e){e.printStackTrace();}
    }
    }
    public static void main(String[] args) {
    ServerDemo sd = new ServerDemo(9999);
    try{
    sd.Start();
    }
    catch(Exception e){e.printStackTrace();}
    }}
      

  3.   

    //此类为服务器执行类
    package com.java.server;import java.io.*;
    import java.net.Socket;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Vector;import org.dom4j.Attribute;
    import org.dom4j.Document;
    import org.dom4j.DocumentHelper;
    import org.dom4j.Element;
    import org.dom4j.io.OutputFormat;
    import org.dom4j.io.XMLWriter;import com.java.client.ClientLand;public class ConnectionDemo extends Thread {
    Socket clientSo = null;

    BufferedReader br = null;

    StringBuffer sb = null;

    SQLParse sp = new SQLParse(); ClientLand cl = new ClientLand();

    Vector VIP = new Vector();

    Vector Vmsg = null; public ConnectionDemo(Socket so) {
    this.clientSo = so;
    Vmsg = new Vector();
    } public void run() {
    this.Type();
    } @SuppressWarnings("unchecked")
    private void Type() {//接收客户信息判断调用哪个方法
    try {
    br = new BufferedReader(new InputStreamReader(clientSo.getInputStream()));
    sb = new StringBuffer();
    String line = null;
    while (!("</Class>").equals(line=br.readLine())) {
    sb.append(line);
    }
    sb.append("</Class>");
    System.out.println(sb.toString());
    Document doc = DocumentHelper.parseText(sb.toString());
    Element root = doc.getRootElement();
    List list = root.selectNodes("//Class/Types");
    ArrayList al = new ArrayList();
    for (Iterator it = list.iterator(); it.hasNext();) {
    Element el = (Element) it.next();
    al.add(el.getText());
    }
    if (al.get(0).toString().equals("LandConn")) {
    this.LandConn(clientSo);
    } else if (al.get(0).toString().equals("EnrollConn")) {
    this.EnrollConn(clientSo);
    } else if (al.get(0).toString().equals("SendConn")) {
    this.SendConn(clientSo);
    } else if (al.get(0).toString().equals("ExitConn")) {
    this.ExitConn(clientSo);
    }
    } catch (Exception e) {e.printStackTrace();} }

    //登陆
    @SuppressWarnings("unchecked")
    private void LandConn(Socket so) {
    try {
    // 接收信息

    Document doc1 = DocumentHelper.parseText(sb.toString());
    Element root1 = doc1.getRootElement();// 有并列的两个子集时,只要写其中一个,而不要都写
    List list = root1.selectNodes("//Class/Classes/@name");
    List list1 = root1.selectNodes("//Class/Classes/FunctionLanding/@name");
    List list2 = root1.selectNodes("//Class/Classes/FunctionLanding/IPparam");
    List list3 = root1.selectNodes("//Class/Classes/FunctionLanding/LNparam");
    List list4 = root1.selectNodes("//Class/Classes/FunctionLanding/ANparam");
    List list5 = root1.selectNodes("//Class/Classes/FunctionLanding/PWparam");
    List list6 = root1.selectNodes("//Class/Classes/FunctionLanding/Fparam");
    ArrayList al = new ArrayList();
    for (Iterator io = list.iterator(); io.hasNext();) {// 得到类名
    Attribute at = (Attribute) io.next();
    al.add(at.getValue());
    }
    for (Iterator io = list1.iterator(); io.hasNext();) {// 得到方法名
    Attribute at = (Attribute) io.next();
    al.add(at.getValue());
    }
    for (Iterator io = list2.iterator(); io.hasNext();) {// 得到客户IP
    Element el = (Element) io.next();
    al.add(el.getText());
    }
    for (Iterator io = list3.iterator(); io.hasNext();) {// 得到客户名
    Element el = (Element) io.next();
    al.add(el.getText());
    }
    for (Iterator io = list4.iterator(); io.hasNext();) {// 得到客户帐号
    Element el = (Element) io.next();
    al.add(el.getText());
    }
    for (Iterator io = list5.iterator(); io.hasNext();) {// 得到客户密码
    Element el = (Element) io.next();
    al.add(el.getText());
    }
    for(Iterator io = list6.iterator(); io.hasNext();){//得到标记1
    Element el = (Element) io.next();
    al.add(el.getText());
    }
    boolean flagLand = false;
    if (al.size() == 7) {
    if (al.get(0).toString().equals("SQLParse")&& al.get(1).toString().equals("LandDemo")) {
    // 将数据传给QQParse,与数据库中的值比较
    flagLand = sp.LandDemo(al.get(2).toString(), al.get(3).toString(), al.get(4).toString(), al.get(5).toString(),al.get(6).toString());
    }
    }

    // 返回信息
    Document doc = DocumentHelper.createDocument();
    Element root = doc.addElement("Class");
    Element incept = root.addElement("incept");
    incept.addAttribute("type", "boolean").addText(String.valueOf(flagLand));
    String lint = "   ";
    boolean newline = true;
    XMLWriter writer = new XMLWriter(clientSo.getOutputStream(),new OutputFormat(lint, newline, "gb2312"));
    writer.write(doc);
    writer.flush();

    } catch (Exception e) {e.printStackTrace();}
    }
    //关闭聊天窗口
             ??问题:当客户登陆成功打开聊天窗口后,我想关闭窗口时,服务器没有反应,确切的说服务器一步都没执行。我找不出错误所在
    private void ExitConn(Socket so){//关闭聊天窗口,同时将客户的一些信息交给数据库类
    boolean flagExit = false;
    try{
    Document doc = DocumentHelper.parseText(sb.toString());
    Element root = doc.getRootElement();
    List list = root.selectNodes("//Class/Classes/Flag");
    List list1 = root.selectNodes("//Class/Classes/AccountNumber");
    ArrayList al = new ArrayList();
    for(Iterator io = list.iterator(); io.hasNext();){
    Element el = (Element)io.next();
    al.add(el.getText());
    }
    for(Iterator io=list1.iterator();io.hasNext();){
    Element el = (Element)io.next();
    al.add(el.getText());
    }
    if(al.size()==2){
    flagExit=sp.ExitDemo(al.get(0).toString(),al.get(1).toString());
    }

    //发送数据
    Document doc1 = DocumentHelper.createDocument();
    Element root1 = doc1.addElement("Class");
    Element incept = root1.addElement("incept");
    incept.addAttribute("type", "boolean").addText(String.valueOf(flagExit));
    String lint = "   ";
    boolean newline = true;
    XMLWriter writer = new XMLWriter(clientSo.getOutputStream(),new OutputFormat(lint, newline, "gb2312"));
    writer.write(doc1);
    writer.flush();
    clientSo.close();
    }
    catch(Exception e){e.printStackTrace();}
    }
    }
      

  4.   

    //客户登陆类
    package com.java.client;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import java.util.List;import org.dom4j.*;
    import org.dom4j.io.*;import org.dom4j.Element;
    import org.dom4j.io.OutputFormat;
    import org.dom4j.io.XMLWriter;import com.java.server.Node;
    public class ClientLand extends JFrame implements ActionListener{

    private JPanel LandPan1 = new JPanel();
    private JPanel LandPan2 = new JPanel();
    private JPanel jp[] = null;
    private JLabel Name = new JLabel("UserName:");
    private JLabel Password = new JLabel("PassWord:");
    private JLabel AccountNumber = new JLabel("AccountNumber:");
    public  JTextField JName = new JTextField(10);
    public  JTextField JPassword = new JTextField(10);
    public JTextField JAccountNumber = new JTextField(10);
    public JButton JLand = new JButton("Land");
    public JButton JEnroll = new JButton("Enroll");
    public JFrame frame;

    Node client = new Node();//类里有socket

    public ClientLand(){

    Container c = this.getContentPane();
    frame = this;

    c.setLayout(new BorderLayout());
    c.add(LandPan1, BorderLayout.CENTER);
    c.add(LandPan2, BorderLayout.SOUTH);

    LandPan1.setLayout(new GridLayout(3, 2));
    jp = new JPanel[6];
    for(int i=0; i<jp.length; i++){
    jp[i] = new JPanel();
    LandPan1.add(jp[i]);
    }
    jp[0].add(Name);
    jp[1].add(JName);
    jp[2].add(AccountNumber);
    jp[3].add(JAccountNumber);
    jp[4].add(Password);
    jp[5].add(JPassword);

    LandPan2.setLayout(new FlowLayout());
    LandPan2.add(JLand);
    LandPan2.add(JEnroll);

    JLand.addActionListener(this);
    JEnroll.addActionListener(this);
    }

    public void actionPerformed(ActionEvent a){

    if(a.getSource()==JLand){
    this.LandConn();//调用登陆方法
    }
    else{
    ClientEnroll ec = new ClientEnroll();//注册类
    ec.setSize(300,300);
    ec.setLocation(400,400);
    ec.setResizable(false);
    ec.show();
     
    }
    }
    //登陆
    @SuppressWarnings("unchecked")
    private String ClientIP = null;
    public void LandConn(){
    String Lflag = "1";//登陆成功设置数据库的flag为1
    try{
    ClientIP= InetAddress.getLocalHost().toString();
    String ClientName = JName.getText();
    String ClientAccountNumber = JAccountNumber.getText();
    String ClientPassWord = JPassword.getText();

    //发送信息
    client.socket = new Socket("localhost",9999);

    Document doc = DocumentHelper.createDocument();
    Element root = doc.addElement("Class");
    Element type = root.addElement("Types");
    Element classes = root.addElement("Classes");
    Element function = classes.addElement("FunctionLanding");
    type.addAttribute("type","String").addText("LandConn");
    classes.addAttribute("name","SQLParse");
    function.addAttribute("name","LandDemo");
    function.addElement("IPparam").addAttribute("type","String").addText(ClientIP);
    function.addElement("LNparam").addAttribute("type","String").addText(ClientName);
    function.addElement("ANparam").addAttribute("type","String").addText(ClientAccountNumber);
    function.addElement("PWparam").addAttribute("type","String").addText(ClientPassWord);
    function.addElement("Fparam").addAttribute("type","String").addText(Lflag);

    //是否有缩进
    String indent = "   ";
    //是否产生新行(即一行一个元素)
    boolean newline = true;
    XMLWriter writer = new XMLWriter(client.socket.getOutputStream(),new OutputFormat(indent,newline,"gb2312"));
    writer.write(doc);
    writer.flush();

    //接收信息
    BufferedReader br = new BufferedReader(new InputStreamReader(client.socket.getInputStream()));
    StringBuffer sb = new StringBuffer();
    String line = null;
    while(!("</Class>").equals(line=br.readLine())){
    sb.append(line);
    }
    sb.append("</Class>");
    Document doc1 = DocumentHelper.parseText(sb.toString());
    Element root1 = doc1.getRootElement();
    List list = root1.selectNodes("//Class/incept");
    ArrayList al = new ArrayList();
    for(Iterator it=list.iterator();it.hasNext();){//得到真假值
    Element el = (Element)it.next();
    al.add(el.getText());
    }
    if(("true").equals(al.get(0).toString())){
    //打开聊天窗口
    QQCoze qc = new QQCoze(JName.getText(),JAccountNumber.getText(),client.socket);
    qc.setSize(600,300);
    qc.setLocation(300,300);
    qc.setVisible(true);
    frame.dispose();
    }
    else{
    //提示用户输入有误
    JOptionPane.showMessageDialog(null,"输入有误,请重新填写!","警告",JOptionPane.WARNING_MESSAGE);
    }

    }
    catch(Exception e){e.printStackTrace();}
    }

    public static void main(String[] args) {
    ClientLand cd = new ClientLand();
    cd.setSize(300,200);
    cd.setLocation(400,400);
    cd.setResizable(false);
    cd.show();
    }}
      

  5.   

    这个类就放了socket和客户的一些信息,这不是关键
      

  6.   

    //聊天类
    package com.java.client;
    import javax.swing.*;
    import java.util.*;
    import java.util.List;
    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.net.*;
    import java.nio.channels.SocketChannel;import org.dom4j.*;
    import org.dom4j.io.*;import com.java.server.Node;//此类为聊天类
    public class QQCoze extends JFrame implements ActionListener{ private JPanel jp1 = new JPanel();
    public JPanel jp2 = new JPanel();
    public JTextField tf = new JTextField(30);
    public JTextArea ta = new JTextArea("");
    private JScrollPane sp = new JScrollPane(ta);
    public JScrollPane jp = new JScrollPane(jp2);
    private JButton send = new JButton("Send");
    private JButton exit = new JButton("Exit");
    private JButton friend = new JButton("GoodFriend");
    private JLabel jl = new JLabel("GOODFRIEND");
    public JButton fbutton = null;

    String username = null;
    String accountnumber = null;
    Node client = new Node();
    public QQCoze(String name, String accountnumber,Socket socket){
    this.username = name;
    this.accountnumber = accountnumber;
    client.socket = socket;从登陆类传socket过来


    Container c = this.getContentPane();
    c.setLayout(new BorderLayout());
    c.add(jp1, BorderLayout.SOUTH);
    c.add(sp, BorderLayout.CENTER);
    c.add(jp,BorderLayout.EAST);

    jp1.setLayout(new FlowLayout());
    jp1.add(tf);
    jp1.add(send);
    jp1.add(friend);
    jp1.add(exit);
    jl.setFont(new Font("新宋体",Font.TYPE1_FONT,18));
    jp2.setLayout(new GridLayout(5,1));
    jp2.add(jl);


    tf.setFocusable(true);//得到光标
    ta.setFocusable(false);
    ta.setEditable(false);//无法输入
    ta.setFont(new Font("",Font.BOLD,16));

    send.addActionListener(this);
    exit.addActionListener(this);
    friend.addActionListener(this);

    } JFrame title = null;
    public void actionPerformed(ActionEvent e){
    if(e.getSource() == send){
    SendDemo();//和大家聊天
    tf.setFocusable(true);
    tf.setText(" ");

    }
    /*if(e.getSource() == friend){
    //System.out.print("OK");
    new FriendFrame(title);
    }*/
    if(e.getSource() == exit){//关闭窗口
    this.ExitDemo();//调用方法
    }
    }

    //关闭
    private void ExitDemo(){
    String CFlag = "0";
    try{

    Document doc = DocumentHelper.createDocument();
    Element root = doc.addElement("Class");
    Element type = root.addElement("Types");
    Element classes = root.addElement("Classes");
    type.addAttribute("type","String ").addText("ExitConn");
    classes.addElement("Flag").addText(CFlag);
    classes.addElement("AccountNumber").addText(accountnumber);
    String indent = "   ";
    boolean newline = true;
    XMLWriter writer = new XMLWriter(client.socket.getOutputStream(),new OutputFormat(indent,newline,"gb2312"));
    writer.write(doc);
    writer.flush();
    ??数据发给服务器,服务器却一步都没执行。请高手指点

    BufferedReader br = new BufferedReader(new InputStreamReader(client.socket.getInputStream()));
    StringBuffer sb = new StringBuffer();
    String line = null;
    while(!("</Class>").equals(line=br.readLine())){
    sb.append(line);
    }
    sb.append("</Class>");
    System.out.print(sb.toString());
    Document doc1 = DocumentHelper.parseText(sb.toString());
    Element root1 = doc1.getRootElement();
    List list = root1.selectNodes("//Class/incept");
    ArrayList al = new ArrayList();
    for(Iterator io=list.iterator();io.hasNext();){
    Element el = (Element)io.next();
    al.add(el.getText());
    }
    if(("true").equals(al.get(0).toString())){
    System.exit(0);
    }

    //client.socket.close();
    }
    catch(Exception x){x.printStackTrace();}
    }
    }
      

  7.   

    发送端写数据完毕后必须把socket关掉,否则接收端认为数据没有发送完成,就仍然处于等待状态。传递新的数据时在打开一个新的socket连接。
    如果在一次通信里进行多次交互,需要自己制定一个协议,以某种特殊标识表示信息的结束,接受端做相应的处理。
      

  8.   

    ziteng1你好,很高兴你参与我的问题。我现在做的是聊天程序,一个客户只能拥有一个端口号。你所说的第一个想法是错误的,不符合实际情况。你的第二个想法我也做了,程序在循环读数据时有自己定义的结束标记</class>。
      

  9.   

    这个问题出在QQCose类中private void ExitDemo()的函数,客户端发给服务器却没有反应。客户可以登陆到聊天系统但是无法关闭系统。请帮忙看一下,谢谢!!!
      

  10.   

    在服务器上做测试已做过,服务器没有任何反应,应该说一步都没做。你可以重点看一下--服务器执行类和聊天类中的private void ExitDemo()的函数