先编写最简答的服务器

思路

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实现多人聊天(基于命令行)的更多相关文章

  1. java swing+socket实现多人聊天程序

    swing+socket实现多人聊天程序 1.准备工作 先看效果: 客户端项目结构图: 服务端项目结构图: 2.运行原理 服务端 先开一个线程serverListerner,线程中开启一个Server ...

  2. Java使用socket实现两人聊天对话

    import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; /* ...

  3. 如何创建一个基于命令行工具的跨平台的 NuGet 工具包

    命令行可是跨进程通信的一种非常方便的手段呢,只需启动一个进程传入一些参数即可完成一些很复杂的任务.NuGet 为我们提供了一种自动导入 .props 和 .targets 的方法,同时还是一个 .NE ...

  4. Linux下基于命令行的抓包方法

    大家可能都已经对著名的抓包工具Ethereal比较熟悉了,这里再介绍一种基于命令行的抓包工具tcpdump. 举例:抓本机1813端口上的数据,并将抓包结果保存在test.cap文件中 然后在本地可以 ...

  5. POP3:基于命令行的电子邮件(EMail)在线查看和批量下载工具

    使用该工具可以在不安装outlook和foxmail等邮件客户端的情况下快速下载指定邮箱的邮件,并将下载的邮件以eml格式进行保存. 附: 查看eml格式的邮件可使用 EmlReader 工具,该工具 ...

  6. java socket之多人聊天室Demo

    一.功能介绍 该功能实现了一个类似QQ的最简单多人聊天室,如下图所示. 二.目录结构 三.服务端 1)SocketServer类,该类是服务端的主类,主要负责创建聊天窗口,创建监听客户端的线程: pa ...

  7. 基于Socket实现多人聊天室

    当前支持: 1.仅文字 2.加入聊天室提醒 3.退出聊天室提醒 可能出现的BUG: 1.可能出现客户端发送信息后不能及时推送,需要下一个客户端发送信息后一起推送 服务端代码: 1 package co ...

  8. 多线程+socket实现多人聊天室

    最近在学习多线程的时候打算做一个简单的多线程socke聊天的程序,结果发现网上的代码都没有完整的实现功能,所以自己实现了一个demo: demo功能大致就是,有一个服务端负责信息转发,多个客户端发送消 ...

  9. Java 多线程Socket编程通讯--实现聊天室代码

    1.创建服务器类 import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import ja ...

随机推荐

  1. Clickhouse 分布式表&本地表 &ClickHouse实现时序数据管理和挖掘

    一.CK 分布式表和本地表 (1)CK是一个纯列式存储的数据库,一个列就是硬盘上的一个或多个文件(多个分区有多个文件),关于列式存储这里就不展开了,总之列存对于分析来讲好处更大,因为每个列单独存储,所 ...

  2. MySQL创建表、更改表和删除表

    1.创建表 mysql> create table t_address( -> id int primary key auto_increment, // 设置id为主键,自动增值 -&g ...

  3. CDH6.2.0离线安装(详细)

    目录 01 准备工作 02 环境配置 03 CDH安装 报错 01 准备工作 官网地址下载页面:https://www.cloudera.com/downloads/cdh.html,现在下载好像需要 ...

  4. 03-Eureka注册中心

    1.介绍 2.快速开始 2.1 pom文件依赖 <?xml version="1.0" encoding="UTF-8"?> <project ...

  5. SpringBoot入门一:基础知识(环境搭建、注解说明、创建对象方法、注入方式、集成jsp/Thymeleaf、logback日志、全局热部署、文件上传/下载、拦截器、自动配置原理等)

    SpringBoot设计目的是用来简化Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,SpringBoot致力于在蓬勃发 ...

  6. 联邦学习:按混合分布划分Non-IID样本

    我们在博文<联邦学习:按病态独立同分布划分Non-IID样本>中学习了联邦学习开山论文[1]中按照病态独立同分布(Pathological Non-IID)划分样本. 在上一篇博文< ...

  7. 递归——深度优先搜索(DFS)——以滑雪问题为例(自顶而下)

    一.问题:滑雪 问题描述:小明喜欢滑雪,为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.小明想知道在一个区域中最长底滑坡.区域由一个二维数组给出.数组的每 ...

  8. 微信小程序书简易支付

    这里结合了上一篇的手机号登录接下来的实现功能 https://www.cnblogs.com/xiaoyantongxue/p/15472915.html 登录后进入课程选择页面 1:数据库填入数据 ...

  9. C++ STL vector扩容原理分析

    扩容特点: 1)新增元素:vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素: 2)对vector的 ...

  10. 9.Flink实时项目之订单宽表

    1.需求分析 订单是统计分析的重要的对象,围绕订单有很多的维度统计需求,比如用户.地区.商品.品类.品牌等等.为了之后统计计算更加方便,减少大表之间的关联,所以在实时计算过程中将围绕订单的相关数据整合 ...