最近在做物联网项目,需要使用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();

}

}

}

}

实现效果

客户端

服务端

以上代码经过本地测试。

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

  1. java post请求 json_好程序员Java教程分享Vue插件之Axios

    好程序员Java教程分享Vue插件之Axios 环境安装: npm install --save axios vue-axios //安装axios Npm install //安装依赖 在main. ...

  2. java压测请求线程数_程序员撕开京东 618 大促压测的另一面 | 原力计划

    作者 | 天涯泪小武 责编 | 王晓曼 出品 | CSDN博客 前天618大促演练进行了全链路压测,在此之前刚好我的热key探测框架也已经上线灰度一周了,小范围上线了几千台服务器,每秒大概接收几千个k ...

  3. java excel 插件开发工具_程序员常用的15 种开发者工具推荐

    程序员常用的15 种开发者工具推荐:Java 线上诊断工具 Arthas.IDE 插件 Cloud Toolkit.混沌实验注入工具 ChaosBlade.Java 代码规约扫描插件.应用实时监控工具 ...

  4. java斗图表情_程序员之间的斗图表情包, java真的输惨了!

    表情包成了人与人聊天中不可少的分量,陌生人聊天表情包丢出去妥妥的拉近关系变熟络啊(¬_¬) 而且可以用表情包化解尴尬.缓解气氛,可以没话找话.忙的时候也可以当做结束语,显得比较有礼貌! 对于沉默寡言. ...

  5. java数据库的量级_程序员学Python还是Java?分析了8张图后得出这个结论

    Java和Python两门语言都是目前非常热门的语言,可谓北乔峰南慕容,二者不分上下,棋逢对手.但是对于初学者来说,非常困惑,因为时间和精力有限,上手必须要先学一门,到底选那个好呢,今天3分钟带你透彻 ...

  6. java装逼的话_程序员装逼指南(语言篇)

    原标题:程序员装逼指南(语言篇) 语言:千万不要说自己是做Java或者.Net的,一下子就屌丝了.PHP现在也不行,Python稍微有点烂大街,但还是明显要强过前几个.剩下的可以说自己是做Ruby的, ...

  7. java异步队对联_程序员的春节对联集锦

    上联:为系统而生,为框架而死,为debug奋斗一辈子! 下联:吃符号的亏,上大小写的当,最后死在需求上! 横批:杯具程序员. 上联:算法数据思路清晰 下联:编译链接一气呵成 横批:码到功成 上联:思前 ...

  8. java占位符填充_程序员:深入理解Java虚拟机,对象的内存布局

    在 HotSpot 虚拟机中,对象在内存中存储的布局分为 3 块区域:对象头 ( Header ) .实例数据 ( InstanceData ) 和对齐填充 (Padding) . 一.对象的内存布局 ...

  9. java 证书查看工具_程序员必备工具 Java证书工具Keytool的使用

    一.简介 Keytool是JDK自带的证书管理工具,在jdk/bin目录下,可以用来生成自签名证书.导入导出证书.打印证书信息等. 回顾下前一章的一些概念:PKI:公钥基础设施 X.509 : PKI ...

最新文章

  1. TCC分布式事务的实现原理
  2. [译] Robinhood 为什么使用 Airflow
  3. angularjs与java_关于angularjs与java结合,获取后台数据并解析的问题
  4. Shell 显示带颜色字体
  5. linux写聊天程序,轻易实现基于linux或win运行的聊天服务端程序
  6. SAP Spartacus里,点击checkbox右边的span文本,不会触发checkbox勾选的原因
  7. python怎么输出结果_Python中print()常用输出方法
  8. 将XML解析成DOM文档
  9. 准备入行Web前端,又担心适不适合,怎么办?
  10. [C] 库函数 sprintf() 和 snprintf()
  11. 服务器cpu哪个型号超频,服务器CPU也超频,AMD霄龙性能暴涨1.5倍-控制器/处理器-与非网...
  12. “ +”(加号)CSS选择器是什么意思?
  13. shell编写三角函数_VB中三角函数计算.doc
  14. 零基础学VB6.0仿真:用四阶龙格库塔法计算传递函数状态方程的结果
  15. (已解决)INSTALL_FAILED_CONFLICTING_PROVIDER虚拟机安装失败错误
  16. PS不改变图片分辨率条件下改变照片kb大小
  17. pose_subscriber.cpp
  18. Codeforces Round #439 (Div. 2) E. The Untended Antiquity (hash+数状数组)
  19. java中jar文件
  20. Qt(mingw)+GDAL位图转矢量图写入shp或json文件

热门文章

  1. 多所高校通知:暂缓返校
  2. 在读博士生 2 年实现 Nature、Science 双发,他来自这所高校!
  3. 被单位开除、摆地摊、住酒店带脸盆被褥,还你一个真实的陈景润
  4. 35岁北大博士拟升市长
  5. 知名大学博士毕业都去哪儿?55所高校大数据揭秘
  6. 如何理解马尔可夫决策过程?
  7. python增删改查mysql_python对数据库mysql的操作(增删改查)
  8. Linux网络编程--文件描述符
  9. Almost Arithmetical Progression
  10. JanusGraph 安装