title: Java多线程实现多客户端的通信
date: 2019-05-05 12:50:00

Java多线程实现多客户端的通信

昨天学了Java中网络支持Socket应用,写了一个基于TCP通信的简陋的登录案例,代码如下:

服务器端:

package com.youdian.singinscoket;
​
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
​
/**** 基于TCP协议的Socket,实现用户登录* 服务器端* @author hkq**/
public class Servert {public static void main(String[] args) {try {//1.创建一个服务器端的Socket,即ServerSocket,指定绑定的端口,并监听此端口ServerSocket serverSocket=new ServerSocket(8088);//2.调用accept()方法开始监听.System.out.println("服务器端启动,等待客户端连接");Socket socket= serverSocket.accept();//3.获取字节输入流,并读取客户端信息InputStream is=socket.getInputStream();//4.将字节流装换为字符流,好处是提高读取的效率InputStreamReader isr=new InputStreamReader(is);//5.搭配使用,为字符输入流添加缓冲BufferedReader br=new BufferedReader(isr);//6.定义String类型的info,循环读取客户端信息并在控制台输出String info=null;while ((info=br.readLine())!=null) {System.out.println("服务器端接收到客户端数据为:"+info);  }//7.关闭socket输入流socket.shutdownInput();//8.获取输出流,响应客户端的请求OutputStream os =socket.getOutputStream();//将字节输出流转换为打印输出流PrintWriter pw=new PrintWriter(os);//服务器端向客户端发送响应信息pw.write("登录成功,欢迎你");//调用flush()方法刷新缓存pw.flush();//9.关闭资源pw.close();os.close();br.close();isr.close();is.close();socket.close();serverSocket.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}
​}
​
}
客户端:
package com.youdian.singinscoket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
​
/**** 客户端* @author hkq**/
public class Client {
​public static void main(String[] args) {try {//1.创建客户端Socket,指定`服务器地址和端口Socket socket=new Socket("127.0.0.1", 8088);//2.连接建立后,通过获取字节输出流读取服务器发送信息OutputStream os =socket.getOutputStream();//将字节输出流转换为打印输出流PrintWriter pw=new PrintWriter(os);//向服务器端发送用户信息请求pw.write("用户名: admin;密码: 123");//刷新缓存pw.flush();//关闭scoket的输出流socket.shutdownOutput();//获取输入流,并读取服务器端的响应信息InputStream is=socket.getInputStream();//将字节流装换为字符流,好处是提高读取的效率InputStreamReader isr=new InputStreamReader(is);//搭配使用,为字符输入流添加缓冲BufferedReader br=new BufferedReader(isr);//定义String类型的info,循环读取服务器信息响应并在控制台输出String info=null;while ((info=br.readLine())!=null) {System.out.println("客户端接收到服务器端数据为:"+info);  }//关闭所有资源br.close();is.close();pw.close();os.close();socket.close();} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}
​}
​
}
​

运行的时候,一定是服务器端的代码先运行,因为客户端的代码先运行会因为找不到服务器端的出现错误提示.....

其实,实际开发中,不可能如上述代码实现服务器端和客户端的通信,因为这个只是点对点的通信方式,不可能为了一个客户端通信单独用一个服务器(有钱任性的,当我没说哈!!!土豪交个朋友!)好了,言归正传,使用多线程实现多客户端的通信,下面直接在上述代码上更改......

创建一个serverThread类继承Thread类,用来处理服务器线程,代码如下:

package com.youdian.singinscoket;
/***
* 服务器线程处理类
* @author hkq
*
*/
​
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
​
public class ServerThread extends Thread {
//和本线程相关的Socket
Socket socket=null;
​
public ServerThread(Socket socket) {
this.socket=socket;
}
//线程执行的操作,响应客户端的请求
public void run() {
InputStream is=null;
InputStreamReader isr =null;
BufferedReader br=null;
PrintWriter pw=null;
OutputStream os=null;
try { //获取字节输入流,并读取客户端信息
is=socket.getInputStream();
//将字节流装换为字符流,好处是提高读取的效率isr=new InputStreamReader(is);
//5.搭配使用,为字符输入流添加缓冲
br=new BufferedReader(isr);
//6.定义String类型的info,循环读取客户端信息并在控制台输出
String info=null;while ((info=br.readLine())!=null) {
System.out.println("服务器端接收到客户端数据为:"+info);
}//7.关闭socket输入流
socket.shutdownInput();
//8.获取输出流,响应客户端的请求os =socket.getOutputStream();
//将字节输出流转换为打印输出流
pw=new PrintWriter(os);
//服务器端向客户端发送响应信息
pw.write("登录成功,欢迎你");
//调用flush()方法刷新缓存
pw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//如果为空,关闭资源
if (pw!=null)
pw.close();
if(os!=null)os.close();
if(br!=null)br.close();
if (isr!=null) isr.close();
if(is!=null)is.close();
if(socket!=null)socket.close();
} catch (Exception e2) {
}
}}
}
​

服务器端代码修改为,如下:

package com.youdian.singinscoket;
​
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
​
/**** 基于TCP协议的Socket,实现用户登录* 服务器端* @author hkq**/
public class Servert {public static void main(String[] args) {try {//1.创建一个服务器端的Socket,即ServerSocket,指定绑定的端口,并监听此端口ServerSocket serverSocket=new ServerSocket(8088);Socket socket=null;int count=0;System.out.println("服务器端启动,等待客户端连接");//使用一个死循环监听while(true) {//调用accept()方法开始监听,等待客户端的连接socket= serverSocket.accept();//创建一个新的线程ServerThread serverThread=new ServerThread(socket);//启动线程serverThread.start();count++;//统计客户端数量System.out.println("当前连接客户端数量:"+count);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}
​}
​
}
​

客户端不变,多创建一个客户端类

package com.youdian.singinscoket;
​
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
​
/**** 客户端* @author hkq**/
public class Client2 {
​public static void main(String[] args) {try {//1.创建客户端Socket,指定`服务器地址和端口Socket socket=new Socket("127.0.0.1", 8088);//2.连接建立后,通过获取字节输出流读取服务器发送信息OutputStream os =socket.getOutputStream();//将字节输出流转换为打印输出流PrintWriter pw=new PrintWriter(os);//向服务器端发送用户信息请求pw.write("用户名: root;密码:5618 ");//刷新缓存pw.flush();//关闭scoket的输出流socket.shutdownOutput();//获取输入流,并读取服务器端的响应信息InputStream is=socket.getInputStream();//将字节流装换为字符流,好处是提高读取的效率InputStreamReader isr=new InputStreamReader(is);//搭配使用,为字符输入流添加缓冲BufferedReader br=new BufferedReader(isr);//定义String类型的info,循环读取服务器信息响应并在控制台输出String info=null;while ((info=br.readLine())!=null) {System.out.println("客户端接收到服务器端数据为:"+info);  }//关闭所有资源br.close();is.close();pw.close();os.close();socket.close();} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}
​}
​
}
​

代码运行结果:

多线程改造完成,实现多客户端与服务器端通信...多线程的本质就是让程序运行占用的资源最优化处理

Java多线程实现多客户端的通信相关推荐

  1. java多线程:线程间的通信-生产者和消费者(三)

    在一个程序中,往往会通过多个线程协同来共同完成一项任务,线程间必然需要进行信息的传递,也即是进程间的通信,我们用生产者和消费者的例子来具体分析: 对于生产者和消费者之间的关系,他们都是针对同一资源的操 ...

  2. Java实现服务器和客户端简单通信

    Java中网络编程这一块有封装的类库,使用简单,了解原理可以教容易实现服务器和客户端的简单通信. 在编程之前,首先要需要对TCP/IP协议有一定的了解,需要知道Socket套接字的作用以及用法,这个可 ...

  3. python实现客户端之间的通信_基于Python的服务端多线程与多客户端的通信过程

    实现server服务端多线程程序,可以开启多个客户端,每个客户端都能实现向服务端发送数据的过程,可以设置最大监听客户端数. 服务端使用命令: python server.py 520 进行开启 其中s ...

  4. Java多线程(5)--线程通信wait和notify

    例题:使用两个线程打印 1-100.线程1, 线程2 交替打印. 解决:涉及wait()和notify()/notifyAll() class Communicate implements Runna ...

  5. java synoch 加锁_线程间通信 - HappyCowboy - 博客园

    线程之间需要一些协调通信,来共同完成一件任务.Java多线程中,线程之间通信最常用的两个方法是wait()与notify() 使用wait()与notify()实现线程间的通信,需注意: ①wait( ...

  6. Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四)

    java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一) java多线程同步以及线程间通信详解&消费者生产者模式&死锁 ...

  7. Java中利用socket实现简单的服务端与客户端的通信(中级)——实现任意双向通信

    本文计划采用socket实现客户端和服务端的任意双向通信,即客户端可以随时给服务端发消息,服务端也可以随时给客户端发消息,最终结果就是一个类似与QQ的聊天软件的功能. 以下代码可以直接拷贝到Eclip ...

  8. Java中利用socket实现简单的服务端与客户端的通信(基础级)

    在上一篇文章中,简单的介绍了java中入门级的socket编程,简单的实现了客户端像服务器端发送数据,服务器端将数据接收并显示在控制台,没有涉及多线程.上一篇文章的链接:Java中利用socket实现 ...

  9. Java 多线程(七) 线程间的通信

    Java 多线程(七) 线程间的通信--wait及notify方法 线程间的相互作用 线程间的相互作用:线程之间需要一些协调通信,来共同完成一件任务. Object类中相关的方法有两个notify方法 ...

最新文章

  1. Windows10安装Ubuntu子系统+docker教程说明
  2. cmake构建工具 初步01
  3. 程序员找 Bug 福音!微软全新开源查找修复 Bug 工具——Project OneFuzz
  4. 《DOM编程艺术》中CSS—DOM的总结(一)
  5. excel转word后表格超出页面_妙招!Word和Execl“联姻”实现数据高效处理!
  6. CRISC风险及信息系统监控认证
  7. 三种 Bitmap 之 Java BitSet
  8. c语言 long double 输出格式,c++ 什么是`long double`的格式说明符
  9. Kettle【实践 04】Java环境实现KJB和KTR脚本文件执行v9版本9.0.0.0-423相关依赖说明(云资源分享:依赖包+kjb+ktr+测试源码)
  10. 如何1秒内快速判断一个函数的凹凸性?还看不懂我给你赔钱
  11. UVM—virtual sequencer and virtual sequence详解
  12. 架构-分布式与集群的区别
  13. 【详解】标识符命名规则及命名规范
  14. 路径和(cdq分治)
  15. 5G无线网络智能规划技术的探索与实践
  16. Android实现新闻浏览功能
  17. Spring自动注入(引用类型)
  18. stem科学实验课关联
  19. 2022年,MCU市场有哪些趋势?
  20. 机器学习中的Logistic回归算法(LR)

热门文章

  1. jQuery性能优化指南(1)
  2. 判断sem信号量为零_kernel.sem信号量调优
  3. 佳点集java_java实现遗传算法实例分享(打印城市信息)
  4. openGauss Summit 2021云和恩墨分论坛即将开启
  5. 【连载】如何掌握openGauss数据库核心技术?秘诀三:拿捏存储技术(1)
  6. 2020 数据技术嘉年华:吹响国产数据库的集结号 诚邀参会览技术前沿
  7. 两万字深度介绍分布式系统原理!【收藏版】
  8. DBA 14条职业选择路线,你适合哪种?
  9. Oracle 12c 新特性:SQL Plan Directives与过量的动态采样解析
  10. 【推荐】 RAC 性能优化全攻略与经典案例剖析