博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java-在线聊天系统-线程
阅读量:5095 次
发布时间:2019-06-13

本文共 4622 字,大约阅读时间需要 15 分钟。

一、概述

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();	}}

  

三、运行结果

转载于:https://www.cnblogs.com/shamgod/p/4612142.html

你可能感兴趣的文章
TransactionScope 之分布式配置
查看>>
ExRichTextEdit.
查看>>
推荐些在线小制作小工具
查看>>
如何保障Go语言基础代码质量?
查看>>
mptcp 路径管理中的fullmesh和 ndiffports以及subflows
查看>>
py编码终极版
查看>>
什么是 CI/CD?(翻译)
查看>>
万象网管快捷方式参数
查看>>
数据库学习之ADO.NET五大对象
查看>>
1405 奶牛的旅行
查看>>
使用smartSVN管理代码时,静态库不能提交的问题解决方案
查看>>
程序日志记录文章链接收藏
查看>>
线程局部变量的使用
查看>>
【BZOJ2527】[Poi2011]Meteors 整体二分
查看>>
7天学会编程设计模式
查看>>
rhel 6.4 + udev+ 11.2.0.3 + gi + asm+ rac 双节点安装
查看>>
tomcat多端口配置
查看>>
每周例行报告——第一周
查看>>
设计模式——单例模式
查看>>
初学c课程笔记整理3--> 流程控制
查看>>