代码如下
jtaServer.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
sendMessage = jtaServer.getText();
if(!sendMessage.isEmpty()){
output.print(jtaServer.getText());
flag = true;
}
} else {
}
}
});
class SendThread extends Thread{
SendThread(Socket socket){
while(true){
if(flag == false){  //程序一直停在这儿
yield();
}
else{
flag = false;
InetAddress inetAddress = socket.getInetAddress();
if(!sendMessage.isEmpty()){
jtaDisplay.append(inetAddress.getHostName() + "\t" + new Date() + "\n"); 
jtaDisplay.append(sendMessage);
}
}
}
}
}
在学习网络,想实现Client 和Server聊天 
我的思路是在Client这里一发送消息,就显示在jtaDisplay = new JTextArea(); 上,就像QQ上一样,能看到彼此的通信记录
同样的从Server哪里接受信息,也显示在jtaDisplay上
jtaServer是JTextArea, 我希望通过jtaServer的事件监听改变flag的值, 从而使SendThread 能进行下去 ,
按理说flag改变为true,就应该能执行下去,但是总是停在这里,不知为何

解决方案 »

  1.   

    检查过:
      if (e.getKeyCode() == KeyEvent.VK_ENTER)
    这里面确实执行过么?另外,所引用的flag变量是同一个么?
      

  2.   

    突然发现,你的线程定义,完全错误呐应该是定义在 run() 函数中,然后用 start() 去启动它,你这样写直接把主线程给阻塞了吧?!
      

  3.   

    照你说的改了,现在SendTask没问题,ReceiveTask有问题,能显示自己的聊天信息,不能显示对方的聊天信息
    代码如下
    try{
    ServerSocket serverSocket = new ServerSocket(8000);

    Socket socket = serverSocket.accept();
    output = new PrintWriter(socket.getOutputStream());
    sc = new Scanner(socket.getInputStream());
    new Thread(new SendTask(socket)).start();
    new Thread(new ReceiveTask(socket)).start();
    }
    catch(Exception ex){
    System.err.println(ex);
    }
    class ReceiveTask implements Runnable{
    private Socket socket;

    public ReceiveTask(Socket socket){
    this.socket = socket;
    }

    public void run(){
    while(true){
    String receiveMessage = "";
    if(!sc.hasNext()){  //线程在这里停住了
    Thread.yield();
    }
    else{
    while(sc.hasNextLine()){
    receiveMessage += sc.nextLine();
    }
    InetAddress inetAddress = socket.getInetAddress();
    if(!receiveMessage.isEmpty()){
    jtaDisplay.append(inetAddress.getHostName() + "\t" + new Date() + "\n"); 
    jtaDisplay.append(receiveMessage + "\n");
    }
    }
    }
    }
    }
      

  4.   

    我的回复似乎丢了。看你的程序没看出来,但你对OutputStream写入数据后,是否执行了 flush()?另外,你所写入的信息,是否确定有分割符(如空格)和换行符(\n)?
      

  5.   

    有空格和\n,没有执行flush()这样会有什么问题吗
      

  6.   

    我把代码贴出出来,真心希望哪位好心人能帮忙看看
    package ex30;import javax.swing.*;
    import java.awt.*;
    import java.io.*;
    import java.net.*;
    import java.util.Date;
    import java.util.Scanner;
    import java.awt.event.*;public class Ex30_12Server extends JFrame{
    private JTextArea jtaDisplay = new JTextArea();
    private JTextArea jtaServer = new JTextArea();
    private PrintWriter output;
    private Scanner sc;
    private String sendMessage = "";
    boolean flag = false;

    public static void main(String[] args) {
    // TODO 自动生成方法存根
    new Ex30_12Server();
    }

    public Ex30_12Server(){
    setLayout(new GridLayout(2, 1, 5, 5));
    jtaDisplay.setEditable(false);
    jtaDisplay.setBorder(BorderFactory.createTitledBorder(
    "Server to Client"));
    jtaServer.setBorder(BorderFactory.createTitledBorder(
    "Server"));
    add(new JScrollPane(jtaDisplay));
    add(new JScrollPane(jtaServer));
    setTitle("Ex30_12Server");
    setSize(500, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);

    try{
    ServerSocket serverSocket = new ServerSocket(8000);

    Socket socket = serverSocket.accept();
    output = new PrintWriter(socket.getOutputStream());
    sc = new Scanner(socket.getInputStream());
    new Thread(new SendTask(socket)).start();
    new Thread(new ReceiveTask(socket)).start();
    }
    catch(Exception ex){
    System.err.println(ex);
    }

    jtaServer.addKeyListener(new KeyAdapter() {
    public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_ENTER) {
    sendMessage = jtaServer.getText();
    if(!sendMessage.isEmpty()){
    output.print(jtaServer.getText());
    flag = true;
    }
    } else {
    }
    }
    });
    }

    // Define the thread class for send message
    class SendTask implements Runnable{
    private Socket socket;
    public SendTask(Socket socket){
    this.socket = socket;
    }

    public void run(){
    while(true){
    if(flag == false){
    Thread.yield();
    }
    else{
    flag = false;
    InetAddress inetAddress = socket.getInetAddress();
    if(!sendMessage.isEmpty()){
    jtaDisplay.append(inetAddress.getHostName() + "\t" + new Date() + "\n"); 
    jtaDisplay.append(sendMessage + "\n");
    }
    }
    }

    }
    }

    // Define the thread class for receive message
    class ReceiveTask implements Runnable{
    private Socket socket;

    public ReceiveTask(Socket socket){
    this.socket = socket;
    }

    public void run(){
    while(true){
    String receiveMessage = "";
    if(!sc.hasNext()){
    Thread.yield();
    }
    else{
    while(sc.hasNextLine()){
    receiveMessage += sc.nextLine();
    }
    InetAddress inetAddress = socket.getInetAddress();
    if(!receiveMessage.isEmpty()){
    jtaDisplay.append(inetAddress.getHostName() + "\t" + new Date() + "\n"); 
    jtaDisplay.append(receiveMessage + "\n");
    }
    }
    }
    }
    }
    }package ex30;import java.awt.*;
    import java.awt.event.*;import javax.swing.*;
    import java.util.*;
    import java.io.*;
    import java.net.*;public class Ex30_12Client extends JFrame{
    private JTextArea jtaDisplay = new JTextArea();
    private JTextArea jtaClient = new JTextArea();
    private PrintWriter output;
    private Scanner sc;
    private String sendMessage = "";
    boolean flag = false;

    public Ex30_12Client(){
    setLayout(new GridLayout(2, 1, 5, 5));
    jtaDisplay.setEditable(false);
    jtaDisplay.setBorder(BorderFactory.createTitledBorder(
    "Client to Server"));
    jtaClient.setBorder(BorderFactory.createTitledBorder(
    "Client"));
    add(new JScrollPane(jtaDisplay));
    add(new JScrollPane(jtaClient));
    setTitle("Ex30_12Client");
    setSize(500, 300);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);

    try{
    Socket socket = new Socket("localhost", 8000);
    output = new PrintWriter(socket.getOutputStream());
    sc = new Scanner(socket.getInputStream());
    new Thread(new SendTask(socket)).start();
    new Thread(new ReceiveTask(socket)).start();
    }
    catch (Exception ex){
    System.err.println(ex);
    }

    jtaClient.addKeyListener(new KeyAdapter() {
    public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_ENTER) {
    sendMessage = jtaClient.getText();
    if(!sendMessage.isEmpty()){
    output.print(jtaClient.getText());
    flag = true;
    }
    } else {
    }
    }
    });
    }

    public static void main(String[] args) {
    // TODO 自动生成方法存根
    new Ex30_12Client();
    }

    //  Define the thread class for send message
    class SendTask implements Runnable{
    private Socket socket;
    public SendTask(Socket socket){
    this.socket = socket;
    }

    public void run(){
    while(true){
    if(flag == false){
    Thread.yield();
    }
    else{
    flag = false;
    InetAddress inetAddress = socket.getInetAddress();
    if(!sendMessage.isEmpty()){
    jtaDisplay.append(inetAddress.getHostName() + "\t" + new Date() + "\n"); 
    jtaDisplay.append(sendMessage + "\n");
    }
    }
    }

    }
    }

    // Define the thread class for receive message
    class ReceiveTask implements Runnable{
    private Socket socket;

    public ReceiveTask(Socket socket){
    this.socket = socket;
    }

    public void run(){
    while(true){
    String receiveMessage = "";
    if(!sc.hasNext()){
    Thread.yield();
    }
    else{
    while(sc.hasNextLine()){
    receiveMessage += sc.nextLine();
    }
    InetAddress inetAddress = socket.getInetAddress();
    if(!receiveMessage.isEmpty()){
    jtaDisplay.append(inetAddress.getHostName() + "\t" + new Date() + "\n"); 
    jtaDisplay.append(receiveMessage + "\n");
    }
    }
    }
    }
    }
    }
      

  7.   

    你的程序真的没法评价!怎么会用到flag,为什么要暂停线程?
    http://www.cnblogs.com/linzheng/archive/2011/01/23/1942328.html
    http://daoyongyu.iteye.com/blog/265677
    这是两个关于这方面的知识,你好好研究研究吧
      

  8.   


    没有执行 flush(),意味着数据包不一定会被立即发送给对方。为了提升网络IO效率,输入输出都是带缓冲区的,批量发送;而不是你写1个字节就立即发送1个字节。
    8楼说的是对的,你对netIO的体系还不熟悉,导致设计上存在扭曲。
    不过我并不想对你程序做结构性修改建议,毕竟是另一个方向的事情,而且关键还是自己先懂。