简单的聊天应用,分析线程问题

1.服务器端

package javaQQ;

import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class JavaQserver {
	//建立客户端线程集合,便于群发
	ArrayList<ClientTread> array=new ArrayList<ClientTread>();
	//定义全局用户变量
	String name="";
	public void Start(){	
		ServerSocket qqserver;
		try {
			qqserver=new ServerSocket(3300);
			System.out.println("服务器启动了");
			 while(true){
				 	//阻塞 等待客户端的访问,返回套接字。	
					Socket qq=qqserver.accept();
					//读取客户端传来的名字
					name=redDate(qq);
					System.out.println(name+"-->客户端在线");
					//创建服务器聊天记录
					//OutputText(qq);
					//实例化客户端线程
					ClientTread clientTread=new ClientTread(qq);	
					//启动线程
					new Thread(clientTread).start();
					array.add(clientTread);
				}
			} catch (IOException e) {
				e.printStackTrace();
		}
	}
		
	//显示时间fun
	public String ShowTime(){
	//获取时间
	Date rightNow = new Date();
	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String data=sdf.format(rightNow);
		return data;
	}
	//读取套接字fun 输入流
	public String redDate(Socket data){
		InputStream in;
		try {
			in = data.getInputStream();
			byte[] buf=new byte[1024];
			int len=in.read(buf);
			String getstr=new String(buf,0,len);
			return getstr;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	//线程
	class ClientTread implements Runnable{
		Socket e;
		InputStream in;
		OutputStream out;
		boolean isConnect=false;//判断是否和服务器相连
		public ClientTread(Socket e) {
			this.e=e;
			try {
				in=e.getInputStream();
				out=e.getOutputStream();
				isConnect=true;
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}	
		}
		@Override
		public void run() {//读取一个线程套接字
			while (isConnect) {
				try {
					byte[] buf=new byte[1024];
					int len=in.read(buf);
					String getstr=new String(buf,0,len);
					if("seeyou".equals(getstr)){
						isConnect=false;
						array.remove(this);
					}else {
						System.out.println(ShowTime()+"\n"+getstr);
						//发送数据给所有用户
						for(int i=0;i<array.size();i++){
							ClientTread ct=array.get(i);
							ct.send(ShowTime()+"\n" +getstr);
						}
						
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}	
			}	
		}

		//线程内写入套接字
		public void send(String input){
			try {
				out.write(input.getBytes());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		JavaQserver s1=new JavaQserver();
		s1.Start();
	}	
}

我这里为什么,在套接字读取的线程呢!下面是我的分析

首先:实例化了一个ServerSocket,接收客户端的套接字,当服务器端运行是开启一个线程来接收 客户端的数据,

假想一下,如果没有线程呢!客户端的套接字,在while循环中。。。。当主线程运行完,能接收另一个客户端,你有没有发现一个客户端

只能传一次数据,而且每个客户端传来的数据都是如此。(做完才能执行下一步)

所有:当传入数据时,我开启了一个线程,这个线程没完就一直做下去。不影响其他客户端(有线程帮他执行)


2.客户端

我想客户端的的线程也是这个原理把

package javaQQ;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

import javax.swing.*;


@SuppressWarnings("serial")
public class JavaQclient extends Frame{
	//单行文本控件
	TextField txtIput=new TextField();
	//多行文本控件
	TextArea txtDinput=new TextArea();
	//定义输入,输出流全局变量
	OutputStream out;
	InputStream in;
	//定义全局的  套接字实现连接服务器
	Socket socket;
	//定义一个判断是否连接
	boolean isClient;
	//用户名
	final String name;
	public JavaQclient() {
		//弹出输入框,输入用户姓名
		name=JOptionPane.showInputDialog(" 请输入姓名:");
		//设置窗体名
		setTitle("QQ原型---"+name);
		//设置窗体大小
		setSize(300, 400);
		//设置初现位置,,,居中
		setLocationRelativeTo(null);
		///窗体是否可变,
		setResizable(false);
		//窗体是否可视
		setVisible(true);
		//添加控件,BorderLayout为布局。
		add(txtIput,BorderLayout.SOUTH);
		add(txtDinput,BorderLayout.NORTH);
		pack();//自动调整组件大小
		//设置记录框只读
		txtDinput.setEditable(false);
		//添加窗体监听事件
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				sendDate("seeyou");
				isClient=false;
				System.exit(0);
			}

			
		});
		init();//输入流和输出流的初始化
		
		//把聊天者的名字传给服务器记录
		sendDate(name);
		
		//输入框的动作监听事件
		txtIput.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				//得到输入框的内容
				String input=txtIput.getText();
				//聊天内容发送给服务器
				sendDate(name+":"+input);
				txtIput.setText("");	
			}
		});
	}
	//定义接收数据的线程
	class ServerThread implements Runnable{
		@Override
		public void run() {
			byte[] buf=new byte[1024];
			try {
				while (isClient) {
					int len = in.read(buf);
					String getstr=new String(buf,0,len);
					txtDinput.append(getstr+"\n");
					RecordText(getstr+"\n");
				}
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}		
		}
	}
	
	
	//发送数据到服务器
	public void sendDate(String data){
		try {
			out.write(data.getBytes());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//聊天记录文件记录写入
	public void RecordText(String str){
		FileWriter file;
		try {
			file=new FileWriter(name+".txt",true);
			BufferedWriter out=new BufferedWriter(file);
			out.write(str);
			out.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//聊天记录文件记录读取
		public void OutputText(){
			File file = new File(name+".txt");
			String outText="";
			try {
				if(!file.exists()){
					file.createNewFile();
				}else {
					FileReader inputStream=new FileReader(file);
					char[] buf = new char[1024];
					int len = inputStream.read(buf); //读buf.length个字节到缓存
					while(len != -1){
						for (char i:buf){
							outText=outText+i;
						}
						txtDinput.append(outText);
						len = inputStream.read(buf); //继续读取后面的字节
					}
					inputStream.close();
				}
				
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	//实例花socket对象
	public void init(){
		try {
			//实例花socket对象
			socket = new Socket("127.0.0.1",3300);
			//得到套接字的输入输出流
			out=socket.getOutputStream(); //输出数据流
			in=socket.getInputStream();//输入数据流
			OutputText();//读取聊天记录
			isClient=true;
			new Thread(new ServerThread()).start();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}//开启客户端
		
	}
	
	public static void main(String[] args) {
		 new JavaQclient();
	 }
}


如果有分析的不对的地方,还请广大网友指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值