java服務器端線程體會

一個完整的項目包括服務器和客服端java

服務器端初步編寫:安全

(1)服務器

服務器端應用窗口的編寫 (服務器類Server):this

包括窗口和組件的一些設置, 添加一些客服端的元素,如客服端在線用戶表(Vector), 服務端接口ServerSocket, 服務端線程ServerThread spa

其次就是組件的事件監聽以及相應的事件方法  線程

(2)代理

服務器線程的編寫 (服務器線程類 ServerThread):  code

服務器線程起分配服務器代理線程做用,接受客服端的鏈接同時爲其分配一個專用的服務器代理線程.blog

編寫相對簡單,給出服務器(Server) 經過其服務端接口(ServerSocket)監聽客服端的鏈接(Socket),同時爲其分配代理線程(ServerAgentThread)接口

public class ServerThread extends Thread
{
    Server father; //聲明Server的引用
    ServerSocket ss;//聲明ServerSocket的引用
    boolean flag=true;
    public ServerThread(Server father)
    {//構造器
        this.father=father;
        ss=father.ss;
    }
    public void run()
    {
        while(flag)
        {
            try
            {
                Socket sc=ss.accept();//等待客戶端鏈接
                ServerAgentThread sat=new ServerAgentThread(father,sc);
                sat.start();//建立並啓動服務器代理線程
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

(3)

服務器代理線程(ServerAgentThread) :代理線程對應相應的客服端 起到接受發送信息做用   一個服務器代理線程與一個客服端惟一對應 

服務器代理線程類是服務器主要類,

其中包括一些基本的代理線程內容 如服務器(Server)  客服端鏈接(Socket) 數據輸入輸出(DateInputStream DateOutputStream)  

還有與客服端的數據的一些交流方法, 線程run方法起判斷客服端信息做用  

public class ServerAgentThread extends Thread
{
    
	Server father;//聲明Server(服務器Server)的引用
	Socket sc;//聲明Socke(客服端接口Socket)t的引用
	DataInputStream din;//聲明數據輸入流與輸出流
	DataOutputStream dout;
	boolean flag=true;//控制線程的生命週期
	public ServerAgentThread(Server father,Socket sc)
	{
                //構造方法通常初始化 服務器 客服端接口 還有應用端接口數據輸入輸出
		this.father=father;
		this.sc=sc;
		try
		{
			din=new DataInputStream(sc.getInputStream());//建立數據輸入流
			dout=new DataOutputStream(sc.getOutputStream());//建立數據輸出流
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	public void run()
	{
		while(flag)
		{
			try
			{
				String msg=din.readUTF().trim();
                                //接收客戶端傳來的信息判斷並做出相應的迴應
                                //其中單個迴應通常包含對服務器端的操做數據迴應 以及對客服端的操做數據迴應
		 		if(msg.startsWith("c"))//收到新用戶的信息
				{
					this.nick_name(msg);
				}
				else if(msg.startsWith("<#CLIENT_LEAVE#>")){
					this.client_leave(msg);
				}
				else if(msg.startsWith("<#TIAO_ZHAN#>")){
					this.tiao_zhan(msg);
				}
				else if(msg.startsWith("<#TONG_YI#>")){
					this.tong_yi(msg);
				}
				else if(msg.startsWith("<#BUTONG_YI#>")){
					this.butong_yi(msg);
				}
				else if(msg.startsWith("<#BUSY#>")){
					this.busy(msg);
				}
				else if(msg.startsWith("<#MOVE#>")){
					this.move(msg);
				}
				else if(msg.startsWith("<#RENSHU#>")){
					this.renshu(msg);
				}	
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}


//單個操做方法的書寫
//此處省略幾個
        //新用戶
	public void nick_name(String msg)
	{
		try
		{
			String name=msg.substring(13);//得到用戶的暱稱
			this.setName(name);//用該暱稱給該線程取名
			Vector v=father.onlineList;//得到在線用戶列表
			boolean isChongMing=false;//重名flag
			int size=v.size();//得到用戶列表的大小
			for(int i=0;i<size;i++)
			{
//遍歷列表,查看是否已經有該用戶名
				ServerAgentThread tempSat=(ServerAgentThread)v.get(i);
				if(tempSat.getName().equals(name))
				{
					isChongMing=true;//有重名,將標誌位設爲true
					break;
				}
			}
			if(isChongMing==true)//若是重名
			{
				dout.writeUTF("<#NAME_CHONGMING#>");//將重名信息發送給客戶端
				din.close();//關閉數據輸入流
				dout.close();//關閉數據輸出流
				
                                //重點部分 重名須要終止分配的該服務器代理線程以避免產生安全問題 
                                sc.close();//關閉Socket
				flag=false;//終止該服務器代理線程
			}
			else//若是不重名
			{
				v.add(this);//將該線程添加到在線列表
				father.refreshList();//刷新服務器在線信息列表
				String nickListMsg="";
				size=v.size();//得到在線列表大小
    //(實時更新)
				for(int i=0;i<size;i++)
				{
					ServerAgentThread tempSat=(ServerAgentThread)v.get(i);
					nickListMsg=nickListMsg+"|"+tempSat.getName();
				}
				nickListMsg="<#NICK_LIST#>"+nickListMsg;
                                //將在線用戶組成字符串  <#NICK_LIST#>|1|2|3|4|5|6|7
				Vector tempv=father.onlineList;
				size=tempv.size();
				for(int i=0;i<size;i++)
				{//遍歷在線列表
					ServerAgentThread satTemp=(ServerAgentThread)tempv.get(i);
					satTemp.dout.writeUTF(nickListMsg);//將最新的列表信息發送到各個客戶端
					if(satTemp!=this)
					{//給其餘客戶端發送新用戶上線的信息
						satTemp.dout.writeUTF("<#MSG#>"+this.getName()+"上線了...");
					}
				}
			}
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
		
	}
            
}    


//用戶下線
public void client_leave(String msg){
		try{
			Vector tempv=father.onlineList;//得到在線列表
			tempv.remove(this);//移除該用戶代理線程
			int size=tempv.size();
			String nl="<#NICK_LIST#>";
			for(int i=0;i<size;i++){//遍歷在線列表
				ServerAgentThread satTemp=(ServerAgentThread)tempv.get(i);
				//向各個客戶端發送用戶離線信息
				satTemp.dout.writeUTF("<#MSG#>"+this.getName()+"離線了...");
				//組織信息的在線用戶列表
				nl=nl+"|"+satTemp.getName();
			}
			for(int i=0;i<size;i++){//將最新的列表信息發送到各個客戶端
				ServerAgentThread satTemp=(ServerAgentThread)tempv.get(i);
				satTemp.dout.writeUTF(nl);
			}

(重點部分  線程下線須要關閉其相關代理)
			this.flag=false;//終止該服務器代理線程
			father.refreshList();//更新服務器在線用戶列表
		}
		catch(IOException e){e.printStackTrace();}
	}                                    
相關文章
相關標籤/搜索