java socket 线程池_程序员:java使用线程池和TCP实现简单多轮聊天系统

最近在做物联网项目,需要使用TCP和传感器进行双向交互,通过这种渠道,找到了下面的代码,写成博客主要也是为了记录一下,以后用到随时可以看。

代码实现

服务端

package com.tcp;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.io.PrintWriter;

import java.io.ObjectInputStream.GetField;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class TalkServer {

public static int i = 0;

private static final int PORT = 9620; // 端口号

private static List user_list = new ArrayList(); // 保存连接对象

private ExecutorService exec;//线程池

private ServerSocket server;//用来监听端口

public static void main(String[] args) {

// 启动服务器程序

new TalkServer();

}

public TalkServer() {

try {

server = new ServerSocket(PORT);

// 创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们

exec = Executors.newCachedThreadPool();

System.out.println("服务器已启动!");

Socket client = null;

while (true) {

client = server.accept(); // 接收客户连接

user_list.add(client);// 将用户添加进列表

System.out.println("端口号为: " + user_list.get(i).getPort());// 输出用户端口号

i++;// 列表下标加一

exec.execute(new s_talk(client));//运行s_talk方法

}

} catch (IOException e) {

e.printStackTrace();

}

}

static class s_talk implements Runnable {

private Socket socket;

private InputStream is = null;//输入流

private OutputStream os = null;//输出流

private String msg;

public s_talk(Socket socket) throws IOException {

this.socket = socket;

is = this.socket.getInputStream();

msg = "【" + this.socket.getPort() + "】进入聊天室!当前聊天室有【"+ user_list.size() + "】人"+"(";

for(Socket st:user_list){

msg+=st.getPort()+",";

}

msg+=")";

System.out.println(msg);

for (Socket client : user_list) {

os = client.getOutputStream();

os.write(msg.getBytes());//把在线人数信息输出到每个客户端

}

}

public void run() {

try {

int len;

byte[] b = new byte[1024];//字节

while ((len = is.read(b)) != -1) {

msg = new String(b, 0, len);//将数据存储到msg

//私聊判定

if (msg.indexOf("@") != -1) {

int n = 0;

String stt = null;

for (n = 0; n < user_list.size() - 1; n++) {

stt = "" + user_list.get(n).getPort();//将端口号转换为字符串类型

if (msg.indexOf(stt) != -1) {

break;//没找到此端口号,跳出循环

}

}

String Str = null;

int duan = socket.getPort();

String st = "" + duan;

int num1 = st.length();//端口号长度

int num = msg.length();

Str = msg.substring(num1 + 1, num);

os = user_list.get(n).getOutputStream();//将信息存入输出流

os.write((socket.getPort() + "对我说:" + Str).getBytes());//打印出私聊信息

//System.out.println("私聊接收端口"+user_list.get(n).getPort());//在服务器显示私聊端口号及其数据

System.out.println(socket.getPort() +"对"+user_list.get(n).getPort()+ "发送的私聊消息:"+ "发送的数据-------" + Str);

} else

{

//判定退出,trim()用于去掉开头和结尾的空格

if (msg.trim().equals("bye")) {

user_list.remove(socket);// 删除一个元素

is.close();//关闭输入输出流

os.close();

msg = "【" + socket.getPort()+ "】离开聊天室!当前聊天室有【" + user_list.size()+ "】人";

socket.close();

System.out.println(msg);

for (Socket client : user_list) {

os = client.getOutputStream();

os.write(msg.getBytes());

}

break;

} else

{ //群聊

msg = "【" + socket.getPort() + "】说:" + msg;

System.out.println(msg);

for (Socket client : user_list) {

os = client.getOutputStream();

os.write(msg.getBytes());

}

}

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

客户端

package com.tcp;

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.PrintStream;

import java.io.PrintWriter;

import java.net.InetAddress;

import java.net.Socket;

import java.util.Scanner;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class TalkClient {

public static String ip = "127.0.0.1";

private static final int PORT = 9620;

private static ExecutorService exec = Executors.newCachedThreadPool(); // 线程池

public static void main(String[] args) throws Exception {

// 启动客户端函数

new TalkClient();

}

public TalkClient() {

try {

Socket socket = new Socket(ip, PORT); // 连接端口

exec.execute(new c_send(socket));// 启动客户端线程

System.out.println("【" + socket.getLocalAddress() + "】您好,欢迎来到神华客户端!");

InputStream is = null;

is = socket.getInputStream();// 创建输入流

String msg;

int len;

byte[] b = new byte[1024];

while ((len = is.read(b)) != -1) {

msg = new String(b, 0, len);// 将消息存入字节数组并赋给msg

System.out.println(msg);

}

} catch (Exception e) {

e.printStackTrace();

}

}

class c_send implements Runnable {

private Socket socket;// 定义套接字

public c_send(Socket socket) {

this.socket = socket;

}

public void run() {

try {

InputStream is = null;

is = socket.getInputStream();// 获取输入输出流

OutputStream os = null;

os = socket.getOutputStream();

String msg;

while (true) {

String stt = null;

Scanner sc = new Scanner(System.in);// 输入欲发送的信息

msg = sc.next();// 把值返回给msg并打印

os.write(msg.getBytes());

if (msg.trim().equals("bye")) {

is.close();

os.close();

exec.shutdownNow();//关闭线程池

break;

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

实现效果

客户端

68f356ce86badcd81857c26eb207984c.png

服务端

a07e907bbf6da4ce48baa9311a82522d.png

以上代码经过本地测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/511697.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里云李飞飞:中国数据库的时与势

简介&#xff1a;数据库、操作系统和中间件并列为三大基础软件&#xff0c;无论是在银行存取款&#xff0c;还是进行健康码查询&#xff0c;我们的日常应用和企业业务背后都离不开数据库。可以说&#xff0c;没有数据库&#xff0c;就难以构建数字化底座。过去的40多年&#xf…

java 最大矩形_Java实现 LeetCode 85 最大矩形

85. 最大矩形给定一个仅包含 0 和 1 的二维二进制矩阵&#xff0c;找出只包含 1 的最大矩形&#xff0c;并返回其面积。示例:输入:[[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]输出: …

阿里巴巴超大规模 Kubernetes 基础设施运维体系介绍

简介&#xff1a;ASI 作为阿里集团、阿里云基础设施底座&#xff0c;为越来越多的云产品提供更多专业服务&#xff0c;托管底层 K8s 集群&#xff0c;屏蔽复杂的 K8s 门槛、透明几乎所有的基础设施复杂度&#xff0c;并用专业的产品技术能力兜底稳定性&#xff0c;让云产品只需…

数据库资深“学霸”再启程,专访数据库初创公司矩阵起源全球 CTO 田丰博士

师出名门&#xff0c;工业界履历从大厂首席工程师到创业公司 CTO&#xff0c;并能一直从事底层系统的核心研发工作&#xff0c;可能是很多优秀技术人向往的光鲜履历。不过抛弃大厂的光鲜稳定工作和成功的创业项目&#xff0c;再次加入初创公司&#xff0c;则需要比常人更大的魄…

Spring官方RSocket Broker 0.3.0发布: 快速构建你的RSocket架构

简介&#xff1a;Spring官方的RSocket Broker其实开发已经非常久了&#xff0c;我以为会伴随着Spring Cloud 2021.0发布的&#xff0c;但是没有发生。不过Spring RSocket Broker还是发布了最新的0.3版本&#xff0c;虽然还是预览版&#xff0c;但目前已经可用&#xff0c;考虑官…

python sqlite3事务_python使用上下文管理器实现sqlite3事务机制

如题&#xff0c;本文记录如何使用python上下文管理器的方式管理sqlite3的句柄创建和释放以及事务机制。1、python上下文管理(with)python上下文管理(context)&#xff0c;解决的是这样一类问题&#xff0c;在进入逻辑之前需要进行一些准备工作&#xff0c;在退出逻辑之前需要进…

Redis 6 中的多线程是如何实现的!?

作者 | 张彦飞allen来源 | 开发内功修炼Redis 是一个高性能服务端的典范。它通过多路复用 epoll 来管理海量的用户连接&#xff0c;只使用一个线程来通过事件循环来处理所有用户请求&#xff0c;就可以达到每秒数万 QPS 的处理能力。下图是单线程版本 Redis 工作的核心原理图单…

如何构建流量无损的在线应用架构 | 专题开篇

简介&#xff1a;本篇是整个《如何构建流量无损的在线应用架构》系列的第一篇&#xff0c;这一系列共三篇&#xff0c;旨在使用最为朴素的语言将影响在线应用流量稳定性的技术问题做一个归类&#xff0c;这些问题的解决方案有的只是一些代码层面的细节&#xff0c;有的需要工具…

云原生时代的运维体系进化

简介&#xff1a;基于容器、Kubernetes 等云原生技术&#xff0c;提供的开放社区标准、不可变基础设施、声明式 API 会成为企业 CloudOps 的最佳实践&#xff0c;也将在这个基础上推进数据化、智能化体系建设&#xff0c;将运维复杂性进一步下沉&#xff0c;让企业可以聚焦于自…

python 抽象语法树_用python演示一个简单的AST(抽象语法树)

假设对‘a 3 * b‘进行解释&#xff0c;其中a2&#xff0c;b5代码很简单&#xff0c;就不再进行详细的解释了。Num lambda env, n: nVar lambda env, x: env[x]Add lambda env, a, b:_eval(env, a) _eval(env, b)Mul lambda env, a, b:_eval(env, a) * _eval(env, b)_eva…

企业如何从 0 到 1 构建整套全链路追踪体系

简介&#xff1a;本文将分享 ARMS 在全链路追踪领域的最佳实践&#xff0c;分享主要分为四部分。首先&#xff0c;是对分布式链路追踪的整体简介。其次&#xff0c;是对 ARMS 在分布式链路追踪领域的核心能力进行介绍。然后&#xff0c;介绍如何从 0 到 1 构建整套全链路追踪体…

React18 的 useEffect 新特性为什么被疯狂吐槽?

作者 | 零一来源 | 前端印象react18 已经出来一段时间了&#xff0c;create-react-app 默认安装的 React 版本也已经是 18&#xff0c;不知道有没有小伙伴发现自己有点看不懂 React 了&#xff1f;import { useEffect, useState } from reactfunction App () {const [data, set…

如何构建一个流量无损的在线应用架构 | 专题中篇

简介&#xff1a;本篇是整个《如何流量无损的在线应用架构》系列的第二篇&#xff0c;这一系列共三篇&#xff0c;旨在使用最为朴素的语言将影响在线应用流量稳定性的技术问题做一个归类&#xff0c;这些问题的解决方案有的只是一些代码层面的细节&#xff0c;有的需要工具进行…

一文读懂蓝绿发布、A/B 测试和金丝雀发布的优缺点

简介&#xff1a;目前&#xff0c;业界已经总结出了几种常见的服务发布策略来解决版本升级过程中带来的流量有损问题。本文首先会对这些普遍的发布策略进行简单的原理解析&#xff0c;最后结合阿里云的云原生网关对这些发布策略进行实践。 作者 | 扬少 背景 目前&#xff0c…

Kafka 到底有多高可靠?

作者 | 敖丙来源 | 敖丙什么叫可靠性&#xff1f;大家都知道&#xff0c;系统架构有三高&#xff1a;「高性能、高并发和高可用」&#xff0c;三者的重要性不言而喻。对于任意系统&#xff0c;想要同时满足三高都是一件非常困难的事情&#xff0c;大型业务系统或者传统中间件都…

java is start_PHP IntlChar::isJavaIDStart()用法及代码示例

IntlChar::isJavaIDStart()函数是PHP中的一个内置函数&#xff0c;用于检查输入字符代码点是否允许&#xff0c;因为第一个字符是Java标识符。对于具有常规类别“Sc”(货币符号)和“Pc”(连接标点符号)的字符而言&#xff0c;它是正确的。用法:bool IntlChar::isJavaIDStart( $…

阿里云张振尧:阿里云边缘云驱动5G时代行业新价值

简介&#xff1a;近日&#xff0c;以“5G融合通信趋势下的技术创新”为主题的2021中国增值电信及虚拟运营高峰论坛在北京召开&#xff0c;阿里云边缘云高级产品专家张振尧发表了《阿里云边缘云驱动5G时代行业新价值》主题演讲&#xff0c;分享了阿里云边缘云作为5G时代的新基础…

美的工业技术亮相2022汉诺威工业博览会,助力全球工业向数字化与可持续迈进

2022年5月31日&#xff0c;2022汉诺威工业博览会开幕并重启线下展览&#xff0c;美的工业技术以“科技驱动&#xff0c;拥抱高效、绿色、智能的工业未来”为主题&#xff0c;携旗下工业自动化品牌“高创”、 “合康新能”和“东菱”&#xff0c;以覆盖自动化、绿色能源领域的领…

vue 传递 对象 路由_vue中路由参数传递可能会遇到的坑

前言vue中路由跳转传参数有多种,自己常用的是下面的几种通过router-link进行跳转通过编程导航进行路由跳转本文主要给大家介绍了关于vue路由参数传递遇到的一些坑&#xff0c;分享出来供大家参考学习&#xff0c;下面话不多说了&#xff0c;来一起看看详细的介绍吧。首先我的路…

hyengine - 面向移动端的高性能通用编译/解释引擎

简介&#xff1a;手机淘宝客户端在历史上接过多种多样的脚本引擎&#xff0c;用于支持的语言包括&#xff1a;js/python/wasm/lua&#xff0c;其中js引擎接过的就有&#xff1a;javascriptcore/duktape/v8/quickjs 等多个。众多的引擎会面临共同面临包大小及性能相关的问题&…