java线程池_程序员: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();

}

}

}

}

实现效果

客户端

19e6b97ff9ce152f4c6a593212e5108f.png

服务端

e42ebb89494771e1feb4478ef3331493.png

以上代码经过本地测试。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本例子就是Delphi中如何利用Socket编写通信程序。 计算机网络是由一系列网络通信协议组成的,其中的核心协议是传输层的TCP/IP和UDP协议。TCP是面向连接的,通信双方保持一条通路,好比目前的电话线使用telnet登陆BBS,用的就是TCP协议;UDP是无连接的,通信双方都不保持对方的状态,浏览器访问Internet时使用的HTTP协议就是基于UDP协议的。TCP和UDP协议都非常复杂,尤其是TCP协议,为了保证网络传输的正确性和有效性,必须进行一系列复杂的纠错和排序等处理。   Socket是建立在传输层协议(主要是TCP和UDP)上的一种套接字规范,最初是由美国加州Berkley大学提出,它定义两台计算机间进行通信的规范(也是一种编程规范),如果说两台计算机是利用一个“通道“进行通信,那么这个“通道“的两端就是两个套接字。套接字屏蔽了底层通信软件和具体操作系统的差异,使得任何两台安装了TCP协议软件和实现了套接字规范的计算机之间的通信成为可能。   微软的Windows Socket规范(简称winsock)对Berkley的套接字规范进行了扩展,利用标准的Socket的方法,可以同任何平台上的Socket进行通信;利用其扩展,可以更有效地实现在Windows平台上计算机间的通信。在Delphi中,其底层的Socket也应该是Windows的Socket。Socket减轻了编写计算机间通信软件的难度,但总的说来还是相当复杂的(这一点在后面具体会讲到);Inprise在Delphi中对Windows Socket进行了有效的封装,使得用户可以很方便地编写网络通信程序。 本例子就是Delphi中如何利用Socket编写通信程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值