文章目录

  • TCP通信
    • 快速入门(一发一收)
      • 编写客户端代码
      • 编写服务器代码
    • 多发多收
    • 多发多收(同时接受多个客户端)
    • 线程池优化

TCP通信

快速入门(一发一收)

TCP协议回顾:

TCP是一种面向连接,安全、可靠的传输数据的协议

传输前,采用“三次握手”方式,点对点通信,是可靠的

在连接中可进行大数据量的传输

TCP通信模式:

在java中只要是使用java.net.Socket类实现通信,底层即是使用了TCP协议

编写客户端代码

Socket(客户端):

构造器 说明
Socket(String host , int port) 创建发送端的Socket对象与服务端连接,参数为服务端程序的ip和端口。

Socket类成员方法:

方法 说明
OutputStream getOutputStream() 获得字节输出流对象
InputStream getInputStream() 获得字节输入流对象

客户端实现步骤:

  • 创建客户端的Socket对象,请求与服务端的连接。
  • 使用socket对象调用getOutputStream()方法得到字节输出流。
  • 使用字节输出流完成数据的发送。
  • 不建议直接关闭socket管道释放资源, 一般用户退出时才会关闭。
/**客户端*/
public class ClientDemo {public static void main(String[] args) {try {// 1. 创建socket通信管道请求与服务端进行连接/**参数一: 服务器IP地址参数二: 服务器端口号*/Socket socket = new Socket("127.0.0.1", 7777);// 2. 从socket通信管道中获取到字节输出流OutputStream os = socket.getOutputStream();// 包裹低级字节输出流为字节打印流PrintStream ps = new PrintStream(os);// 3. 打印流发送消息ps.println("我是TCP的客户端");ps.flush(); // 刷新} catch (Exception e) {e.printStackTrace();}}
}

编写服务器代码

ServerSocket(服务端):

构造器 说明
ServerSocket(int port) 注册服务端端口

ServerSocket类成员方法:

方法 说明
Socket accept() 等待接收客户端的Socket通信连接
连接成功返回Socket对象与客户端建立端到端通信

服务端实现步骤:

  • 创建ServerSocket对象,注册服务端端口。
  • 调用ServerSocket对象的accept()方法,等待客户端的连接,并得到Socket管道对象。
  • 通过Socket对象调用getInputStream()方法得到字节输入流、完成数据的接收。
  • 不建议直接关闭socket管道释放资源, 一般用户退出时才会关闭。
/**服务器*/
public class ServerDemo {public static void main(String[] args) {try {// 1. 创建ServerSocket对象注册服务器端口ServerSocket serverSocket = new ServerSocket(7777);// 2. 调用accept方法, 等待客户端连接, 连接成功返回socket管道对象Socket socket = serverSocket.accept();// 3. 从socket管道中获取字节输入流, 完成数据接受InputStream is = socket.getInputStream();// 把字节输入流包装为缓冲字符输入流进行消息接收BufferedReader br = new BufferedReader(new InputStreamReader(is));// 按照行读取String message;if ((message = br.readLine()) != null) {System.out.println(message);}} catch (Exception e) {e.printStackTrace();}}
}

多发多收

需求

  • 使用TCP通信方式实现:多发多收消息。

具体要求

  • 可以使用死循环控制服务端收完消息继续等待接收下一个消息。
  • 客户端也可以使用死循环等待用户不断输入消息。
  • 客户端一旦输入了exit,则关闭客户端程序,并释放资源。

客户端

/**客户端*/
public class ClientDemo {public static void main(String[] args) {try {Socket socket = new Socket("127.0.0.1", 7777);OutputStream os = socket.getOutputStream();PrintStream ps = new PrintStream(os);// 客户端使用死循环等待用户不断地输入消息Scanner scanner = new Scanner(System.in);while (true) {System.out.println("发送消息: ");String inp = scanner.nextLine();// 一旦输入了exit,则关闭客户端程序,并释放资源if (inp.equals("exit")) {System.out.println("下线成功");ps.close();break;}ps.println(inp);ps.flush();}} catch (Exception e) {e.printStackTrace();}}
}

服务端

/**服务器*/
public class ServerDemo {public static void main(String[] args) {try {ServerSocket serverSocket = new ServerSocket(7777);Socket socket = serverSocket.accept();InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));String message;// 死循环控制服务端收完消息继续等待接收下一个消息while ((message = br.readLine()) != null) {System.out.println("收到消息: " + message);}} catch (Exception e) {e.printStackTrace();}}
}

多发多收(同时接受多个客户端)

思考: 案例实现了多发多收,那么是否可以同时接收多个客户端的消息?

不可以的。

因为服务端现在只有一个线程,只能与一个客户端进行通信; 并且上面代码中, 我们只连接了一个客户端然后就在死循环接受消息。

那么如何才可以让服务端可以处理多个客户端的通信需求

引入多线程。

同时处理多个客户端消息实现架构如下:

主线程死循环不断地接收socket链接, 每成功链接一个socket, 就交给子线程处理

实现步骤如下:

优化服务器代码即可

创建一个线程类, 用来处理接收消息

public class ServerReaderThread extends Thread {private Socket socket;public ServerReaderThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));String message;// 死循环控制服务端收完消息继续等待接收下一个消息while ((message = br.readLine()) != null) {System.out.println("收到消息: " + message);}} catch (Exception e) {e.printStackTrace();}}
}

在服务器主线程中, 每链接到一个socket都要创建一个线程类交给子线程处理

/**服务器*/
public class ServerDemo {public static void main(String[] args) {try {ServerSocket serverSocket = new ServerSocket(7777);// 1. 主线程中定义一个死循环由主线程不断地接收客户端socket管道连接while (true) {// 2. 每接收到一个socket管道, 都交给一个独立的子线程负责读取消息Socket socket = serverSocket.accept();// 交给子线程处理, 并启动子线程new ServerReaderThread(socket).start();}} catch (Exception e) {e.printStackTrace();}}
}

线程池优化

目前的通信架构存在什么问题

客户端与服务端的线程模型是: 1-1的关系, 有多少客户端就会创建多少线程。

客户端并发越多,系统瘫痪的越快。

引入线程池处理多个客户端消息的架构如下:

线程池优化多发多收, 我们只需要优化服务器的代码即可:

创建一个Runnable任务类

public class ServerReaderRunnable implements Runnable {private Socket socket;public ServerReaderRunnable(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));String message;// 死循环控制服务端收完消息继续等待接收下一个消息while ((message = br.readLine()) != null) {System.out.println(socket.getRemoteSocketAddress() + "收到消息: " + message);}} catch (Exception e) {e.printStackTrace();}}
}

优化服务器端代码

/**服务器*/
public class ServerDemo {// 使用静态变量记录一个线程池对象private static ExecutorService pool = new ThreadPoolExecutor(3, 5, 6,TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());public static void main(String[] args) {try {ServerSocket serverSocket = new ServerSocket(7777);while (true) {Socket socket = serverSocket.accept();System.out.println(socket.getRemoteSocketAddress() + "上线了");// 创建Runnable任务交给线程池处理pool.execute(new ServerReaderRunnable(socket));}} catch (Exception e) {e.printStackTrace();}}
}

线程池优势是什么?

服务端可以复用线程处理多个客户端,可以避免系统瘫痪。

适合客户端通信时长较短的场景。
计思想, 客户端将消息发送给服务器, 再由服务器进行转发给其他客户端。

Java网络编程 - TCP通信相关推荐

  1. Java网络编程---TCP通信

    TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信 Java对基于TCP协议的 ...

  2. Java网络编程 ---- TCP 网络通信编程

    视频:[零基础 快速学Java]韩顺平 零基础30天学会Java 文章目录 1. Socket 2. TCP 网络通信编程 3. 应用案例 1(使用字节流) 4. 应用案例 2(使用字节流) 5. 应 ...

  3. java网络编程的通信原理_11 - 网络编程之设备间通信原理

    一.网络编程 1表现形式:一台机子上的应用程序和另外一个设备的程序之间能够互相交换数据. 2 7层网络结构 硬件层:解决硬件连接问题 数据链路层:解决硬件之间能够向指定设备传输数据 IP:为设备提供一 ...

  4. qt tcp通信_Qt之网络编程TCP通信

    点击上方"Qt学视觉",选择"星标"公众号重磅干货,第一时间送达 想要学习的同学们还请认真阅读每篇文章,相信你一定会有所收获 TCP通信概述 TCP(Trans ...

  5. java网络编程TCP传输—流操作—拿到源后的写入动作

    在网络编程中的TCP传输里,拿到Socket的源后,应该怎么进行读写操作呢,下面我列举了两种方法,希望大家帮忙补充···· 1.利用byte数组作为一个缓冲区进行读写 客户端上传 1 //获取sock ...

  6. java网络编程--TCP程序设计

    一,本章目标 了解Socket和ServerSocker类的作用 掌握ECHO程序开发 将多线程应用在TCP程序上实现多用户操作 二,具体内容 在java网络程序中,客户端只要符合连接的通讯协议,那么 ...

  7. java网络编程 TCP程序

    在java中,使用Socket完成TCP(传输控制协议)程序开发,使用此类可以方便地建立可靠的,双向的,持续的,点对点通信连接 服务端: ServerSocket    程序段:Socket Serv ...

  8. 网络编程——TCP通信

    代码 TCP服务端 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #includ ...

  9. 2.Java 网络编程TCP通讯例子 双向发送

    在上篇例子中,存在缺陷 只能允许Client给Server发消息,Server无法发消息给Client端 Client连接成功之后,Server就关闭了 这篇完善上篇的例子 TCP服务端 import ...

最新文章

  1. 2021-01-24过去十年十大AI研究热点,分别为深度神经网络、特征抽取、图像分类、目标检测、语义分割、表示学习、生成对抗网络、语义网络、协同过滤和机器翻译。
  2. 【网上的都不靠谱?还是得改源码】用Javasisst的字节码插桩技术,彻底解决Gson转Map时,Int变成double问题...
  3. FEC之异或运算应用
  4. 2018年4月1日 蓝桥杯 C/C++B组答案 明码
  5. 简单区分Vmware的三种网络连接模式(bridged、NAT、host-only)
  6. jdk自带常用命令行工具使用
  7. 数据链路层中的LLC
  8. 双用户windows linux系统,Windows与Linux合二为一?终于能在windows上运行Linux了!
  9. C语言中的正负数及其输出
  10. 抄底王牌tdx 副图(无未來函数)
  11. python之七行代码制作GIF动画
  12. VOSviewer使用方法(详细便捷)附下载网址
  13. AI上推荐 之 FM和FFM(九九归一)
  14. 求解字谜游戏java_有趣的字谜游戏,一起来解锁答案吧!
  15. Gmail邮箱登陆问题解决方案
  16. 黄冈市2021高考成绩查询系统,黄冈师范学院
  17. 2015年3月CCF软考试题
  18. 互联网公司对Android,iOS开发工程师的职位要求
  19. Velodyne激光雷达使用教程
  20. python画魄罗代码_LOL:灵魂画师在这里!玩家手绘冰雪节魄罗

热门文章

  1. 自然语言处理知识抽取(pkuseg、DDParser安装及使用)
  2. 养猫人士必备App——Catbook
  3. 使用python定时更换桌面壁纸
  4. FME进阶视频教程: FME常用转换器之坐标系操作类,讲解在FME中如何操作矢量数据的坐标系
  5. 837计算机考研科目,2017年中南财经政法大学837软件设计综合考研初试自命题考试科目大纲...
  6. 意法半导体MCU微控制器技术突破在哪?
  7. SpringBoot入门(一)
  8. 31道Android面试题,面试官6个灵魂拷问,快来收藏!
  9. HR必看!2023年人资工作7大趋势,带你超前部署人才战略
  10. 小鸡对话软件测试简历,鸡蛋、小鸡、凤凰心理测试游戏