-
Java连载127-多线程TCP网络编程
一、多线程的TCP网络编程
- 如果需要进行多次数据交互,就可以在程序中设置一个循环,不断向对方发送请求,即可完成多次数据交互。同样,如果需要让服务器同时响应多个客户端的请求,可以使用多线程的方法,也就是服务器端没接收到一个新的连接请求,就启动一个专门的线程与客户端进行交互。
- 本测试程序可以分为三类:客户端类、服务器类和逻辑线程类
- 首先是客户端类
package com.bjpowernode.java_learning; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; import java.util.Scanner; public class D127_1_ClientTest { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String input = null; Socket socket = null; DataInputStream in = null; DataOutputStream out = null; String serverIP = "127.0.0.1"; //服务器端IP int port = 5050; try { socket = new Socket(serverIP,port); //连接服务器 in = new DataInputStream(socket.getInputStream()); //创建输入流 out = new DataOutputStream(socket.getOutputStream());//创建输出流 System.out.println("请输入一个待计算的四则运算表达式"); while(scanner.hasNext()) { input = scanner.nextLine(); //从键盘输入一个待计算的四则运算表达式 if(!input.contentEquals("0")) { out.writeUTF(input); //向服务器发送运算请求 String result = in.readUTF(); //等待读取运算结果 System.out.println("服务器返回的计算结果:"+result); System.out.println("请输入一个正整数的四则运算表达式(输入0退出):"); }else { break; //请求结果 } } }catch(Exception e) { System.out.println("与服务器连接中断"); }finally { try { in.close(); //关闭网络连接 out.close(); socket.close(); System.out.println("连接结束"); }catch(Exception e) { } } } }
- 接下来是服务器端类
package com.bjpowernode.java_learning; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import com.bjpowernode.java_learning.D127_3_ThreadTest; public class D127_2_ServerTest { public static void main(String[] args) { ServerSocket server_socket = null; Socket socket = null; int port = 5050; while(true) { try { server_socket = new ServerSocket(port); System.out.println("服务器启动!"); }catch(IOException e1) { System.out.println("正在监听"); //ServerSocket对象不能重复创建 } try { System.out.println("等待客户请求!"); socket = server_socket.accept(); System.out.println("客户的地址:"+socket.getInetAddress() + ":" + socket.getPort()); }catch(IOException e) { System.out.println("正在等待客户"); } if(socket!=null) { new D127_3_ThreadTest(socket); //为每个客户启动一个专门的线程 } } } }
- 最后是逻辑线程类
package com.bjpowernode.java_learning; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; public class D127_3_ThreadTest extends Thread { Socket socket = null; DataInputStream in = null; DataOutputStream out = null; String str; String response; String ip; int port; public D127_3_ThreadTest(Socket socket) { this.socket = socket; start(); } public void run() { try { in = new DataInputStream(socket.getInputStream()); //创建输入流 out = new DataOutputStream(socket.getOutputStream()); //创建输出流 ip = socket.getInetAddress().getHostAddress(); //客户端IP地址 port = socket.getPort(); //客户端的端口号 while(true) { str = in.readUTF(); //获取客户端的表达式 System.out.println("客户端" + ip + ":" + port + "发送的请求内容:"); System.out.println(str+"=?"); if(str.contentEquals("0")) { System.out.println("连接结束"); break; }else { response = doComputer(str); //对表达式进行计算 out.writeUTF(response); //响应计算结果 } } }catch(Exception e) { System.out.println("连接结束"); }finally { try { in.close(); out.close(); socket.close(); }catch(Exception e) { } } } public String doComputer(String str) { String input; String[] sym; String[] data; int a=0,b=0,result=0; input = str; data = input.split("\\D+"); sym = input.split("\\d+"); a = Integer.parseInt(data[0]); b = Integer.parseInt(data[1]); try { switch(sym[1]) { case "+": result = a + b; break; case "-": result = a - b; break; case "*": result = a * b; break; case "/": result = a / b; } System.out.println("计算结果:"+input+"="+result); return String.valueOf(result); }catch(java.lang.ArithmeticException e) { System.out.println("数据错误!"); return "数据错误"; } } }
- 这样我们就做完了所有的工作,那么接下来进行启动该项目
-
首先启动服务器的类,运行结果如下:
-
然后启动客户端类
-
我们在客户端类中cosole界面输入
3*5
然后回车
-
从上面的运行结果来看,得到了我们想要的结果,那么接下来输入
0
来结束这个项目的运行
总结:在编写代码过程中我们遇到的问题,或者以前忘记的知识点:
1.服务器端类中:
(1)server_socket.accept() 一直处于阻塞直到接收了socket发来的请求,并返回一个socket对象;
(2)写一了一个多线程类,来给每个客户一个线程;
2.客户端类 \ (1)DataInputStream(socket.getInputStream()) \ socket的成员方法来获取输入流,并返回一个InputStream对象,然后经过java.io.DataInputStream方法转换为专有的流。
(2)DataOutputStream对象.writeUTF(String result) 用于传入字符串
(3)DataInputStream对象.readUTF() 用于读取字符串
3.多线程类
(1) 多线程重写了run方法
(2) 客户端和服务器端的读和写是正相反的。
二、源码:
-
- D127_1_ClientTest.java
- D127_2_ServerTest.java
- D127_3_ThreadTest.java
- https://github.com/ruigege66/Java/blob/master/D127_1_ClientTest.java
- https://github.com/ruigege66/Java/blob/master/D127_2_ServerTest.java
- https://github.com/ruigege66/Java/blob/master/D127_3_ThreadTest.java
- 出 处:https://www.cnblogs.com/ruigege0000/p/13245779.html
最新更新
带有参数的装饰器
类装饰器
django中的auth模块与admin后台管理
python的日期处理
字符串常用方法
基本数据类型概述
python-map()函数基本用法
python带你实现任意下载AcFun视频数据~
bbs项目之注册功能
变量的定义和使用
三大常用数据库事务详解之三:事务运行
三大常用关系型数据库事务详解之二:基
三大关系型数据库事务详解之一:基本概
MongoDB常用命令(2)
MongoDB基本介绍与安装(1)
SQLServer触发器调用JavaWeb接口
SQL Server索引的原理深入解析
SqlServer2016模糊匹配的三种方式及效率问题
SQL中Truncate的用法
sqlserver 多表关联时在where语句中慎用tri
VB.NET中如何快速访问注册表
ASP.NET中图象处理过程详解
Vue(1)Vue安装与使用
JavaScript 语言入门
js将一段字符串的首字母转成大写
纯原生html编写的h5视频播放器
H5仿原生app短信验证码vue2.0组件附源码地
TypeScript(4)接口
TypeScript(3)基础类型
TypeScript(2)WebStorm自动编译TypeScript配置