TCP Socket API 讲解,以及回显服务器客户端的实现

文章目录

    • TCP
      • ServerSocket API
      • Socket API
    • TCP 客户端服务器的实现

TCP

ServerSocket API

ServerSocket 是创建TCP服务端 Socket 的 API。

serverSocket构造方法:

方法签名方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口

serverSocket方法:

方法签名方法说明
Socket accept()开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待
void close()关闭此套接字

Socket API

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端 Socket。

不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

Socket 构造方法:

方法签名方法说明
Socket (String host, int port)创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接

Socket 方法:

方法签名方法说明
InetAddress getInetAddress()返回套接字所连接的地址
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

TCP 客户端服务器的实现

因为 TCP 是面向连接的,所以TCP 服务器是需要多线程的,每个客户端连接都需要一个独立的线程来处理数据的收发和状态的维护,否则一个客户端的阻塞会影响其他客户端的正常通信。因此,TCP 服务器需要多线程来支持多个客户端的连接和通信

核心思路

  1. 服务器:

    • 首先给给这个服务器绑定一个端口号。(port:9090)

    • 启动服务器,利用 accept 方法建立与客户端的连接。

    • 建立线程池,后续操作在线程池中执行。

    • 接收客户端发送过来的请求。

    • 根据请求计算响应并发回,注意要添加一条“刷新缓冲区 (flush)”的操作。(回显服务器,响应值就是请求值)

    • 最后打印日志。

  2. 客户端:

    • 完成连接 TCP 服务器的操作。(ip: 127.0.0.1 , port: 9090)
    • 启动客户端,从控制台输入请求。
    • 把请求发送给服务器,同时还要加上刷新缓冲区 (flush) 的操作。
    • 最后读取服务器响应,并打印响应结果。
  3. 注意:

    因为 TCP 是字节流,所以利用 InputStream【Scanner】 和 OutputStream【PrintWriter】来读取或发送数据,由于InputStream 和 OutputStream 生命周期短,因此要及时 close(),这里我们用到 try-with-resources。

Java 打印流 PrintWriter 的介绍:PrintWriter 是 Java 中的一个字符类型的打印输出流,PrintWriter 可以将数据写入文件或其他输出流中,下面代码中用于 服务器向客户端发送数据/客户端向服务器发送数据

TCP 服务器的实现:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TcpEchoServer {private ServerSocket serverSocket = null;// 此处不应该创建固定线程数目的线程池.private ExecutorService service = Executors.newCachedThreadPool();// 这个操作就会绑定端口号public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}// 启动服务器public void start() throws IOException {System.out.println("服务器启动!");while (true) {// 这个写法, 是能自动关闭, 也行. 实现 Closeable 接口就可以这么写.// 这么写会有其他问题. (结合后面讲第二个问题, 再说这个事)Socket clientSocket = serverSocket.accept();// 使用线程池, 来解决上述问题service.submit(new Runnable() {@Overridepublic void run() {processConnection(clientSocket);}});}}// 通过这个方法来处理一个连接的逻辑.private void processConnection(Socket clientSocket) {System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());// 接下来就可以读取请求, 根据请求计算响应, 返回响应三步走了.// Socket 对象内部包含了两个字节流对象, 可以把这俩字节流对象获取到, 完成后续的读写工作try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 一次连接中, 可能会涉及到多次请求/响应while (true) {// 1. 读取请求并解析. 为了读取方便, 直接使用 Scanner.Scanner scanner = new Scanner(inputStream);if (!scanner.hasNext()) {// 读取完毕, 客户端下线.System.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());break;}// 这个代码暗含一个约定, 客户端发过来的请求, 得是文本数据, 同时, 还得带有空白符作为分割. (比如换行这种)String request = scanner.next();// 2. 根据请求计算响应String response = process(request);// 3. 把响应写回给客户端. 把 OutputStream 使用 PrinterWriter 包裹一下, 方便进行发数据.PrintWriter writer = new PrintWriter(outputStream);//    使用 PrintWriter 的 println 方法, 把响应返回给客户端.//    此处用 println, 而不是 print 就是为了在结尾加上 \n . 方便客户端读取响应, 使用 scanner.next 读取.writer.println(response);//    这里还需要加一个 "刷新缓冲区" 操作.writer.flush();// 日志, 打印当前的请求详情.System.out.printf("[%s:%d] req: %s, resp: %s\n", clientSocket.getInetAddress().toString(), clientSocket.getPort(), request, response);}} catch (IOException e) {e.printStackTrace();} finally {// 在 finally 中加上 close 操作, 确保当前 socket 被及时关闭!!try {clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9090);server.start();}
}

TCP 客户端代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {private Socket socket = null;// 要和服务器通信, 就需要先知道, 服务器所在的位置.public TcpEchoClient(String serverIp, int serverPort) throws IOException {// 这个 new 操作完成之后, 就完成了 tcp 连接的建立.socket = new Socket(serverIp, serverPort);}public void start() {System.out.println("客户端启动");Scanner scannerConsole = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {while (true) {// 1. 从控制台输入字符串.System.out.print("-> ");String request = scannerConsole.next();// 2. 把请求发送给服务器PrintWriter printWriter = new PrintWriter(outputStream);//    使用 println 带上换行. 后续服务器读取请求, 就可以使用 scanner.next 来获取了printWriter.println(request);//    不要忘记 flush, 确保数据是真的发送出去了!!printWriter.flush();// 3. 从服务器读取响应.Scanner scannerNetwork = new Scanner(inputStream);String response = scannerNetwork.next();// 4. 把响应打印出来System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);client.start();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/186967.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VUE2+THREE.JS 模型上方显示信息框/标签(CSS3DSprite精灵模型)

THREE.JS 模型上方显示信息框/标签---CSS3DSprite精灵模型 1.CSS2DRenderer/CSS3DRenderer/Sprite的优劣2.实现模型上方显示信息框2.1 引入2.2 初始化加载的时候就执行此方法2.3 animate循环执行2.4 获取设备状态并在每个设备上显示设备状态2.5 样式 CSS3DSprite精灵模型面向摄…

python中的函数定义

默认参数 注: 在Python中,print(x, and y both correct)是一条打印语句(print statement),用于将一条消息输出到控制台或终端。它的作用是将变量x的值和字符串and y both correct同时输出到屏幕上。 在这个语句中&…

【复杂网络建模】——基于代理的社会网络建模(Agent-Based Modeling,ABM)[Python实现]

目录 一、复杂网络建模方法 二、基于代理的社会网络建模实现及Python实现代码 一、复杂网络建模方法 复杂网络是一种由大量相互连接的元素(节点或顶点)组成的网络结构,这些连接通常是非常复杂和动态的。这些网络可以在各种领域中发现,包括社交网络、生物学系统、信息技术…

docker中的网络不通问题

前言 有时候在使用docker时,会莫名其妙docker内部与外网网络不通 docker与防火墙 docker内部的网络与宿主机的防火墙有千丝万缕的联系,docker启动的那一刻如果防火墙是启动的,docker内部与外部就会走防火墙转发策略,这个时候&a…

MySQL表连接详解:解析内连接与外连接的使用方法

在MySQL中,表连接是一种将两个或多个表中的行相关联的操作。这是通过在这些表之间共享一个或多个列的值来实现的。表连接通常用于从多个表中检索相关的数据。 有几种不同类型的表连接,其中两个常见的是内连接(INNER JOIN)和外连接…

Windows11如何让桌面图标的箭头消失(去掉快捷键箭头)

在Windows 11中,桌面图标的箭头是快捷方式图标的一个标志,用来表示该图标是一个指向文件、文件夹或程序的快捷方式。如果要隐藏这些箭头,你需要修改Windows注册表或使用第三方软件。 在此之前,我需要提醒你,修改注册表…

Android 滑动按钮(开关) SwitchCompat 自定义风格

原生的SwitchCompat控件如下图&#xff0c;不说不堪入目&#xff0c;也算是不敢恭维了。开个玩笑... 所以我们就需要对SwitchCompat进行自定义风格&#xff0c;效果如下图 代码如下 <androidx.appcompat.widget.SwitchCompatandroid:id"id/switch_compat"android:…

【Linux】第二十二站:文件(二)深入理解重定向

文章目录 一、重定向1.文件描述符对应的分配规则2.重定向的接口 二、再次实现myshell1.实现细节2.盘点文件与进程替换的一个细节3.代码 三、1号文件和2号文件的区别四、如何理解“一切皆文件&#xff1f;” 一、重定向 1.文件描述符对应的分配规则 我们先看如下代码 #includ…

《C++PrimerPlus》第9章 内存模型和名称空间

9.1 单独编译 Visual Studio中新建头文件和源代码 通过解决方案资源管理器&#xff0c;如图所示&#xff1a; 分成三部分的程序&#xff08;直角坐标转换为极坐标&#xff09; 头文件coordin.h #ifndef __COORDIN_H__ // 如果没有被定义过 #define __COORDIN_H__struct pola…

智能优化算法应用:基于平衡优化器算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于平衡优化器算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于平衡优化器算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.平衡优化器算法4.实验参数设定5.算法结果…

全志XR806基于FreeRTOS下部署竞技机器人先进模糊控制器

前言 很荣幸参与到由“极术社区和全志在线联合组织”举办的XR806开发板试用活动。本人热衷于各种的开发板的开发&#xff0c;同时更愿意将其实现到具体项目中。秉承以上原则&#xff0c;发现大家的重心都放在开发中的环境构建过程&#xff0c;缺少了不少实际应用场景的运用&am…

AIGC: 关于ChatGPT中API接口调用相关准备工作

ChatGPT之API接口相关 通过页面和GPT交流获取信息相比直接调用GPT的API而言是非常有限的 页面上的GPT是比较封闭的&#xff0c;而且只允许我们去输入文本的信息 我们需要借助GPT的API开发来激发AI工具的无限可能&#xff0c;实现更多个性化需求 1 &#xff09;使用API 使用A…

【LeetCode 0167】【数组】两数之和(2)

https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/ 题解 二分查找O(nlogn)&#xff1a;有序自然想到二分查找&#xff0c;从左往右迭代数组每个元素num&#xff0c;在后面剩下的数组元素中二分查找到target-num var twoSum function(numbers, target) {con…

JavaWeb 项目 厉不厉害你鸡哥

来源 源码&#xff1a; <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>一起打篮球嘛</…

【WebSocket】通信协议基于 node 的简单实践和心跳机制和断线重连的实现

前后端 WebSocket 连接 阮一峰大佬 WebSocket 技术博客 H5 中提供的 WebSocket 协议是基于 TCP 的全双工传输协议。它属于应用层协议&#xff0c;并复用 HTTP 的握手通道。它只需要一次握手就可以创建持久性的连接。 那么什么是全双工呢&#xff1f; 全双工是计算机网络中的…

聊聊接口最大并发处理数

文章目录 前言并发和并行并发&#xff08;Concurrency&#xff09;并行&#xff08;Parallelism&#xff09;思考一下 前言 生活在 2023 年的互联网时代下&#xff0c;又是在国内互联网越发内卷的背景下&#xff0c;相信大家面试找工作、网上学习查资料时都了解过互联网系统设…

如何计算数据泄露的成本

现在&#xff0c;几乎所有类型的组织每天都在发生企业 IT 网络遭到破坏的情况。它们是任何合规官员最担心的问题&#xff0c;并且找出更好的方法来防止它们或从中恢复是合规官员永远不会远离的想法。 但数据泄露的实际成本是多少&#xff1f;该数字从何而来&#xff1f;当您获…

考试复习

选择20道 填空10道 判断10道 简答4-5道 编程题2道 一、选择题 1.js中更改一个input框的值&#xff1a; <input ida type"text" value"123456"> 通过a.value改变他的值 方法&#xff1a; 在script标签中通过id获得该输入框对象&#xff0c;然…

纯净版ISO镜像下载大全(Windows、Linux、mac)

目录 一、前言介绍 前言必读 介绍 二、获取ISO镜像方式 &#xff08;一&#xff09;官方镜像下载 &#xff08;二&#xff09;获取下载方式 ps&#xff1a;回复的内容都是小写的 Windows操作系统 1.windows XP系统 2.Windows 7系统 3.Windows10系统 4.Windows11系…

Flutter应用程序的加固原理

在移动应用开发中&#xff0c;Flutter已经成为一种非常流行的技术选项&#xff0c;可以同时在Android和iOS平台上构建高性能、高质量的移动应用程序。但是&#xff0c;由于其跨平台特性&#xff0c;Flutter应用程序也面临着一些安全风险&#xff0c;例如反编译、代码泄露、数据…