/**/ /* * 功能:聊天的客户端 *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(); }}