您的位置:首页 > 理论基础 > 计算机网络

基于TCP 的多线程 聊天程序

2008-05-07 10:02 423 查看
 




/**//*


 * 功能:聊天的客户端


 *soft05jun


 *08.3.12


*/


import java.net.*;


import java.util.*;


import java.io.*;




class connet implements Runnable




...{


    Socket localsocket;


    DataInputStream in=null;


    DataOutputStream out=null;


    Thread send,rec;


    Scanner read;          //读入流对象


    connet(String address,int port)




    ...{


        send=new Thread(this);


        rec=new Thread(this);


        read=new Scanner(System.in);


        try




        ...{


            localsocket=new Socket(address,port);


            in=new DataInputStream(localsocket.getInputStream());


            out=new DataOutputStream(localsocket.getOutputStream());


        }


        catch(IOException e)




        ...{


            System.out.print("套接字创建失败,原因:"+e);


            System.out.println("请检查服务器IP、端口是否正确");


        }


        System.out.println("连接成功,可以进行聊天了");


        send.start();


        rec.start();


    }


    public void send()




    ...{


        while(true)




        ...{


            try




            ...{


                out.writeUTF(read.nextLine());


            }


            catch (IOException e)




            ...{


                System.out.println("写入信息时失败");


            }


        }


    }


    public void rec()




    ...{


        while(true)




        ...{


            try




            ...{


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


            }


            catch(IOException e)




            ...{


                System.out.println("读取服务器信息失败");


            }


        }


    }


    public void run()




    ...{


        if(Thread.currentThread()==send)




        ...{


            System.out.println("send线程启动,进入发送状态");


            this.send();


        }


        if(Thread.currentThread()==rec)




        ...{


            System.out.println("rec线程启动,进入接收监听状态");


            this.rec();


        }


    }


    


}




class client




...{


    public static void main(String args[])




    ...{




        String ip=null;


        int port=2526;  //默认是2526


        try




        ...{


            ip=new String(InetAddress.getLocalHost().getHostAddress());


        }


        catch(Exception e)




        ...{


            System.out.println("获取本地IP地址出错,请检查本地网络连接。");


        }


        Scanner reader=new Scanner(System.in);


        System.out.println("请输入服务器IP:");


        ip=reader.nextLine();


        System.out.println("服务器端口:");


        port=reader.nextInt();


        System.out.println("正在连接服务器的IP地址是:"+ip+" 端口是:"+port);


        connet c=new connet(ip,port);    




    }


}

 

 


import java.net.*;


import java.util.Scanner;


import java.io.*;


import java.util.*;




/**//*


 * 此是服务器端


 * soft05jun


 * 08.3.14


 * 改进:其实current_thread,thread_num,mslist等变量可以声明为全家的静态变量比较好。这样就


 * 省掉了 传递的开销。


 */


class message     //消息类.




...{


    int id=0;


    String ms;


    message(int id,String ms)




    ...{


        this.id=id;


        this.ms=ms;


    }


}


class serverconnet  //服务器监听线程




...{


    ServerSocket localsocket;


    LinkedList<message> mslist;


    static Vector current_thread;


    static int threadnum;


    serverconnet(int port)




    ...{


        try




        ...{


            localsocket =new ServerSocket(port);


        }


        catch(IOException e)




        ...{


            System.out.println("服务器端套接字创建失败,请检查端口是否冲突。如冲突,请换用其它端口");


        }


        mslist=new LinkedList<message>();   //消息链表(用队列比较好.)


        current_thread=new Vector();           //在线列表.(线程列表哦)


        threadnum=current_thread.size();                    //线程数目.(用 在线容器 里线程数量来赋值)


        


        new control(mslist,current_thread).start();   //启动控制线程.(其实这个时候启


                                                //动未必好,因为当没有客户连接过来时,它子线程也一直在运行.浪费CPU


    }


    


    public void work()




    ...{


        System.out.println("正在监听~");


        Socket s=null;


        while(true)




        ...{


            try




            ...{


                s=localsocket.accept();


                System.out.println("接收到一个客户连接请求,它的地址:"+s.getInetAddress());


            }


            catch(IOException e)




            ...{


                System.out.println("接受连接请求出现异常~");


            }


            if(s!=null)




            ...{


                xiancheng thread=new xiancheng(s);


                System.out.println("当前线程编号:"+threadnum);


                thread.setid(threadnum);     //线程ID设置.


                thread.setmsg(mslist);         //将此 消息队列 传参过去.


                


                current_thread.add(threadnum,thread);   //加入在线列表.第一个参数为此对象的索引,类似数组下标。


                threadnum++;


                thread.start();


                


                


            }


        }


    }


    public static void remove(int id)




    ...{


        current_thread.remove(id);


        threadnum--;


        


    }


    


}


class control extends Thread   //控制线程




...{


    LinkedList<message> mslist;


    Vector current_thread;


    int threadnum; //在线线程数目。


    String ms=null;


    control(LinkedList<message> mslist,Vector current_thread)




    ...{


        this.mslist=mslist;


        this.current_thread=current_thread;


    }


    


    public void run()   




    ...{


        while(true)   //这里写得并不高效.可以把链表操作次数再减少,以提高效率.




        ...{


            if(mslist.isEmpty())




            ...{


                try




                ...{


                    Thread.sleep(1000);


                }


                catch(InterruptedException e)




                ...{


                    System.out.println("线程休眠失败.");


                }


                continue;


                //Thread.yield();  //测试发现,此函数并没有很好提高CPU性能,反而是占用率100%


            }


            else




            ...{


                threadnum=current_thread.size();


                ms=new String("线程ID为:"+mslist.getFirst().id+"的客户说:"+mslist.getFirst().ms);


                


                for(int i=0;i<threadnum;i++)




                ...{


                    xiancheng thread=(xiancheng)current_thread.elementAt(i);


                    thread.send(ms);


                }


                mslist.removeFirst();


            }


        }


    }


}


class xiancheng extends Thread  //服务线程




...{


    DataOutputStream out=null;


    DataInputStream in=null;


    String ms=null;


    Socket socket;


    Scanner read;          //读入流对象


    String shiyan;


    


    LinkedList<message> msglist;


    int id=0;


    


    xiancheng(Socket s)




    ...{


        socket=s;


        try




        ...{


            in=new DataInputStream(socket.getInputStream());


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


        }


        catch(IOException e)




        ...{


            System.out.println("这里出现异常~");


        }


    }


    public void run()




    ...{


        while(true)




        ...{


            try




            ...{


                msglist.add(new message(id,in.readUTF()));


            }


            catch(IOException e)




            ...{


                System.out.println("读写异常~,客户端可能已经退出。");


                serverconnet.remove(this.id);         //调用static 方法,移除在线列表。


                break;


            }


        }


    }


    public void send(String ms)




    ...{


        synchronized(out)                   //线程同步~~~~~!!!!!!!!!




        ...{


            try




            ...{


                out.writeUTF(ms);


            }


            catch(IOException e)




            ...{


                System.out.println("线程同步异常:"+e);


            }


        }


    }


    public void setid(int threadnum)   //设置线程编号.




    ...{


        this.id=threadnum;


    }


    public void setmsg(LinkedList<message> mslist)   //设置消息链表.




    ...{


        this.msglist=mslist;


    }


}








public class server 




...{


    public static void main(String args[])




    ...{


        int port=2526;


        System.out.println("请输入服务器监听端口号");


        Scanner reader=new Scanner(System.in);


        port=reader.nextInt();


        serverconnet ss=new serverconnet(port);


        System.out.println("服务器正在监听"+port+"端口,等待客户连接");


        ss.work();


    }


}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息