/*
需求:用多线程机制来实现简单QQ聊天程序;用界面(即窗体显示出来);————可先用单线程实现;
思路:整体思路:窗体界面+UDP服务连接+多线程
  窗体界面
     主窗体设置,大小布局等;关闭按钮事件监听;
     发送,关闭按钮各一个,发送按钮点击时将数据发送出去,即发给接收端,同时也要在文本区域中显示自己已发的信息
 则可以给发送按钮加上事件监听(默认为鼠标),当点击时将数据发出去;
     关闭按钮点击时推出QQ聊天程序;给关闭按钮加事件监听(默认为鼠标);
     两个文本区域,一个显示已发数据和接收到数据,当单击发送按钮时,首先将发送的数据显示在本机上,然后在发出去,
     可是怎么获取已经发出去的数据呢,就是在发送前,获取录入的信息,打印输出在显示文本区域,然后在发送;  
     另一个显示将要发出去的数据,即提供键盘录入操作;
  UDP服务连接设置:
      在发送按钮中添加监听事件时,可首先获取要发送的信息传给接收信息文本区域,
  然后定义UDPSocket,然后将数据打包,写入接收端IP,及端口号;发送出去。关闭UDPSocket
  接收端打开端口监听,接收数据;
      多线程:   
步骤:
*/
package qqtest;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
class QQDemo
{
private Frame qqFrame;
private Button sendBut;
private Button closeBut;
private TextArea sendTa;
private TextArea showTa;
private DatagramSocket sendSocket;
private DatagramSocket receiveSocket;
private DatagramPacket sendPacket;
private DatagramPacket receivePacket;
QQDemo()
{
init();
}
public void init()
{
qqFrame=new Frame("QQ");
qqFrame.setSize(600,400);
qqFrame.setLocation(100,100);
qqFrame.setLayout(new FlowLayout());
sendBut=new Button("发送");
closeBut=new Button("关闭");
sendTa=new TextArea(30,20);
showTa=new TextArea(30,40);
qqFrame.add(sendBut);
qqFrame.add(closeBut);
qqFrame.add(sendTa);
qqFrame.add(showTa);
myEvent();
qqFrame.setVisible(true);

}
public void publicCode()
{
BufferedReader br=null;
try
{
String line=sendTa.getText();
    sendSocket=new DatagramSocket(8888);//可以不指定;
showTa.append(line);
byte[]buf=line.getBytes();
//指定要发送的数据包的接收地址(IP即端口号);
sendPacket=new DatagramPacket(buf,buf.length,InetAddress.getByName("10.1.149.114"),10003);
sendSocket.send(sendPacket);
sendSocket.close();
sendTa.setText("");
}
catch(Exception e)
{
throw new RuntimeException("数据报包套接字发送失败",e);
}
}
private void  myEvent()
{
qqFrame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we)
{
System.out.println("X关闭QQ");
System.exit(0);
}
});
closeBut.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent me)
{
System.out.println("按钮关闭QQ");
System.exit(0);
}
});
sendBut.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent me)
{
publicCode();
}
});
sendTa.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent ke)
{
if(KeyEvent.VK_ENTER==ke.getKeyCode())
publicCode();
}
});
}

}
class QQTest
{
public static void main(String []args)
{
new QQDemo();
}
}
class QQGet
{
public static void main(String []args)
{
try
{
DatagramSocket ds=new DatagramSocket(10003);
while(true)
{
byte[]buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,buf.length);
ds.receive(dp);
//InetAddress ia=dp.getAddress();
String ip=dp.getAddress().getHostAddress();
String text=new String(dp.getData(),0,dp.getLength());
int port =dp.getPort();
System.out.println("发送方 IP:"+ip+"port"+port+"\r\ntext:"+text);
}
//ds.close();
}
catch(Exception  e)
{
throw new RuntimeException("接收数据失败",e);
}
}
}前面两个需求都实现了,就是多线程代码是真心写不出来,要求,收发消息加入多线程
大侠们给点建议吧,真HOLD不住了!

解决方案 »

  1.   

    class QQTest
    {
    public static void main(String []args)
    {
    new QQDemo();
    new QQGet().start();//线程启动了
    }
    }
    class QQGet extends Thread 
    {
    public void run(){
    try
    {
    DatagramSocket ds=new DatagramSocket(10003);
    while(true)
    {
    byte[]buf=new byte[1024];
    DatagramPacket dp=new DatagramPacket(buf,buf.length);
    ds.receive(dp);
    //InetAddress ia=dp.getAddress();
    String ip=dp.getAddress().getHostAddress();
    String text=new String(dp.getData(),0,dp.getLength());
    int port =dp.getPort();
    System.out.println("发送方 IP:"+ip+"port"+port+"\r\ntext:"+text);
    }
    //ds.close();
    }
    catch(Exception e)
    {
    throw new RuntimeException("接收数据失败",e);
    }
    }
    }我就简单的写了一下,调用new QQGet().start();//线程启动了
    这个就启动线程了,你可以根据自己需要改改
      

  2.   

    package qqtest;
    import java.io.*;
    import java.net.*;
    import java.awt.*;
    import java.awt.event.*;
    class QQDemo implements Runnable
    {
    private Frame qqFrame;
    private Button sendBut;
    private Button closeBut;
    private TextArea sendTa;
    private TextArea showTa;
    private DatagramSocket sendSocket;
    private DatagramSocket receiveSocket;
    private DatagramPacket sendPacket;
    private DatagramPacket receivePacket;
    QQDemo()
    {
    //init();
    }
    public void run()
    {
    qqFrame=new Frame("QQ");
    qqFrame.setSize(600,400);
    qqFrame.setLocation(100,100);
    qqFrame.setLayout(new FlowLayout());
    sendBut=new Button("发送");
    closeBut=new Button("关闭");
    sendTa=new TextArea(30,20);
    showTa=new TextArea(30,40);
    qqFrame.add(sendBut);
    qqFrame.add(closeBut);
    qqFrame.add(sendTa);
    qqFrame.add(showTa);
    myEvent();
    qqFrame.setVisible(true);
    }
    /*
    public void init()
    {
    qqFrame=new Frame("QQ");
    qqFrame.setSize(600,400);
    qqFrame.setLocation(100,100);
    qqFrame.setLayout(new FlowLayout());
    sendBut=new Button("发送");
    closeBut=new Button("关闭");
    sendTa=new TextArea(30,20);
    showTa=new TextArea(30,40);
    qqFrame.add(sendBut);
    qqFrame.add(closeBut);
    qqFrame.add(sendTa);
    qqFrame.add(showTa);
    myEvent();
    qqFrame.setVisible(true);

    }
    */
    public void publicCode()
    {
    BufferedReader br=null;
    try
    {
    String line=sendTa.getText();
        sendSocket=new DatagramSocket(8888);//可以不指定;
    showTa.append(line);
    byte[]buf=line.getBytes();
    //指定要发送的数据包的接收地址(IP即端口号);
    sendPacket=new DatagramPacket(buf,buf.length,InetAddress.getByName("10.1.149.114"),10003);
    sendSocket.send(sendPacket);
    sendSocket.close();
    sendTa.setText("");
    }
    catch(Exception e)
    {
    throw new RuntimeException("数据报包套接字发送失败",e);
    }
    }
    private void  myEvent()
    {
    qqFrame.addWindowListener(new WindowAdapter()
    {
    public void windowClosing(WindowEvent we)
    {
    System.out.println("X关闭QQ");
    System.exit(0);
    }
    });
    closeBut.addMouseListener(new MouseAdapter()
    {
    public void mouseClicked(MouseEvent me)
    {
    System.out.println("按钮关闭QQ");
    System.exit(0);
    }
    });
    sendBut.addMouseListener(new MouseAdapter()
    {
    public void mouseClicked(MouseEvent me)
    {
    publicCode();
    }
    });
    sendTa.addKeyListener(new KeyAdapter()
    {
    public void keyPressed(KeyEvent ke)
    {
    if(KeyEvent.VK_ENTER==ke.getKeyCode())
    publicCode();
    }
    });
    }

    }
    class QQTest 
    {
    public static void main(String []args)
    {
    new Thread(new QQDemo()).start();
    new Thread(new QQGet()).start();
    }
    }
    class QQGet implements Runnable
    {
    public void run()
    {
    try
    {
    DatagramSocket ds=new DatagramSocket(10003);
    while(true)
    {
    byte[]buf=new byte[1024];
    DatagramPacket dp=new DatagramPacket(buf,buf.length);
    ds.receive(dp);
    //InetAddress ia=dp.getAddress();
    String ip=dp.getAddress().getHostAddress();
    String text=new String(dp.getData(),0,dp.getLength());
    int port =dp.getPort();
    System.out.println("发送方 IP:"+ip+"port"+port+"\r\ntext:"+text);
    }
    //ds.close();
    }
    catch(Exception  e)
    {
    throw new RuntimeException("接收数据失败",e);
    }
    }
    }这个是我改过的代码,可现在问题是,我发数据是在窗体中,收数据只能在控制台上,怎么能实现将数据收在窗体的接收框中呢,求建议!
      

  3.   

    你可以把private TextArea showTa;
    变成private static TextArea showTa;然后get、set方法。在接受的类中得到textArea就行了
      

  4.   

    public static TextArea showTa;
    QQDemo.showTa.append("我接的:发送方 IP:"+ip+"port"+port+"text:"+text+"\r\n");
    这个是改过的代码,可以实现多线程下的双方通信,感谢楼上的那位了!
    但是菜鸟又有个问题了,怎么布局才像QQ那样,上面是接收区域,下面是发送区域呢?
    我查了我下的API竟然连FlowLayout都没有,是我下的API帮助文档有问题还是?
    所以我只记得FlowLayout。
      

  5.   

    而且我的API连setLayout()都找不到!
      

  6.   

    http://community.csdn.net/,这是我上传的API,如果没分留邮箱我给你发过去
      

  7.   

    网站说错了,你看看吧,你可以用JSplitPane能过拉伸的