java 在线聊天系统_Java-在线聊天系统-线程

一、概述

1.目标:在上一个版本非线程的聊天系统中,出于要不断监听接收新client和接收client发出的信息,把accept()和DataInputStream.readUTF()分别写在了while()死循环里,由于俩方法都是阻塞性方法,所以一方阻塞,另一方永远得不到执行,所以,在上述代码中,只能监听第一个client的发送信息,新的client永远连接不上。

2.思路:

(1)把socet.accept()接收线程和DataInputStream.readUTF()的处理分开,把前者交给server端的处理,server端把接收到的clent封装到线程里,把DataInputStream.readUTF()的逻辑交给线程处理。

(2)采用异步IO

二、代码

1.ChatServer.java

import java.io.DataInputStream;

import java.io.EOFException;

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

import java.net.UnknownHostException;

public class ChatServer{

private ServerSocket ss = null;

private boolean started = false;

public static void main(String[] args) {

new ChatServer().start();

}

public void start(){

try {

ss = new ServerSocket(8888);

started = true;

} catch (IOException e1) {

e1.printStackTrace();

}

try {

while(started){

//!!!!!注意accept()是阻塞性方法,当被readUTF()阻塞时它不会被执行

Socket s = ss.accept();

System.out.println("a client connect------"+s);

new Thread(new Client(s)).start();

}

} catch (EOFException e) {

System.out.println("客户端已关闭!");

} catch (IOException e) {

e.printStackTrace();

}finally{

try {

//if(dis != null ) dis.close();

//if(s != null ) s.close();

if(ss != null ) ss.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

private class Client implements Runnable{

private Socket s;

private DataInputStream dis = null;

boolean bConnect = false;

public Client(Socket s) {

super();

this.s = s;

try {

dis = new DataInputStream(s.getInputStream());

bConnect = true;

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public void run() {

try {

while(bConnect){

//!!!!!注意readUTF()是阻塞性方法

System.out.println(dis.readUTF());

}

} catch (EOFException e) {

System.out.println("客户端已关闭!");

}

catch (IOException e) {

e.printStackTrace();

}finally{

try {

if(dis != null ) dis.close();

if(s != null ) s.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

}

2.ChatClient.java

import java.awt.BorderLayout;

import java.awt.Button;

import java.awt.Frame;

import java.awt.TextArea;

import java.awt.TextField;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.KeyEvent;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import java.io.DataOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import java.net.Socket;

import java.net.UnknownHostException;

public class ChatClient extends Frame{

private TextField tfText;

private TextArea taContent;

//private Button btnSend;

private Socket socket;

private DataOutputStream dos;

public void launchFrame(){

addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

disconnect();

System.exit(0);

}

});

tfText = new TextField();

taContent = new TextArea();

//btnSend = new Button("发送");

//

//btnSend.addActionListener(new ActionListener() {

//@Override

//public void actionPerformed(ActionEvent e) {

taContent.setText(taContent.getText()+"\n\r"+tfText.getText());

tfText.setText("");

//try {

//DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

//dos.writeUTF(tfText.getText());

//dos.close();

//socket.close();

//} catch (IOException e1) {

//e1.printStackTrace();

//}

//}

//});

tfText.addActionListener(new TFListener());

add(taContent,BorderLayout.NORTH);

add(tfText,BorderLayout.CENTER);

//add(btnSend,BorderLayout.SOUTH);

setLocation(300, 100);

pack();

setVisible(true);

connect("localhost", 8888);

}

//当调用了此方法,会自动把成员变量给socket连接上server

public void connect(String address, int port){

try {

socket = new Socket(address, port);

dos = new DataOutputStream(socket.getOutputStream());

} catch (UnknownHostException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

//退出时释放资源

public void disconnect(){

try {

if(dos != null ) dos.close();

if(socket != null ) socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

class TFListener implements ActionListener{

@Override

public void actionPerformed(ActionEvent e) {

taContent.setText(taContent.getText().trim()+"\n\r"+tfText.getText());

try {

dos.writeUTF(tfText.getText());

dos.flush();

tfText.setText("");

//dos.close();

//socket.close();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

public static void main(String[] args) {

new ChatClient().launchFrame();

}

}

三、运行结果

942c621cc00b42a74049cc5199d925fc.png

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值