java-网络通信--socket实现多人聊天(基于命令行)
先编写最简答的服务器
思路
1编写一个实现Runnable接口的静态内部类 ServerC,便于区分每个客户端
1.1 获取客户端数据函数 public String remsg()
1.2 转发消息给所有客户端(自己除外) public void allsend(String data)
1.3 释放资源 public void release()
1.4编写接口重写方法 public void run(),调用收消息和发消息方法。 2server主函数监听客户端的请求
每次的客户端请求都将对应的 ServerC 保存到一个集合当中
最后开启一个线程单独对应
package chat; import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList; public class ServerChat {
private static CopyOnWriteArrayList<ServerC> all = new CopyOnWriteArrayList<>(); public static void main(String[] args) throws IOException {
System.out.println("##################Server##############");
ServerSocket server = new ServerSocket(8888);
while (true){
Socket socket = server.accept();
System.out.println("进入");
ServerC serverC = new ServerC(socket);
all.add(serverC);
//使用多线程分离各个客户端
new Thread(serverC).start();
}
} static class ServerC implements Runnable{
private Socket socket;
private DataOutputStream dos;
private DataInputStream dis; public ServerC(Socket socket) {
this.socket = socket;
try {
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
release();
}
} /**
* 获取客户端data
* @return
*/
public String remsg(){
//接受消息
String data = null;
try {
data = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return data; }
//消息转发给所有人函数
public void transaction(String data){
try{
dos.writeUTF(data);
dos.flush();
}catch (Exception e){
release();
}
} //群发给客户端
public void allsend(String data) {
for (ServerC serverC : all) {
if (this == serverC) {
continue;
} else {
serverC.transaction(data);
} }
} //释放资源函数
public void release(){
try {
dos.close();
dis.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
} } @Override
public void run() {
String data = remsg();
allsend(data);
}
} }
编写客户端的收消息类:
package chat; import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket; public class ClientResevice implements Runnable{
private Socket socket;
private DataInputStream dis; public ClientResevice(Socket socket) {
this.socket = socket;
try {
this.dis = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
release();
}
} @Override
public void run() {
while (true){
//接受消息
String msg = receive();
if(!msg.isEmpty()){
System.out.println(msg);
}
}
} /**
* 接受消息函数
* @return返回消息
*/
public String receive(){
String msg = null;
try {
msg = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
release();
}
return msg;
} //释放资源函数
public void release(){
try {
dis.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端发消息类:
package chat; import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket; /**
* 创建发送消息线程类,发送和接受分开
*/
public class ClientSend implements Runnable{
private BufferedReader console;
private DataOutputStream dos;
private Socket socket; /**
* 建立发送消息线程类的构造函数
* @param socket
*/
public ClientSend( Socket socket){
this.socket = socket;
this.console = new BufferedReader(new InputStreamReader(System.in));
try {
this.dos = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
this.release();
}
} /**
* 实现Runnable里面的run方法
*/
@Override
public void run() {
while (true){
send();
}
} /**
*获取命令函输入函数
* @return
*/
public String conin(){
String msg = null;
try {
msg = console.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return msg;
} /**
* 发送函数
*/
public void send(){
String msg = conin();
if(!msg.isEmpty()){
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
} //释放资源函数
public void release(){
try {
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端代码,主要怎么使用发收消息类:
package chat; import java.io.*;
import java.net.Socket; public class FirstClient { public static void main(String[] args) throws IOException {
System.out.println("##############client################");
Socket socket = new Socket("127.0.0.1",8888);
// 启动发送消息线程
new Thread(new ClientSend(socket)).start();
// 启动接受线程
new Thread(new ClientResevice(socket)).start();
}
}
java-网络通信--socket实现多人聊天(基于命令行)的更多相关文章
- java swing+socket实现多人聊天程序
swing+socket实现多人聊天程序 1.准备工作 先看效果: 客户端项目结构图: 服务端项目结构图: 2.运行原理 服务端 先开一个线程serverListerner,线程中开启一个Server ...
- Java使用socket实现两人聊天对话
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; /* ...
- 如何创建一个基于命令行工具的跨平台的 NuGet 工具包
命令行可是跨进程通信的一种非常方便的手段呢,只需启动一个进程传入一些参数即可完成一些很复杂的任务.NuGet 为我们提供了一种自动导入 .props 和 .targets 的方法,同时还是一个 .NE ...
- Linux下基于命令行的抓包方法
大家可能都已经对著名的抓包工具Ethereal比较熟悉了,这里再介绍一种基于命令行的抓包工具tcpdump. 举例:抓本机1813端口上的数据,并将抓包结果保存在test.cap文件中 然后在本地可以 ...
- POP3:基于命令行的电子邮件(EMail)在线查看和批量下载工具
使用该工具可以在不安装outlook和foxmail等邮件客户端的情况下快速下载指定邮箱的邮件,并将下载的邮件以eml格式进行保存. 附: 查看eml格式的邮件可使用 EmlReader 工具,该工具 ...
- java socket之多人聊天室Demo
一.功能介绍 该功能实现了一个类似QQ的最简单多人聊天室,如下图所示. 二.目录结构 三.服务端 1)SocketServer类,该类是服务端的主类,主要负责创建聊天窗口,创建监听客户端的线程: pa ...
- 基于Socket实现多人聊天室
当前支持: 1.仅文字 2.加入聊天室提醒 3.退出聊天室提醒 可能出现的BUG: 1.可能出现客户端发送信息后不能及时推送,需要下一个客户端发送信息后一起推送 服务端代码: 1 package co ...
- 多线程+socket实现多人聊天室
最近在学习多线程的时候打算做一个简单的多线程socke聊天的程序,结果发现网上的代码都没有完整的实现功能,所以自己实现了一个demo: demo功能大致就是,有一个服务端负责信息转发,多个客户端发送消 ...
- Java 多线程Socket编程通讯--实现聊天室代码
1.创建服务器类 import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import ja ...
随机推荐
- RFC3918组播组容量测试——网络测试仪实操
一.简介 1.RFC3918简介 历史 · 在1999年3月成为正式标准 功能 · 评测网络互连设备或网络系统的性能 · 网络设备: 交换机,路由器- 内容 · 定义了一整套测试方法,为不同厂家的设备 ...
- golang监听rabbitmq消息队列任务断线自动重连接
需求背景: goalng常驻内存任务脚本监听rbmq执行任务 任务脚本由supervisor来管理 当rabbitmq长时间断开连接会出现如下图 进程处于fatal状态 假如因为不可抗拒因素,rabb ...
- 服务器CPU很高-怎么办(Windbg使用坑点)
最近,碰到了一个线上CPU服务器很高的问题,并且也相当紧急,接到这个任务后,我便想到C#性能分析利器,Windbg. 终于在折腾半天之后,找出了问题,成功解决,这里就和大家分享一下碰到的问题. 问题1 ...
- input框限制输入金额
HTML: <input type="tel" class="capital mui-input-clear" value="0.00" ...
- redis主从复制,哨兵以及集群搭建部署
redis主从复制 1.redis支持多实例的功能,一台机器上,可以运行多个单个的redis数据库 环境准备,运行3个redis数据库,达到 1主 2从的配置 主库 6379.conf port 63 ...
- PyTorch深度学习实践——多分类问题
多分类问题 目录 多分类问题 Softmax 在Minist数据集上实现多分类问题 作业 课程来源:PyTorch深度学习实践--河北工业大学 <PyTorch深度学习实践>完结合集_哔哩 ...
- Qt:lambda表达式
说明 c11之后加入了lambda表达式,所以Qt也支持 加载项 CONFIG += c++11 用法 [ capture ] ( parameters ) mutable -> return_ ...
- Go基础知识梳理(四)
Go基础知识梳理(四) GO的哲学是"不要通过共享内存来通信,而是通过通信来共享内存",通道是GO通过通信来共享内存的载体. rumtime包常用方法 runtime.NumGor ...
- 居然可以像玩游戏一样学Git
工作中经常用到 git,但是用到的指令也都是比较初级的.简单的.当时学习的过程也是有点痛苦.各种概念理解起来要么靠想象,要么自己创建工程提交记录,然后执行指令,看具体效果.这样学下来是事倍功半. 在搜 ...
- Linux CentOS7.X-文件操作命令
一.文件新增,touch 1.touch fileName,其中fileName表示文件名称,代表创建一个空文件: 2.touch fn1 fn2 fn3....fnn,其中fn1至fnn表示n个不同 ...