聊天室程序的问题

wslzxql 2010-03-16 09:51:45
我现在正在写一个聊天室程序,我现在只实现了它的部分功能,为什么我只能够把我第一次写的数据发送过去,然后读回来,后面的就不行呢.请高手指点一下下面是我的程序.


//这是客户端的程序前面的大致都可以不看,只看actionperformed里的就可以了,实现的功能大致就是有一个进入聊天室的jb1和发送信息的jb3,两个textarea用来存放接收到的信息和发送信息jrecept和jsend状况是我第一次点发送信息,能够被服务器端收到,第二次就不可以了.
package liaotianshi;
import javax.swing.*;
import java.awt.*;
import java.net.*;
import java.net.InetAddress;
import java.io.*;
import java.io.IOException;
import java.awt.event.*;
public class Myclient extends JFrame implements ActionListener,Runnable{

/**
* @param args
*/
Socket socket;
Thread thread;

DataInputStream in;
DataOutputStream out;
boolean bool=false;

String name,chtext,chin;
String ip=null;

public static final int PORT=8765;
//设置面板
JPanel jpanel1=new JPanel();
JPanel jpanel2=new JPanel();
JPanel jpanel3=new JPanel();
JPanel jpanel4=new JPanel();
JScrollPane jspane=new JScrollPane();
JScrollPane jspane1=new JScrollPane();

//创建按钮
JButton jb1=new JButton("进入聊天室");
JButton jb2=new JButton("退出聊天室");
JButton jb3=new JButton("发送");

//创建用户输入信息组件
JTextField jname=new JTextField("用户名输入");
JTextField jpw=new JTextField("密码");
JTextArea jsend=new JTextArea();
JTextArea jrecept=new JTextArea();
JTextField jservice=new JTextField();
JTextField jport=new JTextField();

//标签组件
JLabel jl1=new JLabel("用户名");
JLabel jl4=new JLabel("密码");
JLabel jl2=new JLabel("服务器地址:");
JLabel jl3=new JLabel("端口号:");


public Myclient(){
this.setSize(400, 600);
Container content=getContentPane();
content.setLayout(null);

jpanel1.setLayout(null);
jpanel1.setBounds(new Rectangle(0,5,400,35));
jpanel2.setBounds(new Rectangle(5,45,380,230));
jpanel2.setLayout(new GridLayout());
jpanel3.setBounds(new Rectangle(5,180,400,150));
//jpanel3.setLayout(new GridLayout(2,1));
jpanel3.setLayout(null);
jpanel4.setBounds(new Rectangle(5,340,380,180));
jpanel4.setLayout(new GridLayout());

jl1.setBounds(new Rectangle(10,0,80,30));
jpanel1.add(jl1);
jname.setBounds(new Rectangle(55,0,70,25));
jl4.setBounds(new Rectangle(130,0,80,30));
jpanel1.add(jl4);
jpanel1.add(jname);
jpw.setBounds(new Rectangle(160,0,70,25));
jpanel1.add(jpw);
jb1.setBounds(240, 0, 60, 25);
jpanel1.add(jb1);
jb2.setBounds(320, 0, 60, 25);
jpanel1.add(jb2);
content.add(jpanel1,null);
jrecept.setLineWrap(true);
jspane.getViewport().add(jrecept);
jpanel2.add(jspane,null);
content.add(jpanel2,null);
jl2.setBounds(new Rectangle(5,100,100,20));
jpanel3.add(jl2);
jservice.setBounds(new Rectangle(80,100,280,20));
jpanel3.add(jservice);
jl3.setBounds(new Rectangle(5,130,100,20));
jpanel3.add(jl3);
jport.setBounds(new Rectangle(80,130,280,20));
jpanel3.add(jport);
content.add(jpanel3,null);
jsend.setLineWrap(true);
jsend.setBounds(new Rectangle(5,200,350,300));
jspane1.getViewport().add(jsend);
jpanel4.add(jspane1,null);
jb3.setBounds(new Rectangle(250,530,80,25));
content.add(jb3);
content.add(jpanel4,null);
WindowListener windl=new WindowAdapter(){
public void windowClosing(WindowEvent e)
{
Myclient.this.dispose();
}};
jb1.addActionListener(this);
jb2.addActionListener(this);
jb3.addActionListener(this);
this.addWindowListener(windl);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e){
if(e.getSource()==jb1)
{
System.out.println("这是进入聊天室");
try{
socket=new Socket("localhost",1888);
System.out.println("这是进入聊天室");
//in=new DataInputStream(socket.getInputStream());
//out=new DataOutputStream(socket.getOutputStream());
//out.writeUTF("这是我的东东这是从客户端发来的东西");
//String s=in.readUTF();
//if(s!=null)
//System.out.println("读到了服务器"+s);
//else
//System.out.println("读到了服务器"+s);
//jrecept.setText(s);


}
catch(IOException e1)
{
e1.printStackTrace();
}
thread=new Thread(this);
thread.start();
bool=true;

}
if(e.getSource()==jb2)
{
System.out.println("这是退出聊天室");
try{
socket.close();
}
catch(IOException e1){

}
}
if(e.getSource()==jb3)
{

try{
String s=jsend.getText();
System.out.println("这是发送信息"+s);
out=new DataOutputStream(socket.getOutputStream());
if(s!=null)
out.writeUTF(jsend.getText());
else
out.writeUTF("请说话");
//chtext=in.readUTF();
//jrecept.setText(chtext);
}
catch(IOException e1){}
}
}
public void run(){
while(true){
try{
System.out.println("进入了thread of client");
in=new DataInputStream(socket.getInputStream());
chtext=in.readUTF();
System.out.println("读到了服务器"+chtext);
jrecept.setText(chtext);
}
catch(IOException e1){}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Myclient myclient=new Myclient();
}

}


//service端
package liaotianshi;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
public class service extends JFrame implements ActionListener{

/**
* @param args
*/
JButton jbs1=new JButton("启动服务器");
JButton jb2=new JButton("关闭服务器");
JTextArea jshow=new JTextArea();

ServerSocket server;
Socket socket;
Thread thread;
boolean bool;
public service(){
this.setSize(300, 300);
Container content=getContentPane();
content.setLayout(null);
jbs1.setBounds(new Rectangle(20,5,100,25));
content.add(jbs1);
jb2.setBounds(new Rectangle(130,5,100,25));
content.add(jb2);
jshow.setBounds(new Rectangle(10,40,270,200));
content.add(jshow);
jbs1.addActionListener(this);
jb2.addActionListener(this);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==jbs1)
{
System.out.println("点了启动");
servicestart();
}
if(e.getSource()==jb2)
{
servicestop();
}
}
private void servicestart(){
System.out.println("进入启动");

thread=new Thread(new ServerThread());//下面一个进程实现
thread.start();

}
private void servicestop(){

}
public static void main(String[] args) {
// TODO Auto-generated method stub
service serv=new service();

}

}


//实现数据的传送
package liaotianshi;
import java.net.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class ServerThread implements Runnable{

ServerSocket serverthread;
DataInputStream in;
DataOutputStream out;
public ServerThread() {
try{
serverthread=new ServerSocket(1888);
}
catch(IOException e1){

}
}

/**
* @param args
*/

public void run(){
while(true){
try{
System.out.println("进入了thread of server");
Socket socket=serverthread.accept();
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
String s=in.readUTF();
if(s!=null)
out.writeUTF(s) //第一次的能够发送回去,第二次就不行了.感觉
//两面都在等对方的一样,结果都没有
else{

out.writeUTF("这是空的啊");
System.out.println("这是空的啊");
}
}
catch(IOException e1){

}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub

}

}



...全文
206 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
wslzxql 2010-03-18
  • 打赏
  • 举报
回复
非常谢谢你们!!!我刚刚终于解决了,三楼是对的,昨天做得到的是一个空指针异常,我以为是错的.我自己对accept没有理解,它是从连接请求队列中取出一个客户的连接请求,我第一次请求后,连接上了,然后accept就进入了阻塞,等新的连接,第二次请求是同样的客户端,已经连接上了,所以服务器端的连接后的in和out就执行不了.我结贴了
smc2java 2010-03-17
  • 打赏
  • 举报
回复
学习啦,接分洛。。。。。。。。。。。。。。。。。。。。。
萝asdf 2010-03-17
  • 打赏
  • 举报
回复
呜呜,我也可怜啊,咋没人可怜可怜我
http://topic.csdn.net/u/20100315/16/50ea8de7-456d-46c5-abf1-e680a60b1d21.html
http://topic.csdn.net/u/20100208/15/4b692be3-84ed-4d17-8aa8-2e9ca7cce944.html
萝asdf 2010-03-17
  • 打赏
  • 举报
回复
public class QQClient{
public static void main(String ag[]){
new ClientFrame().show();
}
}---------
public class QQServer{
public static void main(String args[])throws Exception {
ServerSocket server=new ServerSocket(9000);


//用来保存Socket对象的容器
Vector v=new Vector();

while(true){//不停的循环
Socket s=server.accept();//等待用户连接
InputStream in=s.getInputStream();//得到输入流


v.add(s);//每进来一个客户就向Vector加一个Socket对象

//启动一个接收线程,传入输入流和Vector
new ServerReceiveThread(in,v).start();
}

}
}----------
public class ServerReceiveThread extends Thread{
InputStream in;//针对某个客户端的输入流

Vector allsockets;

public ServerReceiveThread(InputStream in,Vector v){
//完成参数传递。。。。
this.in=in;
this.allsockets=v;
}

public void run(){
BufferedReader br=new BufferedReader(new InputStreamReader(in));
try{
while(true){
String str=br.readLine();//通过输入流读行
System.out.println("我收到信息:"+str);

//下面开始转发消息,vector里面存的都是每个用户的Socket,所以要遍历Vector
for(int i=0;i<allsockets.size();i++){//取一个发一个
Object obj=allsockets.get(i);
Socket socket=(Socket)obj;
PrintWriter pw=new PrintWriter(socket.getOutputStream());
pw.println(str);
pw.flush();
}
System.out.println("该消息转发完毕");
}
}catch(Exception e){System.out.println(e);}
}
}
萝asdf 2010-03-17
  • 打赏
  • 举报
回复
哎,可怜的孩子,哈哈!看看我以前写的。
public class ClientFrame extends Frame implements ActionListener{
//窗体应该有发送按钮、文本框用来输入东西、List列表用来显示信息

Button connectbutton=new Button("连接");
Button sendbutton=new Button("发送");

List list =new List();
TextField content=new TextField(20);
TextField servername=new TextField(20);
Label label=new Label("输入服务器名字:");



Socket socket;

public ClientFrame(){
super("聊天窗体");
sendbutton.addActionListener(this);
connectbutton.addActionListener(this);
Panel p1=new Panel();
p1.add(label);
p1.add(servername);
p1.add(connectbutton);

Panel p2=new Panel();
p2.add(content);
p2.add(sendbutton);


Panel p3=new Panel();
p3.setLayout(new BorderLayout());
p3.add("South",p2);
p3.add(list);

this.add("South",p1);
this.add(p3);

this.pack();

}

public void actionPerformed(ActionEvent e) {
if(e.getSource()==connectbutton){//连接服务器按钮作用是连接服务器
//连接服务器。。。
try{
socket=new Socket(servername.getText(),9000);
connectbutton.setEnabled(false);
javax.swing.JOptionPane.showMessageDialog(this,"连接成功,聊吧");

//启动接收线程,并把输入流和list列表同时交给线程
new ClientReceiveThread(socket.getInputStream(),list).start();

}
catch(Exception ex){
javax.swing.JOptionPane.showMessageDialog(this,"连接服务器失败");
ex.printStackTrace();
}
}
else
{
//发送信息
try{
OutputStream out=socket.getOutputStream();
PrintWriter pw=new PrintWriter(out,true);
pw.println(content.getText());
content.setText("");
}catch(Exception ex)
{
ex.printStackTrace();
}
}
}
}---------------------
public class ClientReceiveThread extends Thread{
InputStream in;
List list;

public ClientReceiveThread(InputStream in,List list){
//在下面完成参数传递
this.in=in;
this.list=list;

}
public void run(){
try{

BufferedReader br=new BufferedReader(new InputStreamReader(in));
while(true){
String str=br.readLine();//得不到值会阻塞
list.add(str);//得到的信息往窗体上的list里写,list会自动更新显示
}
}catch(Exception e){}

}

}--------------

xiesisi3 2010-03-17
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 java2000_net 的回复:]
我有个建议:
InputStream 和 OutputStream 应该分成2个线程单独处理
服务器的Input对应请求的Output
反之亦然

这样,就不会出现任何大家都等的情况了。

另外,数据发送后,记得flush()一下。
[/Quote]


直接用UDP协议更好吧,谁都不用等。。
wslzxql 2010-03-17
  • 打赏
  • 举报
回复
我把代码发简单一点
//下面是客户端的
public void actionPerformed(ActionEvent e){
if(e.getSource()==jb1)//一个进入聊天室的按键 {
System.out.println("这是进入聊天室");
try{
socket=new Socket("localhost",1888);
System.out.println("这是进入聊天室");
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream()); }
catch(IOException e1)
{
e1.printStackTrace();
}
thread=new Thread(this);
thread.start();
bool=true;
}
if(e.getSource()==jb3)//一个发送信息的按键
{
try{
String s=jsend.getText();
if(s!=null)
out.writeUTF(jsend.getText());//问题就出现在这里,第二
//次发送时就发送不出去,我每点一次发送都停在这里去不了服务器那个程序(serverthread),那边的serversocket就接收不到,第一次可以进那个服务程序.
else
out.writeUTF("请说话");
}
catch(IOException e1){}
}
}
public void run(){
while(true){
try{
System.out.println("进入了thread of client");
//in=new DataInputStream(socket.getInputStream());
chtext=in.readUTF();
System.out.println("读到了服务器"+chtext);
jrecept.setText(chtext);
}
catch(IOException e1){}
}
}
public static void main(String[] args) {
Myclient myclient=new Myclient();
}

}

//一面是service的主程序:实现了启动服务的功能
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==jbs1)//启动服务
{
thread=new Thread(new ServerThread());
thread.start(); }}

//serverthread :实现接收客户端的信息的一个线程
public ServerThread() {//它的构造涵数
try{
serverthread=new ServerSocket(1888);
}
catch(IOException e1){}
}
public void run(){
while(true){
try{
System.out.println("进入了thread of server");
Socket socket=serverthread.accept();//第一次能收到,第次
//不能收到
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
String s=in.readUTF();
if(s!=null)
out.writeUTF(s);
else{
out.writeUTF("这是空的啊");
}
}
catch(IOException e1){}
}
}//主涵数略
}
BearKin 2010-03-17
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wslzxql 的回复:]
我试一试你们说的,这个程序很多都不用看,只从acctionperformed那里看就可以了
[/Quote]

为了你我在学applet 和 swt..
wslzxql 2010-03-17
  • 打赏
  • 举报
回复
我试一试你们说的,这个程序很多都不用看,只从acctionperformed那里看就可以了
BearKin 2010-03-17
  • 打赏
  • 举报
回复
前来学习...当初俺做的时候需要开两个窗口 服务端负责显示 客户端负责发送....悲剧哦..
老紫竹 2010-03-17
  • 打赏
  • 举报
回复
我有个建议:
InputStream 和 OutputStream 应该分成2个线程单独处理
服务器的Input对应请求的Output
反之亦然

这样,就不会出现任何大家都等的情况了。

另外,数据发送后,记得flush()一下。
kaylg 2010-03-17
  • 打赏
  • 举报
回复
看看哦,好久没接触线程
xiesisi3 2010-03-17
  • 打赏
  • 举报
回复
while(true){
try{
System.out.println("进入了thread of client");
//in=new DataInputStream(socket.getInputStream());
chtext=in.readUTF();
System.out.println("读到了服务器"+chtext);
jrecept.setText(chtext);
}
catch(IOException e1){}
}


try{
System.out.println("进入了thread of server");
Socket socket=serverthread.accept();//第一次能收到,第次
//不能收到
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
String s=in.readUTF();
if(s!=null)
out.writeUTF(s);
else{
out.writeUTF("这是空的啊");
}
}
catch(IOException e1){}
}
}//


readUTF和writeUTF都是阻塞式的方法
你客户端也在读,服务器也在读,哪来的那么多东西让它们一起读?都阻塞在那不动了,自己先搞清楚逻辑。
一个读一个写,一个写,一个读,象老式的电话一样才能让你的这个程序跑起来。
wslzxql 2010-03-17
  • 打赏
  • 举报
回复
我把client和服务器端的连接都在发送事件里测试过了:if(socket.isClosed()==false)
System.out.println("没被关闭了");
if(socket.isConnected()==false)
System.out.println("连接被断开了");
if(socket.isOutputShutdown())
System.out.println("out被关闭了");
out.writeUTF(s);//s是要发送的字符串,为什么就是写不过去啊,全部连接都是连接上的啊,谁要是给我解决了,我给90分给他.

wslzxql 2010-03-17
  • 打赏
  • 举报
回复
还是不行啊,有没有谁能再指点一下呀
一头头 2010-03-16
  • 打赏
  • 举报
回复
public void run(){
while(true){
try{
System.out.println("进入了thread of server");
Socket socket=serverthread.accept();
****
}


accept() 以后 线程就停在这里不走下去了
所以你需要把accept放在线程外面 先accept了以后 再搞个线程去socket In
qingyuan18 2010-03-16
  • 打赏
  • 举报
回复
楼主你这样不行,太长的代码很少有人这么有时间来一行行看的

你先debug一下找出问题出在那一部分,再问也好一点,有的放矢
无聊司马 2010-03-16
  • 打赏
  • 举报
回复
学习了 高手哥

62,611

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧