我做了一个类似QQ的聊天项目。所有的信息发送都是用xml发送的,用socket建立的网络通道。我没有把xml写成文件,而是把它写在物理内存中。现在的问题是客户端发送一条信息就必须shutdownoutput,这时候socket的输出端被关闭了,如果下次再发送它就报错--输出流是断开的。如果重新new一个socket就不符合实际情况--一个客户只能有一个端口号。如果不用整个程序就死机。我试过用close,那样信息就无法回过来。
请问高手们是否有办法解决这个问题,或者用其他办法解决这个问题。
非常感谢!
请问高手们是否有办法解决这个问题,或者用其他办法解决这个问题。
非常感谢!
从设计上找原因,这肯定是可以避免的
请给出意见,谢谢!!!
注意XML大小问题,如果小的话直接readUTF()和writeUTF()就方便多了,如果数据量很庞大的话考虑是否需要缓存,但是我想学生做的话应该很小
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();
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();
client.socket.shutdownOutput();//这就是出问题的地方
//接收信息
BufferedReader br = new BufferedReader(new InputStreamReader(client.socket.getInputStream()));
StringBuffer sb = new StringBuffer();
String line = br.readLine();
while((line=br.readLine())!=null){
sb.append(line);
} 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(line.toString().equals("true")){
//打开聊天窗口
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();
}}
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();//这个类中有socket,还有其他的用来绑定客户
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();}
}}
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();//此类为登陆类 public ConnectionDemo(Socket so) {
this.clientSo = so;
} 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 ((line=br.readLine())!=null) {//这里null可以改成
</Class>,但会出现我昨天提到的问题
sb.append(line);
}
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());
}
//如果al.get(0).toString()的值是LandConn就调用下面的方法
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;//从数据库返回true或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();
clientSo.shutdownOutput();
} catch (Exception e) {e.printStackTrace();}
}
}
> sb.append(line);
> }先说这个吧,把 null 改成 </Class> 肯定是不合适的,字符串的比较最好用 equals(),用 == 和 != 往往不是你预期的效果。至于为什么会 OutOfMemory,你想 line=br.readLine() 事实上已经返回 null 了(因为你在对端关闭了输出流),但你却去判断 line != "</Class>",当然总是成立的,然后就死循环了。
大哥你搞java很久了吧?我测试成功后就给你加分.
package test.Land;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;public class Client { public static void main(String[] args) throws Exception {
test();
} public static void test() throws Exception {
Socket 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(socket.getOutputStream(), new OutputFormat(indent, newline, "gb2312"));
writer.write(doc);
writer.flush();
System.out.println("发送完毕"); // 接收响应
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
// 接收数据,直至 socket 被对方 close(或者 shutdownOutput)
while ((line = br.readLine()) != null) {
sb.append(line);
}
System.out.println("接收到的内容: " + sb.toString()); socket.close();
}
}//-------- test\Land\Server.java --------
package test.Land;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;public class Server { public static void main(String[] args) throws Exception {
test();
} public static void test() throws IOException {
ServerSocket ss = new ServerSocket(9999);
Socket socket = ss.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuffer sb = new StringBuffer();
String line = null;
// 接收数据,直至收到一行 "</Class>"
while (!"</Class>".equals(line = br.readLine())) {
sb.append(line);
}
sb.append("</Class>");
System.out.println("接收到的内容: " + sb.toString()); // 返回信息
Document doc = DocumentHelper.createDocument();
Element root = doc.addElement("Class");
Element incept = root.addElement("incept");
incept.addAttribute("type", "boolean").addText(String.valueOf(true));
String lint = " ";
boolean newline = true;
XMLWriter writer = new XMLWriter(socket.getOutputStream(), new OutputFormat(lint, newline, "gb2312"));
writer.write(doc);
writer.flush();
System.out.println("发送完毕"); socket.close();
ss.close();
}}