上一篇: Java Socket 基于UDP协议的多线程连接
- 思路:
- 所有人都访问一个地址和端口号
- 用户接受消息都单独放在一个开启了线程的类里面
- 在主方法Client里面调用这两个线程类
- 服务器用一个List集合来保存连接的用户Socket连接,并且用一个不终止
- 的循环不断开启线程来接受和发送Socket消息,接受一个Socket
- 连接后,将Socket保存在List集合中,并且将消息发送给非当前发送消
- 息用户的用户Socket。这样简单的实现类多人Socket聊天,相当于一
- QQ讨论组一样的形式.
项目结构
ThreadWriter.java源码
package cjj.online.cn; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; /** *@author:蔡佳君 *@date:2017年12月7日 上午10:57:34 *@version: *@description:用户输入,保存到socket中去 */ public class ThreadWriter extends Thread{ Socket socket; public ThreadWriter(Socket socket) { this.socket = socket; } public void run() { try { Scanner sc = new Scanner(System.in); int i = 0; while(true) { System.out.println("第的" + i++ + "条消息:"); String str = sc.next(); OutputStream os = socket.getOutputStream(); //将输入的字符写入到利用输出流写到socket中保存 os.write(str.getBytes()); } } catch (IOException e) { e.printStackTrace(); } } }
TheadReader.java源码
package cjj.online.cn; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.ArrayList; /** *@author:蔡佳君 *@date:2017年12月7日 上午11:04:50 *@version: *@description: */ public class TheadReader extends Thread{ Socket socket; public TheadReader(Socket socket) { this.socket = socket; } @Override public void run() { try { while(true) { //利用输出流得到socket中的消息. InputStream is = socket.getInputStream(); byte[] b = new byte[1024]; //读取到字节b中,并获取字节的个数。 int len = is.read(b); //转化为字符 String str = new String(b,0,len); System.out.println(str); } } catch (IOException e) { e.printStackTrace(); } super.run(); } }
ServerThread.java源码
package cjj.online.cn; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.ArrayList; /** *@author:蔡佳君 *@date:2017年12月7日 上午10:31:09 *@version: *@description:有多个客户端时,就会开启多个socket连接, *得到发送socket消息的socket。发送给其他未发送socket消息的 *客户端 */ public class ServerThread extends Thread{ Socket socket; ArrayList<Socket> list; InputStream is; OutputStream os; public ServerThread(Socket socket,ArrayList<Socket> list) { this.socket = socket; this.list = list; } @Override public void run() { try { while(true) { //得到一个客户端的消息 is = socket.getInputStream(); byte[] b = new byte[1024]; int len = is.read(b); String str = new String(b,0,len); System.out.println(str); for(Socket socket:list) { //避免socket消息自己发给自己 if(this.socket != socket) { os = socket.getOutputStream(); //输出流 写到socket中去 os.write(str.getBytes()); } } } } catch (Exception e) { e.printStackTrace(); } } }
Client.java, Server.java源码
package cjj.online.cn; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; /** *@author:蔡佳君 *@date:2017年12月7日 上午10:56:37 *@version: *@description: */ public class Client { public static void main(String[] args) throws Exception { Socket socket = new Socket("127.0.0.1",8888); new ThreadWriter(socket).start(); new TheadReader(socket).start(); } } ------------------------------------------------------------- package cjj.online.cn; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; /** *@author:蔡佳君 *@date:2017年12月7日 上午10:27:43 *@version: *@description: */ public class Server { private static ArrayList<Socket> list = new ArrayList<Socket>(); public static void main(String[] args) throws IOException { @SuppressWarnings("resource") ServerSocket server = new ServerSocket(8888); while(true) { //如果队列中没有等待的连接,套接字也没有被标记为Non-blocking,accept()会阻塞调用函数直到连接出现 Socket socket = server.accept(); //将连接的socket放到一个list集合 list.add(socket); new ServerThread(socket,list).start(); } } }