java多线程服务器,实现客户端间聊天
来源:互联网 发布:淘宝开发者平台 api 编辑:程序博客网 时间:2024/05/13 11:37
转载请注明出处:http://blog.csdn.net/htwhtw123/article/details/78762364
通过服务器中转消息,实现多客户端之间的对话。客户端输入格式为:接受消息的客户端编号+空格+要发出的消息。客户端输入end下线。有客户端上线或下线,服务器都会通知其他客户端情况。效果如下图:
1.服务端
服务端为连接上的每一个客户端,提供一个接受线程,监听接受消息,在向客户端发送消息时会临时开启一个发送线程。
import java.io.IOException;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;import java.util.List;/** * Created by HeTingwei on 2017/12/9. * 多线程服务器,实现多客户端聊天 */public class Server { List<ReceiveThread> receiveList = new ArrayList<>();//存放已连接客户端类 private final static int MESSAGE_SIZE = 1024;//每次允许接受数据的最大长度 int num = 0;//客户端编号 public static void main(String[] args) { new Server(); } //服务端处理逻辑 Server() { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(45678);//用来监听的套接字,指定端口号 while (true) { Socket socket = serverSocket.accept();//监听客户端连接,阻塞线程 System.out.println("连接上客户端:" + num);//在其他线程处理接收来自客户端的消息 ReceiveThread receiveThread = new ReceiveThread(socket, num); receiveThread.start(); receiveList.add(receiveThread); //有客户端新上线,服务器就通知其他客户端 String notice="有新客户端上线,现在在线客户端有:客户端:"; for (ReceiveThread thread : receiveList) { notice = notice + "" + thread.num; } for (ReceiveThread thread : receiveList) { new SendThread(thread.socket, notice).start(); } num++; } } catch (IOException e) { e.printStackTrace(); } } //接受消息的线程(同时也有记录对应客户端socket的作用) class ReceiveThread extends Thread { int num; Socket socket;//客户端对应的套接字 boolean continueReceive = true;//标识是否还维持连接需要接收 public ReceiveThread(Socket socket, int num) { this.socket = socket; this.num = num; try { //给连接上的客户端发送,分配的客户端编号的通知 socket.getOutputStream().write(("你的客户端编号是" + num).getBytes()); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { super.run(); //接收客户端发送的消息 InputStream inputStream = null; try { inputStream = socket.getInputStream(); byte[] b; while (continueReceive) { b = new byte[MESSAGE_SIZE]; inputStream.read(b); b = splitByte(b);//去掉数组无用部分 //发送end的客户端断开连接 if (new String(b).equals("end")) { continueReceive = false; receiveList.remove(this); //通知其他客户端 String message = "客户端" + num + "连接断开\n" + "现在在线的有,客户端:"; for (ReceiveThread receiveThread : receiveList) { message = message + " " + receiveThread.num; } System.out.println(message); for (ReceiveThread receiveThread : receiveList) { new SendThread(receiveThread.socket, message).start(); } } else { try { String[] data = new String(b).split(" ", 2);//以第一个空格,将字符串分成两个部分 int clientNum = Integer.parseInt(data[0]);//转换为数字,即客户端编号数字 //将消息发送给指定客户端 for (ReceiveThread receiveThread : receiveList) { if (receiveThread.num == clientNum) { new SendThread(receiveThread.socket, "客户端"+num+"发消息:"+data[1]).start(); System.out.println("客户端" + num + "发送消息到客户端" + receiveThread.num + ": " + data[1]); } } } catch (Exception e) { new SendThread(socket, "输入错误,请重新输入").start(); System.out.println("客户端输入错误"); } } } } catch (IOException e) { e.printStackTrace(); } finally { try {//关闭资源 if (inputStream != null) { inputStream.close(); } if (socket != null) { socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } //发送消息的线程 class SendThread extends Thread { Socket socket; String str; public SendThread(Socket socket, String str) { this.socket = socket; this.str = str; } @Override public void run() { super.run(); try { socket.getOutputStream().write(str.getBytes()); } catch (IOException e) { e.printStackTrace(); } } } //去除byte数组多余部分 private byte[] splitByte(byte b[]) { int i = 0; for(;i<b.length;i++) { if (b[i] == 0) { break; } } byte[] b2 = new byte[i]; for (int j = 0; j <i ; j++) { b2[j] = b[j]; } return b2; }}
2.客户端
在主线程中接受键盘输入,并发送消息,在子线程中接受消息。
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.util.Scanner;/** * Created by HeTingwei on 2017/12/9. * 多线程客户端 */public class Client { Socket socket; private static final int MESSAGE_SIZE = 1024;//每次允许接受数据的最大长度 public static void main(String[] args) { new Client(); } public Client() { try { socket = new Socket("127.0.0.1", 45678); if (socket.isConnected() == true) { System.out.println("连接成功"); new Thread() {//开启一个接受数据的线程 @Override public void run() { super.run(); InputStream in; try { in = socket.getInputStream(); byte[] b; while (true) { b = new byte[MESSAGE_SIZE]; in.read(b); System.out.println("接收到服务端消息:" + new String(b)); } } catch (IOException e) { e.printStackTrace(); } } }.start(); } OutputStream out = null; while (true) { Scanner scanner = new Scanner(System.in); String str = scanner.nextLine(); out = socket.getOutputStream(); out.write(str.getBytes()); out.flush(); if (str.equals("end")) { System.exit(0);//关闭客户端 } } } catch (IOException e) { e.printStackTrace(); } }}
阅读全文
0 0
- java多线程服务器,实现客户端间聊天
- 【Java】Java多线程实现的聊天客户端和服务器
- Java 利用 Socket 实现服务器客户端聊天
- Java 实现TCP网络聊天[服务器-客户端]UI界面
- 在Linux下用多线程实现两台客户端通过服务器进行聊天,类似qq功能
- 利用 Socket 实现服务器客户端聊天
- Java聊天软件服务器+客户端源码---…
- 【Java】NIO 客户端-服务器 聊天 例子
- java使用多线程编程,实现socket服务器客户端交互
- java实现tcp服务器(单线程、多线程)、客户端
- java多线程<二>TCP/IP实现简单的多客户端聊天
- 在java网络编程中实现服务器和客户端一对一的聊天
- 聊天服务器-客户端
- Java实现多个客户端聊天程序
- Java实现多个客户端聊天程序
- JAVA Socket实现多客户端聊天
- Java网络----Socket, 多线程实现内网多人聊天及一对一聊天
- Linux 多线程聊天服务器
- opencv4android开发记录(2):简单文字检测
- 在VMware虚拟机中手动安装VMware Tools
- EE必知—1
- CentOS 7.X 配置mongoDB(阿里)
- 坚持or放弃?
- java多线程服务器,实现客户端间聊天
- docker 启动mysql
- LA 3135 Argus
- 文件操作
- 文章标题
- 2017-12-9 pat b review&think
- deepin Linux 安装nodejs
- Least squares
- CF-897B.Chtholly's request