聊天室程序的问题

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

}

}



...全文
208 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
  • 打赏
  • 举报
回复
学习了 高手哥
Java聊天室程序 需求分析 2.1 业务需求 1. 与聊天室成员一起聊天。 2. 可以与聊天室成员私聊。 3. 可以改变聊天内容风格。 4. 用户注册(含头像)、登录。 5. 服务器监控聊天内容。 6. 服务器过滤非法内容。 7. 服务器发送通知。 8. 服务器踢人。 9. 保存服务器日志。 10.保存用户聊天信息。 2.2 系统功能模块 2.2.1 服务器端 1.处理用户注册 2.处理用户登录 3.处理用户发送信息 4.处理用户得到信息 5.处理用户退出 2.2.2 客户端 1.用户注册界面及结果 2.用户登录界面及结果 3.用户发送信息界面及结果 4.用户得到信息界面及结果 5.用户退出界面及结果 2.3 性能需求 运行环境:Windows 9x、2000、xp、2003,Linux 必要环境:JDK 1.5 以上 硬件环境:CPU 400MHz以上,内存64MB以上 3.1.2 客户端结构 ChatClient.java 为客户端程序启动类,负责客户端的启动和退出。 Login.java 为客户端程序登录界面,负责用户帐号信息的验证与反馈。 Register.java 为客户端程序注册界面,负责用户帐号信息的注册验证与反馈。 ChatRoom.java 为客户端程序聊天室主界面,负责接收、发送聊天内容与服务器端的Connection.java 亲密合作。 Windowclose 为ChatRoom.java的内部类,负责监听聊天室界面的操作,当用户退出时返回给服务器信息。 Clock.java 为客户端程序的一个小程序,实现的一个石英钟功能。 3. 2 系统实现原理 当用户聊天时,将当前用户名、聊天对象、聊天内容、聊天语气和是否私聊进行封装,然后与服务器建立Socket连接,再用对象输出流包装Socket的输出流将聊天信息对象发送给服务器端 当用户发送聊天信息时,服务端将会收到客户端用Socket传输过来的聊天信息对象,然后将其强制转换为Chat对象,并将本次用户的聊天信息对象添加到聊天对象集Message中,以供所有聊天用户访问。 接收用户的聊天信息是由多线程技术实现的,因为客户端必须时时关注更新服务器上是否有最新消息,在本程序中设定的是3秒刷新服务器一次,如果间隔时间太短将会增加客户端与服务器端的通信负担,而间隔时间长就会让人感觉没有时效性,所以经过权衡后认为3秒最佳,因为每个用户都不可能在3秒内连续发送信息。 当每次用户接收到聊天信息后将会开始分析聊天信息然后将适合自己的信息人性化地显示在聊天信息界面上。 4.1.1 问题陈述 1.接受用户注册信息并保存在一个基于文件的对象型数据库。 2.能够允许注册过的用户登陆聊天界面并可以聊天。 3.能够接受私聊信息并发送给特定的用户。 4.服务器运行在自定义的端口上#1001。 5.服务器监控用户列表和用户聊天信息(私聊除外)。 6.服务器踢人,发送通知。 7.服务器保存日志。

62,624

社区成员

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

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