QQ-服务器端增加广播,客户端读取服务器

来源:互联网 发布:域名再长狼也能记住 编辑:程序博客网 时间:2024/06/06 08:34

功能:

客户端:从控制台发到服务器端,再接收服务器端返回的信息,打印到控制台

服务器端:从一个控制台读消息,发给所有连接到服务器的客户端上,实际上实现了群聊的机制,即服务器广播一个客户端发送的消息。

FirstServer.java

package com.InetAddress;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketException;import java.util.Collections;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class FirstServer {//线程安全Set集合public static Set<Socket> clients = Collections.synchronizedSet(new HashSet<Socket>());public static void main(String[] args) throws IOException {//ServerSocket只负责接收连接ServerSocket ss = new ServerSocket(9999);System.out.println("服务器正在等待连接:");while(true){//Socket会阻塞线程Socket s = ss.accept();//每当有一个客户端连接就把该客户端的socket加入到set集合中clients.add(s);System.out.println("已连接");System.out.println(clients);System.out.println("客户端的数量:"+clients.size());new ServerThread(s).start();   }} }class ServerThread extends Thread{private Socket socket;public ServerThread(Socket socket){this.socket = socket;}public void run(){/* * 从socket里面读,然后打印到控制台 */try{//使用BufferedReader的好处是可以一次读一行BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));    String line = null;while((line = br.readLine())!=null){//for(Socket s : FirstServer.clients){//用迭代器来遍历HashSet集合for(Iterator<Socket> it = FirstServer.clients.iterator();it.hasNext(); ){Socket s = it.next();try{//往socket里面写,println()一次就会清空一次PrintStream ps = new PrintStream(s.getOutputStream());System.out.println(line);//打印到控制台ps.println(line);//输出到各客户端的socket,就相当于打印到客户端控制台上}catch(SocketException sex){//此时捕获到的异常即是客户端断开连接时会产生的SocketException,要把这个客户端从set集合中删除    //此处可以不做任何处理,只要在最后捕获SocketException就可以了it.remove();//sex.printStackTrace();}catch(Exception ex){ex.printStackTrace();}}}//while}catch(SocketException sex){//把退出的客户端的socket从集合中删除FirstServer.clients.remove(socket);}catch(Exception ex){ex.printStackTrace();}}//run() }//Thread


 

FirstClient.java

package com.InetAddress;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.Socket;public class FirstClient {public static void main (String[] args) throws IOException {Socket s = new Socket("127.0.0.1",9999);new ClientThread(s).start();/* *从控制台读,往socket里写  *///把字节流转化成字符流,从控制台读InputStreamReader reader = new InputStreamReader(System.in);//使用BufferedReader的好处是可以一次读一行BufferedReader br = new BufferedReader(reader);//往socket里面写,println()一次就会清空一次PrintStream ps = new PrintStream(s.getOutputStream());String keyline = null;while((keyline = br.readLine())!=null){//打印到控制台//System.out.println(keyline);//发送到socket里ps.println(keyline);}}}class ClientThread extends Thread{private Socket socket;public ClientThread(Socket socket){this.socket = socket;}public void run(){try {/* *从socket读,打印到控制台  *///把字节流转化成字符流,从socket读InputStreamReader reader1 = new InputStreamReader(socket.getInputStream());//使用BufferedReader的好处是可以一次读一行BufferedReader br1 = new BufferedReader(reader1);//往socket里面写,println()一次就会清空一次//PrintStream ps = new PrintStream(s.getOutputStream());String keyline1 = null;while((keyline1 = br1.readLine())!=null){//打印到控制台System.out.println(keyline1);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}


 此处客户端加线程是因为

1.从控制台读,往socket里写是一个死循环

2,从socket里读,往控制台写也是一个死循环

如果client端不起线程,两个死循环(都是阻塞式)不可能同时执行

0 0
原创粉丝点击